momo zone

调核人的blog

Monthly Archives: 一月 2012

如何从oops或panic 中获得源代码

1. 最简单的

addr2line -f -e vmlinux 0xXXXXXXXX

2.使用crash 工具

这个功能就多了,启用方法是执行crash,增加模块到crash 环境:

mod -s <mod_name> <path/to/ko>

然后l *0xXXXXXXXXXXXXXXXX

如果是func+偏移的形式可以用这种 l *func+0xXXXXXXXXXXXXXXXX

另外几个比较强力的用法:

打印所有任务的堆栈:foreach bt -tf

打印结构定义,并配合地址参数显示结构中的成员变量: struct timespec xtime 左边是结构体定义,右边是结构体变量

根据符号名称显示原型 : whatis modules

遍历列表:list pdev2 -s mydev_s 左边是包含list的结构体变量,右边是需要遍历出来的结构体,(结构体定义)

打印:p , carsh 中的p 非常智能,如果参数是符号名称,他能够自动查找符号原型来格式化输出。

3. 使用gdb

gdb vmlinux /proc/kcore

对于内核模块,还要使用出自LDD3 P104的方法:

add-symbol-file <ko> 0xXXXXXXXX  -s .bss <addr> -s .data <addr>

.bss .data 获取方法可以 cat /sys/module/<module_name>/sections/.bss    ,cat /sys/module/<module_name>/sections/.data

接下来就用crash 的方法了,不同的是crash dump 出的数据是实时的,而gdb 要用load 来重新挂载才能更新。

使用slub(slab)的调试功能‏

在日常开发工作中最容易发生的错误十有八九都是出在线性空间的操作方面。(这里指的线性空间可以认为等同于虚拟地址或虚拟内存,但其他场合并不一 定适用)

主要的问题体现在:
1. 访问了未初始化的线性空间。 这类问题还是相对比较容易发现,因为内核立即会告警并打印堆栈。
2. 释放了错误的线性空间,或者对某个线性空间进行了双重释放。这种情况如果测试充分也能被发现,但即使被发现也很难判定就是因为误释放线性空间而发生错误。 因为内核无法判断你要释放的线性空间是不是就是你要释放的,所以也不会有任何告警。如果测试过程中未被发现那么它将是埋在产品中的一颗定时炸弹, 也许连续run 几个小时内核就会挂掉,也许run 几天几十天才会挂掉。
3. 已分配的线性空间没有释放,其实就是常说的内存泄露,如果某个类型的内存对象很小,或者被分配的几率很低,这通常不是什么非常大的问题,尤其是在拥有海量 内存的系统上。如果情况不是这样,那么写代码的时候就要小心了,因为后续补救起来是件非常耗时和麻烦的工作。

使用slub(slab) API 并配合debug(posion 内存毒药)功能能够大幅降低上述问题的发生。

准备内核:

1. 如果分配器使用的是slab, kernel configuration:
CONFIG_SLAB=y
CONFIG_SLAB_DEBUG=y
CONFIG_DEBUG_SLAB_LEAK=y
CONFIG_DEBUG_SLABINFO=y
CONFIG_DEBUG_INFO=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y

2. 如果分配器使用的是slub 那么就简单了,无需重新编译内核,slub默认就内嵌了debug的相关代码,只不过这项功能默认是禁用的。
最好仍然增加如下kernel configuration:
CONFIG_DEBUG_SLABINFO=y
CONFIG_DEBUG_INFO=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y

启用方法:

个人仅使用过slub debug,下文均以slub分配器来说明:

1. 如果需要启用全局的slub debug 需要在内核启动参数中加入 slub_debug

2. 有时候在全局启用了debug后 内核消息输出会增加很多,对于debug 特定的slub(slab) 对象而言看起来很不方便,并大幅降低分配器的效率。 这种情况下可以选择特定的对象来调试,而且可以在内核运行时打开/关闭 调试对象,不需要重启。步骤如下:

#cat /proc/slabinfo

