Wednesday, July 20, 2011

[Windows]windbg kernel debugging

debugging virtual machine using windbg:
http://www.ndis.com/ndis-debugging/virtual/vmwaresetup.htm


    Steps:
  1. (One time) On host machine, install WinDbg
  2. On the target machine (i.e., the VM running on HyperV), ran following in cmd:
    bcdedit -debug on
    bcdedit -dbgsettings serial debugport:1 baudrate:115200
  3. In HyperV’s control panel, open the settings for the VM.  Under COM1, add a Named Pipe called “MyVIrtualCom1”.
  4. Create a shortcut for windbg on host machine, make it run as administrator (otherwise, you can not access the com). The command to run windbg is something like:
  5. C:\Debuggers\windbg.exe -y SRV*C:\symbols*http://msdl.microsoft.com/download/symbols -k com:port=\\.\pipe\MyVirtualCom1,pipe,resets=0,reconnect

Thursday, July 14, 2011

dumpbin: 查看binary文件所需要的symbols
VC自带的工具.
dumpbin /imports foo.sys

Friday, June 17, 2011

[Windows]dbg

cheating sheet ntsd: user mode debugger
kd: kernel mode debugger
windbg: GUI wrapp for ntsd and kd

最基本命令
.hh: 查看help
k: show call stack
r: show register
Q: quit dbg
bp: set breakpoint
  • bp foo!main
  • bp `source.c:31`
  • ba: set data breakpoint

p: step
pc: step to next call


kb: Dump the stack with Params
kn: Dump the stack with Frame #
kd: Dump stack dissassembly
~#s: Change to thread (Example: ~3s)
dd # - Dump the data (Example: dd 01f056548)
bl: list breakpoints
bd: disable breakpoint
bc: remove breakpoint
lm: system modules
x foo!*: 查看所有module foo的symbol
.sympath: 查看当前sympath
!sympath+“\\your_computer\path\to\your\pdb”: 添加路径到sympath中
!sym noisy/quiet: Generate verbose output from symbol loader
.srcpath: 查看当前srcpath
!srcpath+"\\your_computer\path\to\your\pdb": 添加路径到srcpath中



Kernel Mode Extension
!symfix: 碰到说nt symbols are incorrect please fix的时候运行
!reload: 重新读入symbols 包括kernel symbols, private symbols, user symbols.
!reload foo.sys: 重新读入foo.sys这个driver的symbols
!process: 查看所有进程
!process 0 0 myprocess.exe: 查看叫myprocess.exe的进程
!thread: 查看所有线程
!driveinfo: 驱动信息
!irp: IRP
!irpfind


读取symbol
!symfix
!reload
Connected to Windows 7 7601 x64 target at (Tue Jun 21 13:22:28.221 2011 (UTC - 7:00)), ptr64 TRUE
Loading Kernel Symbols
...............................................................
................................................................
............................
Loading User Symbols
................................................................
.........................
Loading unloaded module list
..........
显示driver object (比如kbdclass)
!drvobj kbdclass
Driver object (fffffa8007370870) is for:
 \Driver\kbdclass
Driver Extension List: (id , addr)
显示driver object (比如kbdclass)的dispatch routines
!drvobj kbdclass 7
Driver object (fffffa8007370870) is for:
 \Driver\kbdclass
Driver Extension List: (id , addr)

Device Object list:
fffffa8007a31ce0  fffffa800743d6c0  

DriverEntry:   fffff8800440becc kbdclass!GsDriverEntry
DriverStartIo: 00000000 
DriverUnload:  00000000 
AddDevice:     fffff880044083b4 kbdclass!KeyboardAddDevice

Dispatch routines:
[00] IRP_MJ_CREATE                      fffff88004401dd4 kbdclass!KeyboardClassCreate
[01] IRP_MJ_CREATE_NAMED_PIPE           fffff800034b58ac nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE                       fffff8800440217c kbdclass!KeyboardClassClose
[03] IRP_MJ_READ                        fffff88004402804 kbdclass!KeyboardClassRead
[04] IRP_MJ_WRITE                       fffff800034b58ac nt!IopInvalidDeviceRequest
[05] IRP_MJ_QUERY_INFORMATION           fffff800034b58ac nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION             fffff800034b58ac nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA                    fffff800034b58ac nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA                      fffff800034b58ac nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS               fffff88004401ce0 kbdclass!KeyboardClassFlush
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff800034b58ac nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff800034b58ac nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL           fffff800034b58ac nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff800034b58ac nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL              fffff88004408a40 kbdclass!KeyboardClassDeviceControl
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff880044082b4 kbdclass!KeyboardClassPassThrough
[10] IRP_MJ_SHUTDOWN                    fffff800034b58ac nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL                fffff800034b58ac nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP                     fffff88004401afc kbdclass!KeyboardClassCleanup
[13] IRP_MJ_CREATE_MAILSLOT             fffff800034b58ac nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY              fffff800034b58ac nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY                fffff800034b58ac nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER                       fffff88004409fd4 kbdclass!KeyboardClassPower
[17] IRP_MJ_SYSTEM_CONTROL              fffff8800440a364 kbdclass!KeyboardClassSystemControl
[18] IRP_MJ_DEVICE_CHANGE               fffff800034b58ac nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA                 fffff800034b58ac nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA                   fffff800034b58ac nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP                         fffff88004403368 kbdclass!KeyboardPnP

列出当前所有irp
!irpfind

Scanning large pool allocation table for Tag: Irp? (fffffa8005481000 : fffffa8005781000)

  Irp    [ Thread ] irpStack: (Mj,Mn)   DevObj  [Driver]         MDL Process
fffffa8007375930 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3)
fffffa8004f19520 [00000000] Irp is complete (CurrentLocation 2 > StackCount 1) 0x0000000000000000
fffffa8007dcfe10 [fffffa80081438f0] irpStack: ( e,2d)  fffffa8006e6eb10 [ \Driver\AFD]
fffffa8007ecdbc0 [fffffa80088a9b60] irpStack: ( e, 0)  fffffa8006aa4da0 [ \Driver\Beep]
...

特别查看某个irp (比如地址是fffffa8007dcfe10的这个)
!irp fffffa8007dcfe10
Irp is active with 4 stacks 4 is current (= 0xfffffa8007dcffb8)
 No Mdl: System buffer=fffffa8008dc7d80: Thread fffffa80081438f0:  Irp stack trace.  
     cmd  flg cl Device   File     Completion-Context
 [  0, 0]   0  0 00000000 00000000 00000000-00000000    

   Args: 00000000 00000000 00000000 00000000
 [  0, 0]   0  0 00000000 00000000 00000000-00000000    

   Args: 00000000 00000000 00000000 00000000
 [  0, 0]   0  0 00000000 00000000 00000000-00000000    

   Args: 00000000 00000000 00000000 00000000
>[  e,2d]   5  1 fffffa8006e6eb10 fffffa80086bfa30 00000000-00000000    pending
        \Driver\AFD
   Args: fffffa80081844b0 fffffa80081844b0 fffff88003f03150 fffffa8007ecf810
最后一行显示出这个irp的major function是e 也就是IRP_MJ_DEVICE_CONTROL

查看namespace里\Driver里的内容:
!object \Driver
Object: fffff8a00008b7f0  Type: (fffffa8004e83a90) Directory
    ObjectHeader: fffff8a00008b7c0 (new version)
    HandleCount: 0  PointerCount: 107
    Directory Object: fffff8a000004dc0  Name: Driver

    Hash Address          Type          Name
    ---- -------          ----          ----
     00  fffffa8006fbae70 Driver        nvlddmkm
         fffffa80069eae70 Driver        fvevol
         fffffa8005d2e890 Driver        iaStorV
...