slabinfo – version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fat_inode_cache       23    253    688   23    4 : tunables    0    0    0 : slabdata     11     11      0
fat_cache            102    204     40  102    1 : tunables    0    0    0 : slabdata      2      2      0
fuse_request          26     52    608   26    4 : tunables    0    0    0 : slabdata      2      2      0
fuse_inode             1     23    704   23    4 : tunables    0    0    0 : slabdata      1      1      0
kcopyd_job             0      0   3240   10    8 : tunables    0    0    0 : slabdata      0      0      0
dm_uevent              0      0   2608   12    8 : tunables    0    0    0 : slabdata      0      0      0
dm_rq_target_io        0      0    408   20    2 : tunables    0    0    0 : slabdata      0      0      0
ip6_dst_cache          7     25    320   25    2 : tunables    0    0    0 : slabdata      1      1      0
UDPLITEv6              0      0   1024   16    4 : tunables    0    0    0 : slabdata      0      0      0
UDPv6                 16     32   1024   16    4 : tunables    0    0    0 : slabdata      2      2      0
tw_sock_TCPv6          0     16    256   16    1 : tunables    0    0    0 : slabdata      1      1      0
TCPv6                 19     34   1856   17    8 : tunables    0    0    0 : slabdata      2      2      0
flow_cache             0      0    104   39    1 : tunables    0    0    0 : slabdata      0      0      0
cfq_queue            225    238    232   17    1 : tunables    0    0    0 : slabdata     14     14      0
bsg_cmd                0      0    312   26    2 : tunables    0    0    0 : slabdata      0      0      0
journal_handle       340    340     24  170    1 : tunables    0    0    0 : slabdata      2      2      0
journal_head          72    288    112   36    1 : tunables    0    0    0 : slabdata      8      8      0
revoke_record        256    256     32  128    1 : tunables    0    0    0 : slabdata      2      2      0
ext4_inode_cache   21466  21618    904   18    4 : tunables    0    0    0 : slabdata   1201   1201      0
ext4_free_data       146    146     56   73    1 : tunables    0    0    0 : slabdata      2      2      0
ext4_allocation_context    870    870    136   30    1 : tunables    0    0    0 : slabdata     29     29      0
ext4_io_end           58    319   1128   29    8 : tunables    0    0    0 : slabdata     11     11      0
ext4_io_page         516   1792     16  256    1 : tunables    0    0    0 : slabdata      7      7      0
ext3_inode_cache       0      0    792   20    4 : tunables    0    0    0 : slabdata      0      0      0
ext3_xattr             0      0     88   46    1 : tunables    0    0    0 : slabdata      0      0      0
arp_cache             36     36    448   18    2 : tunables    0    0    0 : slabdata      2      2      0
RAW                  461    475    832   19    4 : tunables    0    0    0 : slabdata     25     25      0
UDP                   38     38    832   19    4 : tunables    0    0    0 : slabdata      2      2      0
tw_sock_TCP           21     42    192   21    1 : tunables    0    0    0 : slabdata      2      2      0
TCP                   42    209   1664   19    8 : tunables    0    0    0 : slabdata     11     11      0
blkdev_queue          20     36   1816   18    8 : tunables    0    0    0 : slabdata      2      2      0
blkdev_requests       52    220    368   22    2 : tunables    0    0    0 : slabdata     10     10      0
sock_inode_cache     554    675    640   25    4 : tunables    0    0    0 : slabdata     27     27      0
net_namespace          1     12   2560   12    8 : tunables    0    0    0 : slabdata      1      1      0
shmem_inode_cache  11296  11448    656   24    4 : tunables    0    0    0 : slabdata    477    477      0
shared_policy_node  21143  22440     48   85    1 : tunables    0    0    0 : slabdata    264    264      0
numa_policy          203    210    136   30    1 : tunables    0    0    0 : slabdata      7      7      0
radix_tree_node     7248   8456    568   28    4 : tunables    0    0    0 : slabdata    302    302      0
idr_layer_cache      872    900    544   30    4 : tunables    0    0    0 : slabdata     30     30      0
dma-kmalloc-8192       0      0   8192    4    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-4096       0      0   4096    8    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-2048       0      0   2048   16    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-1024       0      0   1024   16    4 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-512        0     16    512   16    2 : tunables    0    0    0 : slabdata      1      1      0
dma-kmalloc-256        0      0    256   16    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-128        0      0    128   32    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-64         0      0     64   64    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-32         0      0     32  128    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-16         0      0     16  256    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-8          0      0      8  512    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-192        0      0    192   21    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-96         0      0     96   42    1 : tunables    0    0    0 : slabdata      0      0      0
kmalloc-8192          41     44   8192    4    8 : tunables    0    0    0 : slabdata     11     11      0
kmalloc-4096         109    120   4096    8    8 : tunables    0    0    0 : slabdata     15     15      0
kmalloc-2048         597    672   2048   16    8 : tunables    0    0    0 : slabdata     42     42      0
kmalloc-1024         787    864   1024   16    4 : tunables    0    0    0 : slabdata     54     54      0
kmalloc-512        10975  11088    512   16    2 : tunables    0    0    0 : slabdata    693    693      0
kmalloc-256         1439   1488    256   16    1 : tunables    0    0    0 : slabdata     93     93      0
kmalloc-128         1886   3232    128   32    1 : tunables    0    0    0 : slabdata    101    101      0
kmalloc-64         21988  23040     64   64    1 : tunables    0    0    0 : slabdata    360    360      0
kmalloc-32         20129  20992     32  128    1 : tunables    0    0    0 : slabdata    164    164      0
kmalloc-16          3341   3584     16  256    1 : tunables    0    0    0 : slabdata     14     14      0
kmalloc-8          22202  23040      8  512    1 : tunables    0    0    0 : slabdata     45     45      0
kmalloc-192        17809  17955    192   21    1 : tunables    0    0    0 : slabdata    855    855      0
kmalloc-96          6222   6342     96   42    1 : tunables    0    0    0 : slabdata    151    151      0
kmem_cache            32     32    256   16    1 : tunables    0    0    0 : slabdata      2      2      0
kmem_cache_node      153    192     64   64    1 : tunables    0    0    0 : slabdata      3      3      0

然后记下需要调试的对象名称(第一列)
echo 1 > /sys/kernel/slab/<对象名称>/poison

最后cat /sys/kernel/slab/<对象名称>/poison

如果显示为1 则说明针对此对象的debug poison 已经打开
注意:实际情况下并不是所有<对象名称>都可以在运行时开启/关闭debug poison 比如kmalloc-x

测试:

示例代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
MODULE_LICENSE(“GPL”);

struct slab_obj{
int aa;
int bb;
int cc;
};

typedef struct slab_obj* slab_obj_t;

slab_obj_t memblk=NULL;

struct kmem_cache *myslabobj;

static void mm_create(void){
myslabobj=kmem_cache_create(“my_slab_obj”,sizeof(struct slab_obj),0,SLAB_HWCACHE_ALIGN,NULL);
memblk=kmem_cache_alloc(myslabobj,GFP_KERNEL);
memblk->aa=0xabcd;
memblk->bb=0x1234;
memblk->cc=0x6879;
}

static void mm_destroy(void){
kfree(memblk);
kmem_cache_destroy(myslabobj);
}

static int __init mmbug_init(void){
mm_create();
return 0;
}

static void __exit mmbug_exit(void){
mm_destroy();
}

module_init(mmbug_init);
module_exit(mmbug_exit);

这段代码是没有内存方面的问题的,针对自定义的“slab_obj” 创建了slub  cache “my_slab_obj” 。由于是非内核数据结构,所以my_slab_obj不会在/proc/slabinfo 中新开一行,而是根据sizeof(struct slab_ojb) 的大小合并到kmalloc-8 。又因为kmalloc-8 不能在运行时开启debug poison ,所以只能启动时加内核参数slub_debug来开启。

1. 检测内存泄露:

在mm_destroy() 函数中把kfree(memblk); 注释掉 。 这样在模块卸载时调用到kmem_cache_destroy(myslabobj) 就会触发slub debug ,告警:

Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943251] =============================================================================
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943254] BUG my_slab_obj: Objects remaining on kmem_cache_close()
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943256] —————————————————————————–
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943256]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943258] INFO: Slab 0xffffea000039f200 objects=24 used=1 fp=0xffff88000e7c9e30 flags=0x20000000004080
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943261] Pid: 4842, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943263] Call Trace:
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943269]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943272]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943275]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943279]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943283]  [<ffffffff8116e28f>] slab_err+0x8f/0xa0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943286]  [<ffffffff81173e9e>] list_slab_objects.constprop.65+0x5e/0x200
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943289]  [<ffffffff81174117>] free_partial+0xd7/0x110
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943291]  [<ffffffff81174270>] kmem_cache_destroy+0x120/0x230
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943296]  [<ffffffffa028f039>] mmbug_exit+0x39/0x1000 [mmbug]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943300]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943304]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943311]  [<00007f0966db7b27>] 0x7f0966db7b26
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943314] INFO: Object 0xffff88000e7c8000 @offset=0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943317] INFO: Allocated in 0xffffffffa0005033 age=1316 cpu=1 pid=4841
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943319]       set_track+0x5d/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943321]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943322]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943324]       kmem_cache_alloc+0x141/0x150
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943326]       0xffffffffa0005033
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943328]       do_one_initcall+0x3b/0x180
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943329]       sys_init_module+0x113/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943331]       system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943333]       0x7f491185cc8a
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943346] SLUB my_slab_obj: kmem_cache_destroy called for cache that still has objects.
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943348] Pid: 4842, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943350] Call Trace:
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943352]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943355]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943357]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943360]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943362]  [<ffffffff81174295>] kmem_cache_destroy+0x145/0x230
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943366]  [<ffffffffa028f039>] mmbug_exit+0x39/0x1000 [mmbug]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943368]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943371]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943374]  [<00007f0966db7b27>] 0x7f0966db7b26