查看_DRIVER_OBJECT的结构
dt nt!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x008 DeviceObject     : Ptr64 _DEVICE_OBJECT
   +0x010 Flags            : Uint4B
   +0x018 DriverStart      : Ptr64 Void
   +0x020 DriverSize       : Uint4B
   +0x028 DriverSection    : Ptr64 Void
   +0x030 DriverExtension  : Ptr64 _DRIVER_EXTENSION
   +0x038 DriverName       : _UNICODE_STRING
   +0x048 HardwareDatabase : Ptr64 _UNICODE_STRING
   +0x050 FastIoDispatch   : Ptr64 _FAST_IO_DISPATCH
   +0x058 DriverInit       : Ptr64     long 
   +0x060 DriverStartIo    : Ptr64     void 
   +0x068 DriverUnload     : Ptr64     void 
   +0x070 MajorFunction    : [28] Ptr64     long 

Tuesday, June 14, 2011

[Windows]cmd命令笔记

删除一个文件夹foo所有内容
rd foo /s

查看当前所有进程(类似ps)
tasklist

杀死一个进程(类似kill)
taskkill

查找文件中出现的字符串
findstr

5秒内关机并重启
shutdown -r -t 5

Monday, June 13, 2011

[Winodws]内核驱动笔记

占坑
背景知识

用户模式(User Mode):
内核模式(Kernel Mode):
Win32 API:

C++注意事项

微软官方的文档C++ for Kernel Mode Drivers: Pros and Cons
求摘要?看这里Advanced C++ features and Kernel-mode programming don't mix


cmd或者在(Start->Run)运行msinfo32,然后选"software environment"->"system drivers"可以看到当前系统里所有安装了的驱动

编译

source文件相当于Linux/Unix下的Makefile. 如何写一个source文件? 参见http://randomlearningnotes.wordpress.com/2009/04/20/using-wdkddk-build-environment-for-drivers-and-non-drivers/

build 命令相当于Linux/Unix下的make

build /c 把所有obj文件全部删除再编译

build的output很少, 详细信息可以参见编译时生成的.log,.wrn和.err文件

disable所有编译优化: 在source 文件中加设置环境变量
MSC_OPTIMIZATION=/Od /Oi

debugview是一个可以用来查看kernel debug输出信息的工具. 可以connect到local machine来查看本机的, 也可以连接到remote机器上. 后者的方法是先在remote的机器上运行debugview /c, 接着使用debugview在local机器上

常用API

信号量
KeWaitForSingleObject 阻塞当前线程直至信号变量(比如一个event object)被置成signaled
KeSetEvent 把一个event object设为signaled
KeResetEvent 把一个event object重置成not-signaled

文件操作:
ZwReadFile: Read data from the file.
ZwWriteFile: Write data to the file.
ZwQueryInformationFile: Read metadata for the file or file handle.
ZwSetInformationFile: Write metadata for the file or file handle.

Saturday, May 28, 2011

Ubuntu添加删除ppa

添加一个ppa是一件很容易的事情, 比如添加ppa:ubuntu-toolchain-r/test(可以在11.04上装gcc-4.6)
$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test
更新仓库软件列表
$ sudo apt-get update 

删除一个ppa并rollback到稳定版本稍微麻烦一些,需要下一个叫ppa-purge的工具先
$ sudo apt-get install ppa-purge
删除刚才添加的ppa
$ sudo ppa-purge ppa:ubuntu-toolchain-r/test
然后会自动帮你downgrade或者remove软件.

Wednesday, May 25, 2011

关于uint64_t(64位整数)的一些操作

显示

#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t a = 90;
  printf("test uint64_t : %" PRIu64 "\n", a);
  return 0;
}
如果是使用C++编译器编译上述代码,有时候会报如下错误
main.cpp: In function ‘int main()’:
main.cpp:9:30: error: expected ‘)’ before ‘PRIu64’
main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]
解决方法是在inttypes.h这个头文件前加上一个__STDC_FORMAT_MACROS宏定义
#define __STDC_FORMAT_MACROS
#include <inttypes.h>

左移

对于32bit或者更短的的integer, 1左移x位就是 1≤≤x
但是对于64bit的integer, 比如unsigned long long或者uint64_t, 1≤≤32却是0. 如果需要2^32或者更大的数, 需要用1ULL≤≤32

http://cboard.cprogramming.com/c-programming/62790-bitshift-64-bit-integers.html

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main( void )
{
   uint64_t a = 1ULL << 32;
   uint64_t b = 1 << 32;
   printf( "a = %016"PRIx64", b = %016"PRIx64"\n",  a, b);
   return 0;
}
a = 0000000100000000, b = 0000000000000000

Friday, May 20, 2011

[Linux/Mac]编译相关的工具和命令

GNU make的常用变量

  • CFLAGS: C compiler的flags,会被传递给关于C代码的compile和link的命令
  • CXXFLAGS: C++ compiler的flags,会被传递给关于C++的compile和link的命令
  • CPPFLAGS: C PreProcessor的flags(注意,不要和CXXFLAGS混淆)。它会被传递给编译C以及C++代码的命令
  • LDFLAGS: linking阶段的选项。常用来指定一些库文件的位置 比如"-L/usr/local/Cellar/gettext/0.18.1.1/lib"
  • CC: C Compiler。比如"gcc", "cc"
  • CXX: C++ Compiler。比如"g++"
参考:
http://stackoverflow.com/questions/495598/difference-between-cppflags-and-cxxflags-in-gnu-make

autoconf

根据configure.ac生成configure文件
$ autoconf configure.ac > configure
$ chmod +x configure
$ ./configure
参见A brief introduction to autoreconf
http://sourceware.org/autobook/autobook/autobook_toc.html#SEC_Contents

autoreconf

根据configure.ac, 会调用autoconf, autoheader, aclocal, automake, libtoolize, 以及autopoint等工具生成configure文件. 然后configure再根据Makefile.am生成Makefile
$ autoreconf -is
$ ./configure
$ make
参见Using autoreconf to Update configure Scripts

configure

增加额外的编译参数(比如默认的configure找不到某个包,就需要显式的告诉它路径)
Bash底下
$ LDFLAGS="-L/opt/local/lib" CXXFLAGS="-I/opt/local/include"\
 PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/" ./configure
或者csh底下
$ env LDFLAGS="-L/opt/local/lib" CXXFLAGS="-I/opt/local/include"\
 PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/" ./configure
configure的常用参数包括
  • --prefix: 通常默认为 "--prefix=/usr/local"
  • --enable-shared: build shared libraries,否定为"--enable-shared=no"或者"--disable-shared"
  • --enable-static: build static libraries,否定为"--enable-static=no"或者"--disable-static"

ldd

显示一个可执行文件或者一个shared library文件(.so文件)所dependent的其他.so文件
$ ldd a.out 
 linux-vdso.so.1 =>  (0x00007fff4c5ff000)
 libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f55df989000)
 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f55df5ea000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f55dfc3b000)

nm

查看一个obj文件的symbol table
$ nm mypair.o
000001c4 s EH_frame1
000001a5 s __GLOBAL__I_mypair.cc
00000254 s __GLOBAL__I_mypair.cc.eh
00000153 s __Z41__static_initialization_and_destruction_0ii
0000022c s __Z41__static_initialization_and_destruction_0ii.eh
         U __ZNKSs4sizeEv
         U __ZNKSsixEm
         U __ZNSt8ios_base4InitC1Ev
         U __ZNSt8ios_base4InitD1Ev
0000012c S __ZSt3minImERKT_S2_S2_
000001e0 S __ZSt3minImERKT_S2_S2_.eh
00000000 t __ZStL17__verify_groupingPKcmRKSs
00000204 s __ZStL17__verify_groupingPKcmRKSs.eh
000002a8 b __ZStL8__ioinit
         U ___cxa_atexit
         U ___dso_handle
         U ___gxx_personality_v0
00000104 t ___tcf_0
00000278 s ___tcf_0.eh

strip

减小一个可执行文件的size。代码体积变小后可能会对icache有帮助。代价是symbol table等帮助debug的信息会被移除。
$ strip a.out

pkg-config