2. 检测错误释放线性空间(这里表现为重复释放):

在原来的kfree(memblk) 后面再加一个kfree(memblk) 进行重复释放,卸载模块时告警:

Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831862] =============================================================================
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831866] BUG my_slab_obj: Object already free
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831867] —————————————————————————–
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831868]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831875] INFO: Allocated in 0xffffffffa0005033 age=4621 cpu=1 pid=5196
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831879]       set_track+0x5d/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831882]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831884]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831886]       kmem_cache_alloc+0x141/0x150
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831887]       0xffffffffa0005033
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831890]       do_one_initcall+0x3b/0x180
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831893]       sys_init_module+0x113/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831895]       system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831897]       0x7f569ec49c8a
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831899] INFO: Freed in mmbug_exit+0x10/0x1000 [mmbug] age=0 cpu=0 pid=5198
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831901]       set_track+0x5d/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831903]       free_debug_processing+0x137/0x1a7
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831904]       __slab_free+0x2c/0x30b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831906]       kfree+0x140/0x170
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831907]       mmbug_exit+0x10/0x1000 [mmbug]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831909]       sys_delete_module+0x191/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831911]       system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831912]       0x7f41cf78bb27
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831913] INFO: Slab 0xffffea0001483e00 objects=24 used=0 fp=0xffff8800520f8000 flags=0x20000000004081
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831915] INFO: Object 0xffff8800520f8000 @offset=0 fp=0xffff8800520f9e30
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831916]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831917]   Object 0xffff8800520f8000:  6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5             kkkkkkkkkkk�
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831925]  Redzone 0xffff8800520f800c:  bb bb bb bb                                     ����
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831932]  Padding 0xffff8800520f8148:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831940] Pid: 5198, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831941] Call Trace:
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831945]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831948]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831951]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831954]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831957]  [<ffffffff8116f1cb>] print_trailer+0xfb/0x160
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831960]  [<ffffffff81663d49>] free_debug_processing+0x11a/0x1a7
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831962]  [<ffffffff81663e02>] __slab_free+0x2c/0x30b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831965]  [<ffffffff8116fed0>] kfree+0x140/0x170
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831968]  [<ffffffffa02c701c>] mmbug_exit+0x1c/0x1000 [mmbug]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831971]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831974]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831977]  [<00007f41cf78bb27>] 0x7f41cf78bb26
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831979] FIX my_slab_obj: Object at 0xffff8800520f8000 not freed

注意最后一行的 “FIX” 他的意思是第二次释放无效,这样其实避免了内核panic的可能性。

3. 访问已释放的线性空间

对于写操作:
增加kfree后面的代码如下
memblk->aa=0xabcd;
memblk->bb=0x1234;
memblk->cc=0x8789;
卸载模块时告警:

Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313558] =============================================================================
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313562] BUG my_slab_obj: Poison overwritten
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313563] —————————————————————————–
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313564]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313565] INFO: 0xffff88000aace000-0xffff88000aace00a. First byte 0xcd instead of 0x6b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313572] INFO: Allocated in 0xffffffffa0005033 age=1607 cpu=1 pid=5369
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313577]       set_track+0x5d/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313579]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313581]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313583]       kmem_cache_alloc+0x141/0x150
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313584]       0xffffffffa0005033
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313587]       do_one_initcall+0x3b/0x180
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313590]       sys_init_module+0x113/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313592]       system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313594]       0x7f3ce0bbbc8a
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313596] INFO: Freed in mmbug_exit+0x10/0x1000 [mmbug] age=0 cpu=1 pid=5370
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313598]       set_track+0x5d/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313600]       free_debug_processing+0x137/0x1a7
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313601]       __slab_free+0x2c/0x30b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313603]       kfree+0x140/0x170
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313604]       mmbug_exit+0x10/0x1000 [mmbug]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313606]       sys_delete_module+0x191/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313608]       system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313609]       0x7f8e151a2b27
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313611] INFO: Slab 0xffffea00002ab380 objects=24 used=0 fp=0xffff88000aace000 flags=0x20000000004080
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313612] INFO: Object 0xffff88000aace000 @offset=0 fp=0xffff88000aacfe30
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313613]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313614]   Object 0xffff88000aace000:  cd ab 00 00 34 12 00 00 89 87 00 00             ͫ..4…….
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313622]  Redzone 0xffff88000aace00c:  bb bb bb bb                                     ����
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313629]  Padding 0xffff88000aace148:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313637] Pid: 5370, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313639] Call Trace:
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313643]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313646]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313648]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313652]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313655]  [<ffffffff8116f1cb>] print_trailer+0xfb/0x160
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313658]  [<ffffffff8116f356>] check_bytes_and_report+0x126/0x160
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313661]  [<ffffffff8116f852>] check_object+0x242/0x290
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313664]  [<ffffffff8116f9e4>] __free_slab+0x144/0x190
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313667]  [<ffffffff811740ed>] free_partial+0xad/0x110
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313670]  [<ffffffff81174270>] kmem_cache_destroy+0x120/0x230
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313673]  [<ffffffffa028f045>] mmbug_exit+0x45/0x1000 [mmbug]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313676]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313679]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313682]  [<00007f8e151a2b27>] 0x7f8e151a2b26
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313684] FIX my_slab_obj: Restoring 0xffff88000aace000-0xffff88000aace00a=0x6b

同样最后的 “FIX” 指示第二次访问无效,内核不会panic。

对于读操作 不会出现告警,但如果用printk 打印这段地址,会输出多个字节的0x6b。看到这个就说明正在访问已经释放过的线性空间。

原理:

slub 实现poison debug 其实是简单的,正如刚才的debug 信息中所示slub(slab)会在恰当的时候放置单字节poison  0x6b  来占据实际分配的空间 ,并以单字节0xa5 结束。后续填充一定数量的单字节0xbb 作为Redzone (具体用意不明),最后还有单纯的填充字节0x5a 。 当发生重复释放,错误访问等情况时这些放置的“毒药”就会起作用,slab 也会采取措施纠正错误的操作。
有关内存毒药的字节定义可以查看 /lib/modules/$(uname -r)/build/include/linux/poison.h

其他说明:

尽管示例代码演示的是直接使用slab API 分配线性空间 ,但使用kmalloc来分配线性空间也可以配合slub(slab) debug ,因为kmalloc 实际分配的slab 对象是kmalloc-64 。不过因为无法使用kmem_cache_destroy这样的函数来释放slab cache 所以无法检测出内存泄露这样的问题。
如果操作线性空间分配与释放的层次不属于slub(slab) 而是位于伙伴系统(分页管理) 则需要开启page poison debug 。

erland 和 linux kernel 追踪的blog

http://mryufeng.iteye.com/

http://blog.yufeng.info

 

据说是taobao 运维人员的blog 有点内容

串口 COM口 TTL RS-232 RS-485 区别

Point:
1、串口、COM口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)。
2、接设备的时候,一般只接GND RX TX。不会接Vcc或者+3.3v的电源线,避免与目标设备上的供电冲突。
3、PL2303、CP2102芯片是 USB 转 TTL串口 的芯片,用USB来扩展串口(TTL电平)。
4、MAX232芯片是 TTL电平与RS232电平的专用双向转换芯片,可以TTL转RS-232,也可以RS-232转TTL。
5、TTL标准是低电平为0,高电平为1(+5V电平)。RS-232标准是正电平为0,负电平为1(±15V电平)。
6、RS-485与RS-232类似,但是采用差分信号负逻辑,更适合长距离传输。这里略过不讲。
串口、COM口:
COM口即串行通讯端口,简称串口。这里区别于USB的“通用串行总线”和硬盘的“SATA”。
一般我们见到的是两种物理标准。D型9针插头,和 4针杜邦头 两种。
这是常见的4针串口,在电路板上常见,经常上边还带有杜邦插针。还有时候有第五根针,3.3V电源端。
由于是预留在电路板上的,协议可以有很多种,要看具体设备。
下面这个就是D型9针串口(通俗说法)。在台式电脑后边都可以看到。
记住,这种接口的协议只有两种:RS-232和RS-485。不会是TTL电平的(除非特殊应用)。
9针串口的定义可以参考这里:http://wenku.baidu.com/view/5c170c6925c52cc58bd6be6e.html
我们一般只接出RXD TXD两针,外加GND。
下图是个USB转TTL串口的小板(TTL电平),可以用USB扩展出一个串口。芯片为PL2303HX。
网上经常混淆各种串口,但是这个确实是可以给STC单片机下载程序的。
这是另一种,CP2102芯片的,也是USB转串口(也是TTL电平)。
据说比PL2303的好,实际使用中没感觉出来。这个小板就多了+3.3V电源端,以适应不同的目标电路。

上边介绍的都是USB转TTL电平的串口,如果目标设备上是RS-232串口(D型9针接口)咋弄?
再接一片MAX232转换一下就行。
你也可以搭一个简单的比较器电路,来实现TTL转RS-232的功能,如下图。
RS-232转TTL咋弄?这就需要你动点脑子咯

当然,早有人想到了做一款成品。
仔细看下图,USB经过PL2303转成了TTL串口(中间那四个窟窿可以引出),再经由MAX232转换为RS-232电平,9针串口引出。
下面这是另一款:电平转换依旧用的是MAX232。

你或许会买到这种:看起来里边只有一个牛屎芯片的。

但是记住一点,只要是 D型9针串口,不会是TTL电平的,没特殊说明就默认是RS-232。
所以这根线,不管里边构造怎样的,是 USB转RS-232串口 的线。

我想要强调的是,一个设备的串口可以根据引出的串口线来判断是TTL还是RS-232,从而决定链接方式以及是否需要转换电路。

samba 与 win7

win7 和samba 沟通有点问题(还是这句话,如果不是普通用户,选择win server 2008 比 win7 更好),主要错误如下:

# smbclient //hostname/ …..
session setup failed: SUCCESS – 0

解决这个问题我试过各种方法:

1. 升级samba 到3.5

2. gpedit.msc -> 计算机配置 ->windows设置->安全设置->本地策略->安全选项,更改:

网络访问:本地帐号的共享和安全模型 经典-本地帐号的共享和安全模式(默认只能用guest 帐号访问)

3. gpedit.msc -> 计算机配置 ->windows设置->安全设置->本地策略->安全选项,更改:

网络安全:LAN 管理器身份验证 发送LM和NTLM-如果已协商,则使用NTLM2 安全会话

没辙了,打开smbclient -d7     debug开关,看到这个可疑的错误:

SPNEGO login failed: Invalid parameter

最后google到这个:

Win7 + Live Sign-in Assistant includes a mechToken in the SPNEGO response packet which seemingly all versions of samba 3.x.x fail to parse and always return permission denied

正好我加了Live Sign-in Assistant ,可能这样samba 就不能用NTLMv2 了,要使用旧的lanman认证方法,改smb.conf 吧

[global]
client lanman auth = Yes
client ntlmv2 auth = No
client use spnego = No

现在ok了,挂载也没问题了:

mount -t cifs -o username=user,password=passwd “//192.168.5.2/f$” /mnt/smb/

C 预处理的用法

(一) 预处理命令简介

注意: 函数宏对参数类型是不敏感的, 你不必考虑将何种数据类型传递给宏. 那么, 如何构建对参数类型敏感的宏呢? 参考本章的第九部分, 关于”##”的介绍.

关于定义宏的另外一些问题

(1) 宏可以被多次定义, 前提是这些定义必须是相同的. 这里的”相同”要求先后定义中空白符出现的位置相同, 但具体的空白符类型或数量可不同, 比如原先的空格可替换为多个其他类型的空白符: 可为tab, 注释…

e.g.

#define NULL 0

#define NULL /* null pointer */ 0

上面的重定义是相同的, 但下面的重定义不同:

#define fun(x) x+1

#define fun(x) x + 1 或: #define fun(y) y+1

如果多次定义时, 再次定义的宏内容是不同的, gcc会给出”NAME redefined”警告信息.