pkg-config相当于一个数据库,用以维护系统中那些已经安装了的library。
比如你可以通过--modversion来查询某个library的版本
$ pkg-config --modversion openssl
0.9.8j
也可以用--cflags以及--libs查询在Makefile里使用一个library所需要使用的include的路径和其他选项。比如:
$ pkg-config --cflags thrift
-I/usr/local/include/thrift  
$ pkg-config --libs thrift  
-L/usr/local/lib -lthrift
pkg-config中的library数据库是通过搜索特定路径下的一系列xxx.pc文件来建立的。每个.pc文件对应一个library,包括了这个library的一些metadata。可以通过如下命令来查看当前数据库中包含了哪些library了。
$ pkg-config --list-all

Tuesday, May 17, 2011

Indefero

在Indefero上new了一个project之后, 想用git pull一个空的source tree下来.但是发现git总是报错
Cloning into hashfilter...
fatal: '/var/local/indefero/git/repositories/myproj.git' does not appear to be a git repository
fatal: The remote end hung up unexpectedly
折腾了很久, 后来发现原来Indefero上新建的project是没有repo的. 第一次使用的时候需要自己import.所以要在自己的目录里
git init
git add .
git commit -m "initial import"
git remote add origin git@a.b.c.d:yourproj.git
git push origin master
然后就可以在Indefero上看见自己的source tree了

Friday, May 13, 2011

Hash, Hash and Hash

(更新中)
Universal Hashing
A probability distribution H over hash functions from U to $\{1, \ldots, M\}$ is uni-
versal if for all x = y in U , we have
$$
Pr\{h(x) == h(y)\} \leq 1/M
$$

换言之当h是从H中随机选取,任何两个元素collide的概率不超过1/M.

(c,k)-Universal Hashing
$\{h_i\} h_i : U \to R$, for any distinct elements $x_1,\ldots,x_k \in U$, and $y_1,\ldots,y_k \in R$, we have
$$
Pr\{h_i(x_1) = y_1,\ldots, h_i(x_k) =y_k\} \leq c/|R|^k
$$

Monday, May 09, 2011

[Linux]Ubuntu 11.04(Natty)上安装gcc-4.6

gcc-4.6没有进Natty默认的repo.
可以从ppa源里安装
https://launchpad.net/~ubuntu-toolchain-r/+archive/test

Sunday, May 08, 2011

[Linux]关于用户,组

增加用户foo
sudo adduser foo

把用户foo添加到group admin当中(这样foo就可以sudo)
sudo adduser foo admin

增加组bar
sudo addgroup bar

查看某个用户foo所属的组
groups foo

Saturday, May 07, 2011

[Linux]IRQ

中断请求IRQ
http://www.mjmwired.net/kernel/Documentation/IRQ.txt
IRQ是来自某个设备(比如NIC,Harddisk,SSD等)的请求,请求CPU给于处理
为了识别来自不同设备的IRQ, 每个中断来源都被分配了一个数字(也就是IRQ number).
在/proc/interrupts中记录了当前各种IRQ的number和它们的来源:
$cat /proc/interrupts
           CPU0       CPU1       
  0:        570          0   IO-APIC-edge      timer
  1:          2          0   IO-APIC-edge      i8042
  7:          0          0   IO-APIC-edge      parport0
  8:          1          0   IO-APIC-edge      rtc0
  9:          0          0   IO-APIC-fasteoi   acpi
 12:          4          0   IO-APIC-edge      i8042
 16:          0          0   IO-APIC-fasteoi   uhci_hcd:usb3
 17:          0          0   IO-APIC-fasteoi   uhci_hcd:usb4, uhci_hcd:usb6
 18:          0          0   IO-APIC-fasteoi   uhci_hcd:usb7
 20:    1104815          0   IO-APIC-fasteoi   ata_piix, ata_piix
 22:     187848          0   IO-APIC-fasteoi   ehci_hcd:usb1
 23:       1110          0   IO-APIC-fasteoi   ehci_hcd:usb2, uhci_hcd:usb5
 43:    4747272          0   PCI-MSI-edge      radeon
 44:      97360          0   PCI-MSI-edge      hda_intel
 45:    4284421          0   PCI-MSI-edge      eth0