应该避免重新定义函数宏, 不管是在预处理命令中还是C语句中, 最好对某个对象只有单一的定义. 在gcc中, 若宏出现了重定义, gcc会给出警告.

(2) 在gcc中, 可在命令行中指定对象宏的定义:

e.g.

$ gcc -Wall -DMAX=100 -o tmp tmp.c

相当于在tmp.c中添加” #define MAX 100″.

那么, 如果原先tmp.c中含有MAX宏的定义, 那么再在gcc调用命令中使用-DMAX, 会出现什么情况呢?

—若-DMAX=1, 则正确编译.

—若-DMAX的值被指定为不为1的值, 那么gcc会给出MAX宏被重定义的警告, MAX的值仍为1.

注意: 若在调用gcc的命令行中不显示地给出对象宏的值, 那么gcc赋予该宏默认值(1), 如: -DVAL == -DVAL=1

(3) #define所定义的宏的作用域

宏在定义之后才生效, 若宏定义被#undef取消, 则#undef之后该宏无效. 并且字符串中的宏不会被识别

e.g.

#define ONE 1

sum = ONE + TWO /* sum = 1 + TWO */

#define TWO 2

sum = ONE + TWO /* sum = 1 + 2 */

#undef ONE

sum = ONE + TWO /* sum = ONE + 2 */

char c[] = “TWO” /* c[] = “TWO”, NOT “2”! */

(4) 宏的替换可以是递归的, 所以可以嵌套定义宏.

e.g.

# define ONE NUMBER_1

# define NUMBER_1 1

int a = ONE /* a = 1 */

2, #undef

#undef用来取消宏定义, 它与#define对立:

#undef name

如够被取消的宏实际上没有被#define所定义, 针对它的#undef并不会产生错误.

当一个宏定义被取消后, 可以再度定义它.

3, #if, #elif, #else, #endif

#if, #elif, #else, #endif用于条件编译:

#if 常量表达式1

语句…

#elif 常量表达式2

语句…

#elif 常量表达式3

语句…

#else

语句…

#endif

#if和#else分别相当于C语句中的if, else. 它们根据常量表达式的值来判别是否执行后面的语句. #elif相当于C中的else-if. 使用这些条件编译命令可以方便地实现对源代码内容的控制.

else之后不带常量表达式, 但若包含了常量表达式, gcc只是给出警告信息.

使用它们可以提升代码的可移植性—针对不同的平台使用执行不同的语句. 也经常用于大段代码注释.

e.g.

#if 0

{

一大段代码;

}

#endif

常量表达式可以是包含宏, 算术运算, 逻辑运算等等的合法C常量表达式, 如果常量表达式为一个未定义的宏, 那么它的值被视为0.

#if MACRO_NON_DEFINED == #if 0

在判断某个宏是否被定义时, 应当避免使用#if, 因为该宏的值可能就是被定义为0. 而应当使用下面介绍的#ifdef或#ifndef.

注意: #if, #elif, #else之后的宏只能是对象宏. 如果name为名的宏未定义, 或者该宏是函数宏. 那么在gcc中使用”-Wundef”选项会显示宏未定义的警告信息.

4, #ifdef, #ifndef, defined.

#ifdef, #ifndef, defined用来测试某个宏是否被定义

#ifdef name 或 #ifndef name

它们经常用于避免头文件的重复引用:

#ifndef __FILE_H__

#define __FILE_H__

#include “file.h”

#endif

defined(name): 若宏被定义,则返回1, 否则返回0.

它与#if, #elif, #else结合使用来判断宏是否被定义, 乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef. defined用于在一条判断语句中声明多个判别条件:

#if defined(VAX) && defined(UNIX) && !defined(DEBUG)

和#if, #elif, #else不同, #indef, #ifndef, defined测试的宏可以是对象宏, 也可以是函数宏. 在gcc中使用”-Wundef”选项不会显示宏未定义的警告信息.

5, #include , #include_next

#include用于文件包含. 在#include 命令所在的行不能含有除注释和空白符之外的其他任何内容.

#include “headfile”

#include <headfile>

#include 预处理标记

前面两种形式大家都很熟悉, “#include 预处理标记”中, 预处理标记会被预处理器进行替换, 替换的结果必须符合前两种形式中的某一种.

实际上, 真正被添加的头文件并不一定就是#include中所指定的文件. #include”headfile”包含的头文件当然是同一个文件, 但#include <headfile>包包含的”系统头文件”可能是另外的文件. 但这不值得被注意. 感兴趣的话可以查看宏扩展后到底引入了哪些系统头文件.

相对于#include, 我们对#include_next不太熟悉. #include_next仅用于特殊的场合. 它被用于头文件中(#include既可用于头文件中, 又可用于.c文件中)来包含其他的头文件. 而且包含头文件的路径比较特殊: 从当前头文件所在目录之后的目录来搜索头文件.

比如: 头文件的搜索路径一次为A,B,C,D,E. #include_next所在的当前头文件位于B目录, 那么#include_next使得预处理器从C,D,E目录来搜索#include_next所指定的头文件.

可参考cpp手册进一步了解#include_next

6, 预定义宏

标准C中定义了一些对象宏, 这些宏的名称以”__”开头和结尾, 并且都是大写字符. 这些预定义宏可以被#undef, 也可以被重定义.