NMI:          0          0   Non-maskable interrupts
LOC:   36071250   31250448   Local timer interrupts
SPU:          0          0   Spurious interrupts
PMI:          0          0   Performance monitoring interrupts
IWI:          0          0   IRQ work interrupts
RES:    1218335     677796   Rescheduling interrupts
CAL:       3889       6659   Function call interrupts
TLB:     137697     175959   TLB shootdowns
TRM:          0          0   Thermal event interrupts
THR:          0          0   Threshold APIC interrupts
MCE:          0          0   Machine check exceptions
MCP:        533        533   Machine check polls
ERR:          1
MIS:          0
比如这里可以看出,我的机器有两个CPU(其实是dual core)

IRQ SMP Affinity
http://www.cs.uwaterloo.ca/~brecht/servers/apic/SMP-affinity.txt


irqbalance
http://www.irqbalance.org/documentation.html

Thursday, May 05, 2011

[Linux]中文字体美化笔记

升级到Ubuntu 11.04之后, 突然中文设置全都混乱了.于是只好重新设置.笔记一下以免下次再出现.我主要是设置firefox和fontconfig的字体替换.

背景知识
有衬线(Serif) 无衬线 (Sans Serif)和等宽(Monospace)字型
  • 1 有衬线(Serif)字型是比较正式的字体,比划粗细不一,在笔划的边缘有装饰部分(我的理解是有笔锋)。英文当中比较有名的包括 Times New Roman, Georgia, 而中文当中则是包括大名鼎鼎的宋体,明体(繁体宋体在港台的叫法)。Serif font 的好处是看起来比较容易辨认,我自己觉得读起来速度会快。
  • 2 无衬线(Sans Serif)是比较活泼一些的字体,比划粗细一致。。英文当中包括Arial, Helvetica, Tahoma, Verdana等,而中文则是包括黑体,幼圆,仿宋好像也算是sans serif。要注意的是,这里的"黑体"有时会造成歧义,如要表达Bold的字体,可能粗体是更恰当。Sans Serif 的好处,据说字体小的时候看起来比较舒服。
  • 3 等宽(Monospace)字型顾名思义就是每个字母的宽度相同。通常显示代码的时候用等宽的字体会比较整齐. 另外命令行(Console)里面也用等宽字体比较好看。比较有名的是Courier。 我是Dejavu Sans Mono的忠实粉丝。

DPI
DPI=Dots per inch. 在显示器里可以理解为一英寸长要多少像素。Windows 以及Firefox (all platform)里的默认值为96。以前的话这个值是和大多数显示器差的不会太远。但是很多现在的显示器可以支持到更高(比如我的Macbook Pro的LCD就是110)。那么如果还设定DPI=96,相应的字体就会显小。所以可以首先确定自己系统里设定的DPI是否正确。

字体的单位
Font的大小分为pointsize(单位是pt磅)和pixelsize(单位是px像素).两者换算的关系可参考 http://www.emdpi.com/fontsize.html . 简单说来关于磅和像素这两个单位的换算关系是:1磅=1/72英寸,而1英寸= DPI 像素。 所以一个 X pt 的字,折合 X*DPI/72 px.
Linux系统里面容易混淆的地方是不同地方的设置用的不同的单位. 比如GNOME桌面设置字体的时候,单位是磅(pt)而而Firefox当中字体的设置用的是像素(px).

GNOME设置字体
首先在桌面右键->"Change Desktop Background"->"Font",会出现如下的面板

注意这里的单位是磅(pt)

Firefox设置字体
firefox设置起来很简单. 以Firefox 4为例, 在Edit->Preference->Content->Advanced 面板里, 选择是否允许使用网页指定的字体:
  • 如果你允许网页自己选择字体,则直接跳至fontconfig的设置. 我自己是这么选的---不然网页字体都那么千篇一律,多无聊阿).
  • 如果不允许网页自己指定的字体,则在对于中文(Simplified Chinese)字符集和西文(Western)字符集分别设置Serif, Sans Serif, Monospace三种字型的默认字体.这里字体大小的单位是px(像素),而不是pt(磅).

    但是有时候浏览器自己侦测的网页语言字符集是不对的, 或者有时候就是中文西文混合的(比如上facebook),这样就造成一个两难的局面: 网页语言detect错误时,以英文字体设置显示中文会很丑或者很虚. 如果干脆把浏览器的英文字体也都默认成中文--可是这样上英文网页就会崩溃因为几乎所有的中文字体的英文部分都太丑了.所以需要进行下一步,在fontconfig里做字体替换

fontconfig设置字体
设置fontconfig的作用在于你可以手动设置系统什么时候用什么中文字体.比如系统知道自己要显示一段Sans Serif的文字,英文部分好说,咣咣弄好了, 但是中文部分它不知道得用什么字体.于是你可以在fontconfig里设置,使得它可以用微软雅黑(Microsoft YaHei)来显示那部分中文,这就是字体替换.对自己账户的fontconfig设置在~/.fonts.conf中.
关于fontconfig设置的用法,参考http://linux.die.net/man/5/fonts-conf

这里附上我的~/.fonts.conf文件.
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="pattern">
    <test qual="any" name="family">
      <string>serif</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>Times New Roman</string>
      <string>Times</string>
      <string>Georgia</string>
      <string>Bitstream Vera Serif</string>
      <string>DejaVu Serif</string>
      <string>SimSun</string>
      <string>NSimSun</string>
      <string>Microsoft YaHei</string>
    </edit>
  </match> 
  <match target="pattern">
    <test qual="any" name="family">
      <string>sans-serif</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>DejaVu Sans</string>
      <string>Ubuntu</string>
      <string>Arial</string>
      <string>Helvetica</string>
      <string>Microsoft YaHei</string>
    </edit>
  </match> 
  <match target="pattern">
    <test qual="any" name="family">
      <string>monospace</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
      <string>DejaVu Sans Mono</string>
      <string>Courier</string>
      <string>Courier New</string>
      <string>Microsoft YaHei</string>
    </edit>
  </match> 
</fontconfig>
有几点说明:
1 因为宋体(比如SimSun, NSimSun)被认为是Serif, 所以我把他们放在了Serif里
2 黑体(比如Microsoft YaHei)是Sans Serif,所以放在了Sans Serif那类
3 因为所有中文字体大小都一样,所以Monospace那里随便用神马字体都可以, 我个人喜欢Microsoft YaHei

Tuesday, May 03, 2011

node.js 学习笔记

占坑先
node.js提供一种framework使得我么可以在server端运行的javascript 如果你是一个新手,务必请先读一下这篇Understand Node.js, 写的非常非常好. 参考
一个对于新手来说很不错的tutorial http://www.nodebeginner.org
Understand node.js event loop

使用minicom给firmware升级

接上串口以后, 在你的主机上运行
minicom
重启board, minicom的屏幕上会出现菜单
1......Program Flash via XModem Download
2......Version
3......Boot System
选择1 ,然后确认. 这时候出现
Erasing blocks ............

Start XModem dowmload...
这个时候先按几下回车,再接着按Ctrl-a s表示send文件, 然后出现如下的菜单来选择不同的protocol
+-[Upload]--+
| zmodem    |
| ymodem    |
| xmodem    |
| kermit    |
| ascii     |
+-----------+
选择xmodem,这时候会出现文件对话框,让你选择哪一个bin文件来升级BIOS. 选择之后, 我发现总是出现incomplete 或者根本就没有progress. 需要多send几次. 就可以了

Wednesday, April 27, 2011

[Linux] filesystem的几个命令

查看filesystem type

$ df -T
Filesystem    Type   1K-blocks      Used Available Use% Mounted on
10.103.0.1:/nfsroot
               nfs   230583296 137044992  81824768  63% /
none      devtmpfs      497684       220    497464   1% /dev
none         tmpfs      502108         0    502108   0% /dev/shm
tmpfs        tmpfs      502108         0    502108   0% /tmp
none         tmpfs      502108        48    502060   1% /var/run
none         tmpfs      502108         0    502108   0% /var/lock
none         tmpfs      502108         0    502108   0% /lib/init/rw
/dev/sda1     ext4   115377640    192116 109324612   1% /localfs