下面列出一些标准C中常见的预定义对象宏(其中也包含gcc自己定义的一些预定义宏:

__LINE__ 当前语句所在的行号, 以10进制整数标注.

__FILE__ 当前源文件的文件名, 以字符串常量标注.

__DATE__ 程序被编译的日期, 以”Mmm dd yyyy”格式的字符串标注.

__TIME__ 程序被编译的时间, 以”hh:mm:ss”格式的字符串标注, 该时间由asctime返回.

__STDC__ 如果当前编译器符合ISO标准, 那么该宏的值为1

__STDC_VERSION__ 如果当前编译器符合C89, 那么它被定义为199409L, 如果符合C99, 那么被定义为199901L.

我用gcc, 如果不指定-std=c99, 其他情况都给出__STDC_VERSION__未定义的错误信息, 咋回事呢?

__STDC_HOSTED__ 如果当前系统是”本地系统(hosted)”, 那么它被定义为1. 本地系统表示当前系统拥有完整的标准C库.

gcc定义的预定义宏:

__OPTMIZE__ 如果编译过程中使用了优化, 那么该宏被定义为1.

__OPTMIZE_SIZE__ 同上, 但仅在优化是针对代码大小而非速度时才被定义为1.

__VERSION__ 显示所用gcc的版本号.

可参考”GCC the complete reference”.

要想看到gcc所定义的所有预定义宏, 可以运行: $ cpp -dM /dev/null

7, #line

#line用来修改__LINE__和__FILE__.

e.g.

printf(“line: %d, file: %s\n”, __LINE__, __FILE__);

#line 100 “haha”

printf(“line: %d, file: %s\n”, __LINE__, __FILE__);

printf(“line: %d, file: %s\n”, __LINE__, __FILE__);

显示:

line: 34, file: 1.c

line: 100, file: haha

line: 101, file: haha

8, #pragma, _Pragma

#pragma用编译器用来添加新的预处理功能或者显示一些编译信息. #pragma的格式是各编译器特定的, gcc的如下:

#pragma GCC name token(s)

#pragma之后有两个部分: GCC和特定的pragma name. 下面分别介绍gcc中常用的.

(1) #pragma GCC dependency

dependency测试当前文件(既该语句所在的程序代码)与指定文件(既#pragma语句最后列出的文件)的时间戳. 如果指定文件比当前文件新, 则给出警告信息.

e.g.

在demo.c中给出这样一句:

#pragma GCC dependency “temp-file”

然后在demo.c所在的目录新建一个更新的文件: $ touch temp-file, 编译: $ gcc demo.c 会给出这样的警告信息: warning: current file is older than temp-file

如果当前文件比指定的文件新, 则不给出任何警告信息.

还可以在在#pragma中给添加自定义的警告信息.

e.g.

#pragma GCC dependency “temp-file” “demo.c needs to be updated!”

1.c:27:38: warning: extra tokens at end of #pragma directive

1.c:27:38: warning: current file is older than temp-file

注意: 后面新增的警告信息要用””引用起来, 否则gcc将给出警告信息.

(2) #pragma GCC poison token(s)

若源代码中出现了#pragma中给出的token(s), 则编译时显示警告信息. 它一般用于在调用你不想使用的函数时候给出出错信息.

e.g.

#pragma GCC poison scanf

scanf(“%d”, &a);

warning: extra tokens at end of #pragma directive

error: attempt to use poisoned “scanf”

注意, 如果调用了poison中给出的标记, 那么编译器会给出的是出错信息. 关于第一条警告, 我还不知道怎么避免, 用””将token(s)引用起来也不行.

(3) #pragma GCC system_header

从#pragma GCC system_header直到文件结束之间的代码会被编译器视为系统头文件之中的代码. 系统头文件中的代码往往不能完全遵循C标准, 所以头文件之中的警告信息往往不显示. (除非用 #warning显式指明).

(这条#pragma语句还没发现用什么大的用处)

由于#pragma不能用于宏扩展, 所以gcc还提供了_Pragma:

e.g.

#define PRAGMA_DEP #pragma GCC dependency “temp-file”

由于预处理之进行一次宏扩展, 采用上面的方法会在编译时引发错误, 要将#pragma语句定义成一个宏扩展, 应该使用下面的_Pragma语句:

#define PRAGMA_DEP _Pragma(“GCC dependency \”temp-file\””)

注意, ()中包含的””引用之前引该加上\转义字符.

9, #, ##

#和##用于对字符串的预处理操作, 所以他们也经常用于printf, puts之类的字符串显示函数中.

#用于在宏扩展之后将tokens转换为以tokens为内容的字符串常量.

e.g.

#define TEST(a,b) printf( #a “<” #b “=%d\n”, (a)<(b));

注意: #只针对紧随其后的token有效!

##用于将它前后的两个token组合在一起转换成以这两个token为内容的字符串常量. 注意##前后必须要有token.

e.g.

#define TYPE(type, n) type n

之后调用:

TYPE(int, a) = 1;

TYPE(long, b) = 1999;

将被替换为:

int a = 1;

long b = 1999;

(10) #warning, #error

#warning, #error分别用于在编译时显示警告和错误信息, 格式如下:

#warning tokens

#error tokens

e.g.

#warning “some warning”

注意, #error和#warning后的token要用””引用起来!

(在gcc中, 如果给出了warning, 编译继续进行, 但若给出了error, 则编译停止. 若在命令行中指定了 -Werror, 即使只有警告信息, 也不编译.

预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:

#define 定义一个预处理宏

#undef 取消宏的定义

#include 包含文件命令

#include_next 与#include相似, 但它有着特殊的用途

#if 编译预处理中的条件命令, 相当于C语法中的if语句

#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句

#ifndef 与#ifdef相反, 判断某个宏是否未被定义

#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if

#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else

#endif #if, #ifdef, #ifndef这些条件命令的结束标志.

defined 与#if, #elif配合使用, 判断某个宏是否被定义

#line 标志该语句所在的行号

# 将宏参数替代为以参数值为内容的字符窜常量

## 将两个相邻的标记(token)连接为一个单独的标记

#pragma 说明编译器信息

#warning 显示编译警告信息

#error 显示编译错误信息

(二) 预处理的文法

预处理并不分析整个源代码文件, 它只是将源代码分割成一些标记(token), 识别语句中哪些是C语句, 哪些是预处理语句. 预处理器能够识别C标记, 文件名, 空白符, 文件结尾标志.

预处理语句格式: #command name(…) token(s)

1, command预处理命令的名称, 它之前以#开头, #之后紧随预处理命令, 标准C允许#两边可以有空白符, 但比较老的编译器可能不允许这样. 若某行中只包含#(以及空白符), 那么在标准C中该行被理解为空白. 整个预处理语句之后只能有空白符或者注释, 不能有其它内容.

2, name代表宏名称, 它可带参数. 参数可以是可变参数列表(C99).

3, 语句中可以利用”\”来换行.

e.g.

# define ONE 1 /* ONE == 1 */

等价于: #define ONE 1

#define err(flag, msg) if(flag) \

printf(msg)

等价于: #define err(flag, msg) if(flag) printf(msg)

(三) 预处理命令详述

1, #define

#define命令定义一个宏:

#define MACRO_NAME(args) tokens(opt)

之后出现的MACRO_NAME将被替代为所定义的标记(tokens). 宏可带参数, 而后面的标记也是可选的.

对象宏

不带参数的宏被称为”对象宏(objectlike macro)”

#define经常用来定义常量, 此时的宏名称一般为大写的字符串. 这样利于修改这些常量.

e.g.

#define MAX 100

int a[MAX];

#ifndef __FILE_H__

#define __FILE_H__

#include “file.h”

#endif

#define __FILE_H__ 中的宏就不带任何参数, 也不扩展为任何标记. 这经常用于包含头文件.

要调用该宏, 只需在代码中指定宏名称, 该宏将被替代为它被定义的内容.

函数宏

带参数的宏也被称为”函数宏”. 利用宏可以提高代码的运行效率: 子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源. 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率.

函数宏的参数是固定的情况

函数宏的定义采用这样的方式: #define name( args ) tokens

其中的args和tokens都是可选的. 它和对象宏定义上的区别在于宏名称之后不带括号.

注意, name之后的左括号(必须紧跟name, 之间不能有空格, 否则这就定义了一个对象宏, 它将被替换为 以(开始的字符串. 但在调用函数宏时, name与(之间可以有空格.

e.g.

#define mul(x,y) ((x)*(y))

注意, 函数宏之后的参数要用括号括起来, 看看这个例子:

e.g.

#define mul(x,y) x*y

“mul(1, 2+2);” 将被扩展为: 1*2 + 2

同样, 整个标记串也应该用括号引用起来:

e.g.

#define mul(x,y) (x)*(y)

sizeof mul(1,2.0) 将被扩展为 sizeof 1 * 2.0

调用函数宏时候, 传递给它的参数可以是函数的返回值, 也可以是任何有意义的语句:

e.g.

mul (f(a,b), g(c,d));

e.g.

#define insert(stmt) stmt

insert ( a=1; b=2;) 相当于在代码中加入 a=1; b=2 .

insert ( a=1, b=2;) 就有问题了: 预处理器会提示出错: 函数宏的参数个数不匹配. 预处理器把”,”视为参数间的分隔符.

insert ((a=1, b=2;)) 可解决上述问题.

在定义和调用函数宏时候, 要注意一些问题:

1, 我们经常用{}来引用函数宏被定义的内容, 这就要注意调用这个函数宏时的”;”问题.

example_3.7:

#define swap(x,y) { unsigned long _temp=x; x=y; y=_tmp}

如果这样调用它: “swap(1,2);” 将被扩展为: { unsigned long _temp=1; 1=2; 2=_tmp};

明显后面的;是多余的, 我们应该这样调用: swap(1,2)

虽然这样的调用是正确的, 但它和C语法相悖, 可采用下面的方法来处理被{}括起来的内容:

#define swap(x,y) \

do { unsigned long _temp=x; x=y; y=_tmp} while (0)

swap(1,2); 将被替换为:

do { unsigned long _temp=1; 1=2; 2=_tmp} while (0);

在Linux内核源代码中对这种do-while(0)语句有这广泛的应用.

2, 有的函数宏是无法用do-while(0)来实现的, 所以在调用时不能带上”;”, 最好在调用后添加注释说明.

eg_3.8:

#define incr(v, low, high) \

for ((v) = (low),; (v) <= (high); (v)++)

只能以这样的形式被调用: incr(a, 1, 10) /* increase a form 1 to 10 */

函数宏中的参数包括可变参数列表的情况

C99标准中新增了可变参数列表的内容. 不光是函数, 函数宏中也可以使用可变参数列表.

#define name(args, …) tokens

#define name(…) tokens

“…”代表可变参数列表, 如果它不是仅有的参数, 那么它只能出现在参数列表的最后. 调用这样的函数宏时, 传递给它的参数个数要不少于参数列表中参数的个数(多余的参数被丢弃).

通过__VA_ARGS__来替换函数宏中的可变参数列表. 注意__VA_ARGS__只能用于函数宏中参数中包含有”…”的情况.

e.g.

#ifdef DEBUG

#define my_printf(…) fprintf(stderr, __VA_ARGS__)

#else

#define my_printf(…) printf(__VA_ARGS__)

#endif

tokens中的__VA_ARGS__被替换为函数宏定义中的”…”可变参数列表.

注意在使用#define时候的一些常见错误:

#define MAX = 100

#define MAX 100;

=, ; 的使用要值得注意. 再就是调用函数宏是要注意, 不要多给出”;”.


dvd rw 工具集

dvd+rw-tools 有很多dvd rw 的底层工具:

/usr/bin/btcflash

好像是刷机工具

/usr/bin/dvd+rw-booktype

设置booktype:

dvd+rw-booktype -dvd-rom -media /dev/scdN

dvd+rw-booktype -dvd-rom -unit+r /dev/scdN

/usr/bin/dvd+rw-format

对于DVD-RW 而言:

要把 DVD-RW 置于受限式覆写格式, 必须使用下面的命令:

dvd+rw-format -force /dev/cd0 #快速格式化

dvd+rw-format -force=full /dev/cd0 #完全格式化

更改回顺序写入模式使用:

dvd+rw-format -blank /dev/cd0 #快速擦除

# dvd+rw-format -blank=full /dev/cd0 #全面擦除

对于DVD+RW 而言没有顺序,复写模式的概念:

dvd+rw-format -force /dev/cd0 #快速擦除

dvd+rw-format -lead-out /dev/cd0 #写入导出区(关闭区段)

复写模式:Mounted Media:         13h, DVD-RW Restricted Overwrite  .最大的特点是可以随机物理写,比如要追加文件不需要开一个新的区段。但它不能像win7 那样像文件系统那样修改目录。因为dvd+rw-tools 不支持udf文件系统。

顺序模式:  Mounted Media:         14h, DVD-RW Sequential . 也就是传统的光盘写入方式了。

好像使用顺序模式也无法创建多区段了,nero的多区段模式实际上是用的复写模式。


/usr/bin/dvd+rw-mediainfo

十分有用的工具

/usr/bin/dvd-ram-control

/usr/bin/growisofs

#growisofs is a front-end to mkisofs, i.e. invokes mkisofs to perform the actual ISO9660 file system layout

示例:

growisofs -dvd-compat -udf -iso-level 3 -Z /dev/cdrom8 -J -R /path/to/file  –speed=nX

growisofs -dvd-compat -M /dev/cdrom8 -J -R /path/to/file  –speed=nX

growisofs -Z /dev/scd0=image.iso –speed=nX

详细看这里

/usr/share/doc/packages/dvd+rw-tools/index.html

http://www.freebsd.org/doc/zh_CN/books/handbook/creating-dvds.html

WPA/WPA2 破解技术的新突破

我试了一下确实破解了一个信号最强的(-56) 用了不到6个小时,利用的手段是WPS穷举。发现WPS确实是一个非常弱智的设计。

详细参照这里:

http://blog.ibeini.com/archives/513.html

所需的工具:

http://code.google.com/p/reaver-wps

BD defect management

These are somewhat less organized Blu-ray Disc specific usage notes. Idea is to introduce terminology, outline options, explain some design choices…The first thing about Blu-ray Disc [hereafter BD] is its defect management system. Well, maybe second, after its capacity:-) But first or second, defect management is defined forboth BD-RE, rewritable media, and BD-R, write-once media. No, the latter part of the last sentence is not a joke, it is defined even for BD-R. Defect management comes with a performance penalty: most units will typically record at about 1/2 of the advertised media speed. This is because such units will spend every second revolution verifying the newly recorded data for defects. Even though some would argue to favour performance over the data integrity, I find it inappropriate to leave your data “in the dark,” and therefore dvd+rw-tools are coded to favour the defect management. On the positive side, even BD player units are required to recognize and respect BD-R[E] defect relocation list. This means that no explicit support by OS will be ever required to play back BD recorded with defect control in effect. This is unlike “Mt. Rainier” approach, which expects OS kernel to interpret the defect lists upon playback. In other words there is hardly any reason to bypass the BD defect management system. BD-RE specification defines two basic formats: with spare area reserved for remapping of media defects and without [though the latter is optional]. If present, spare area consists of two zones per layer: inner and outer. The inner zone of the first layer is of fixed size of 256MB, while others are of variable size, e.g. the outer zones size varies from 0 to 1GB each. Dvd+rw-format allows the outer zone to be grown in 32MB increments, but as of the moment of this writing you as the end-user is responsible for making sure that the increased outer spare area does not overlap with the end of the last data set. This brings us to the following practical hints:

  • when growisofs “runs into” a blank BD-RE media, it automatically pre-formats it with minimal spare area of 256MB;
  • if you want a larger spare area, run dvd+rw-format and specify the desired spare area size with -ssa option, e.g. ‘dvd+rw-format -ssa=1G /dev/dvd’, preferably prior to the actual recording;
  • dvd+rw-format recognizes -ssa=max;
  • dvd+rw-format also allows for -ssa=none, but [as mentioned earlier] it is not recommended and might be unsupported by your unit.

BD-R specification defines following recording modes:

  • SRM, Sequential Recording Mode, applied to blank media without any spare areas allocated;
  • SRM applied to media explicitly pre-formatted with spare area[s];
  • SRM with an option for Pseudo-Overwrite, SRM+POW;
  • RRM, Random Recording Mode;

For brevity, let’s refer to these four modes as SRM, SRM-POW, SRM+POW and RRM. Even though it is not explicitly mentioned above, both SRM+POW and RRM require spare area[s] to be allocated. This is because overwrites supported in these modes are handled as if they were defects, i.e. by remapping the blocks to be overwritten through the defect list. The exact difference between SRM+POW and RRM is beyond the current scope. To provide enough room for such [well, RRM actually] “overwrites” BD-R spare areas can be specified [depending on application requirements] to be as large as 1/2 of the total media capacity, yes, as much as 12GB per layer. Now burn this into your mind:

  • the recording mode and spare area size can be chosen/set only once for given BD-R media prior to the recording of the first user data block;
  • when growisofs “runs into” blank BD-R media, it automatically pre-formats it for SRM+POW with only inner spare area of 256MB;
  • growisofs allows for SRM recordings without spare area through “undocumented”option, but it’s not recommended;
  • if you wish to allocate larger spare area or use SRM-POW, use dvd+rw-formatprior to invoking growisofs;

As you might have noticed there is nothing about RRM to burn into your mind. RRM is specified as optional and the unit I have got unfortunately does not implement it. For this reason the current version of dvd+rw-tools does not support RRM. You surely wonder “all right, but why pre-format just for SRM+POW then?” Recall that POW stands for Pseudo-Overwrite. Pseudo or not, it allows us to effectively replace volume descriptors at the logical block address 16 or, in other words, to grow ISO9660 volume within single session – the same way it’s done with DVD+RW, DVD-RW Restricted Overwrite and DVD-RAM. This means that data recorded at different occasions will be accessible even on not-multisession-aware OSes. This is basically the reason for favouring SRM+POW. Given the BD media capacity, it would be interesting to store files larger than 4GB in an ISO9660 volume. It should be noted that the ISO9660 specification actually permits for files larger than 4GB, ifthey are broken into smaller extents. It is the single extent size that is limited to 4GB[-2KB] by the specification, not the whole file size. Unfortunately, mkisofs does not currently support multiextent file layout, not to mention that not all operating systems are capable to access such files. Therefore you have to chop large files into several pieces prior to the recording. Well, it is possible to burn bridge volume with large files with -udf option, but then multisessioning is out of picture.


linux 中的buffer和cache

这里指的buffer和cache 就是free 命令中看到的。

 

很多人为此写了很多(大部分都是错误的,或不准确的)文章来说明这个问题。下面我谈一下:

Page cache实际上是针对文件系统的,是文件的缓存,在文件层面上的数据会缓存到page cache。文件的逻辑层需要映射到实际的物理磁盘,这种映射关系由文件系统来完成。当page cache的数据需要刷新时,page cache中的数据交给buffer cache,但是这种处理在2.6版本的内核之后就变的很简单了,没有真正意义上的cache操作。

Buffer cache是针对磁盘块的缓存,也就是在没有文件系统的情况下,直接对磁盘进行操作的数据会缓存到buffer cache中,例如,文件系统的元数据都会缓存到buffer cache中。

简单说来,page cache用来缓存文件数据,buffer cache用来缓存磁盘数据。在有文件系统的情况下,对文件操作,那么数据会缓存到page cache,如果直接采用dd等工具对磁盘进行读写,那么数据会缓存到buffer cache

补充一点,在文件系统层每个设备都会分配一个def_blk_ops的文件操作方法,这是设备的操作方法,在每个设备的inode下面会存在一个radix tree,这个radix tree下面将会放置缓存数据的page页。这个page的数量将会在top程序的buffer一栏中显示。如果设备做了文件系统,那么会生成一个inode,这个inode会分配ext3_ops之类的操作方法,这些方法是文件系统的方法,在这个inode下面同样存在一个radix tree,这里会缓存文件的page页,缓存页的数量在top程序的cache一栏进行统计。从上面的分析可以看出,2.6内核中的buffer cache和page cache在处理上是保持一致的,但是存在概念上的差别,page cache针对文件的cache,buffer是针对磁盘块数据的cache,仅此而已

下面附个图一目了然