查看硬盘

sudo fdisk -l /dev/sda
Disk /dev/sda: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders, total 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000c821

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048      499711      248832   83  Linux
/dev/sda2          501758   976771071   488134657    5  Extended
/dev/sda5          501760   976771071   488134656   8e  Linux LVM

格式化硬盘

首先使用fdisk在硬盘上建立partition
$ sudo fdisk /dev/sda
然后格式化
$ sudo mkfs.ext4 /dev/sda1
mke2fs 1.41.11 (14-Mar-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
4890624 inodes, 19537040 blocks
976852 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
597 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
        4096000, 7962624, 11239424

Warning: could not read block 0: Attempt to read block from filesystem resulted in short read
Writing inode tables: 151/597
mount硬盘

$ sudo mount -t ext4 /dev/sda1 /my/mountpoint
$ sudo chown binfan:root /my/mountpoint
Ref
http://www.tldp.org/HOWTO/Partition/fdisk_partitioning.html

Sunday, April 17, 2011

关于diff, colordiff

diff常用于比较两个文件的不同:
diff path_to_file1 path_to_file2
可以用-y(或者--side-by-side)来分两列显示diff区别
diff --side-by-side path_to_file1 path_to_file2


diff还可以比较两个文件夹的不同,列出所有不同的文件的不同之处
diff -r path_to_dir1 path_to_dir2
还可以用-q(或者--brief)只显示哪些文件不同
diff --brief -r path_to_dir1 path_to_dir2


colordiff是diff的一个wrap,可以把diff的输出加上不同的色彩.所以通常能用diff的场合都可以放心的改成colordiff.也可以简单的在你的shell启动配置(比如.bashrc)里加上
alias diff=colordiff
关于colordiff的全局设置--比如什么输出配什么颜色--在/etc/colordiffrc当中.你可以把该文件拷贝至~/.colordiffrc然后自行修改.

如果希望svn diff使用colordiff(svn默认使用它自己内建的diff),修改~/.subversion/config文件,加上
diff-cmd = colordiff

Friday, April 15, 2011

[算法]关于字符串的算法

判断字符串的匹配(一个字符串是否在另一个字符串中出现):
KMP, 时间复杂度 线性, O(n)


找出k个字符串的最长公共子字符串(每个字符串长度不超过n):
使用suffix tree. 对于每个字符串建立一棵suffix tree的时间是线性O(n),合并这k棵suffix tree, 然后寻找合并过的大树中拥有属于所有string的最深的节点.


两个文件,各自拥有很多单词.寻找在两个文件中重复出现的单词:
可以用feed-forward bloom filter

Thursday, April 14, 2011

tmux: 更好的screen

tmux是什么?

tmux和screen和类似(关于screen的用法, 参见我写的screen小结).对我来说它比screen优越的地方是,它允许你在一个terminal上窗口上分割成多个tty,这样可以充分利用屏幕而不用来回切换. 比如下图:
你可以使用热键方便的在切割而成的不同的pane间切换.

怎么安装tmux?

Ubuntu下很简单
$sudo apt-get install tmux
在MacOS下可以用port
$sudo port install tmux

哪里有关于tmux的文档?

tmux官方主页
这个写得很赞: Tmux: a crash course
一个写的很好的tutorial:part1, part2
switching from gnu screen to tmux
http://wiki.frugalware.org/index.php/Tmux

tmux怎么使用?

和screen的比较:
功能 screen命令 tmux命令
查看当前session
$screen -ls
$tmux ls
$tmux list-sessions
重入的session
$screen -r
$screen -r session-name
$tmux attach
$tmux attach -t session-id
新建一个session,
执行一个shell命令(比如top)并立刻detach
$screen -m -d top
$screen -S session-name -m -d top
$tmux new-session -d top
发送指令(比如退出)到一个session中
$screen -X quit
$screen -S session-name -X quit
$tmux kill-session
$tmux kill-session -t session-id