Chinaunix首页 | 论坛 | 博客
  • 博客访问: 214038
  • 博文数量: 53
  • 博客积分: 2626
  • 博客等级: 少校
  • 技术积分: 509
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-27 22:40
文章分类

全部博文(53)

文章存档

2012年(2)

2011年(13)

2010年(10)

2009年(28)

我的朋友

分类: LINUX

2009-12-23 21:38:25

-----------------------------------------------------------------------------------
1.1 af_inet.c中有: list_for_each(p, &inetsw[sock->type]) 就是一个"语句表达式":

#define list_for_each(pos, head) \
    for (pos = (head)->next, prefetch(pos->next); pos != (head); \
            pos = pos->next, prefetch(pos->next))


而prefetch的定义为:

extern inline void prefetch(const void *x)
{
     __asm__ __volatile__ ("dcbt 0,%0" : : "r" (x));
}


__volatile__指明不要编译优化 dcbt为预取catch指令 (load...fetch the first catch)不知道正着翻还是反着翻译 '把pos->next预取到第一个cache' 貌似比较对

1.2 linux中很多表达式语句都有一个do while(0)结构

#define __copy_user(to,from,size)                    \
do {                                    \
    int __d0, __d1;                            \
    __asm__ __volatile__(                        \
        "0:    rep; movsl\n"                    \
        "    movl %3,%0\n"                    \
        "1:    rep; movsb\n"                    \
        ...
        : "memory");                        \
} while (0)


乍一看不可思议多此一举 其实这是个很巧妙的用法 首先是可以避免宏替换时造成的语法错误 如:
if (...) __copy_user(...) else ...
这种时候如果直接替换则很容易造成语法错误(else没有配对) 用do while(0)的花括号括起来则可以避免
do while(0)还有一个好处就是当你想在程序段中使用goto而又不敢用时 大可以交给do+break+while(0) 挺好用的样子... 对于熟悉系统编程的人来说这并不新鲜花哨... 对我来说 恩.

2."标准 C 要求数组或结构变量的初使化值必须以固定的顺序出现",那python呢 py传参的时候貌似也可以指定变量名 用a=b,...就可以了 可是不知道顺序是不是固定的

结构体的初始化必须以固定顺序出现却不代表必须全员出席!! 像tcp_prot中就没有赋bind初值(于是bind=0) 而raw_prot中bind:raw_bind 于是 在inet_bind中通过判断 if (sk->prot->bind) 来决定是否 return sk->prot->bind(...)

3.可变长数组 又叫柔性数组 并不是为了在结构体后预留空间 而是这样用的:

typedef struct{

    int m, n;

    char p[0];

}a;

a* b=(a*)malloc(sizeof(a)+100);

bzero(b->p,100);


最帅气的是那个b->p 想做啥都可以
这样,一个全新的buffer p[100]就归属a了 所以a称为可变长数组 因为它的长度是在malloc时决定的(but sizeof(*b)并不识别那100)
而且p[100]就在紧接m,n之后 (据说match和target就是这样接在ipt_entry中的 遍历时直接遍历地址就可以了(未经考证))
这样带来的一个好处之二是: p类型可以灵活多变且, 直接free(b)就可以了 而如果你用的是char *p来指向另外一个新buffer 则free的时候则须先free(p)再free(b) 否则p那块内存就搞没了!

4.标号元素
linux中有很多这样的结构体:

struct proto {
    void            (*close)(struct sock *sk, long timeout);
    int            (*connect)(struct sock *sk, struct sockaddr *uaddr, int addr_len);
    int            (*disconnect)(struct sock *sk, int flags);

    ........


其元素就是一个函数定义, 如close的返回类型为void 参数为(struct sock *sk, long timeout), 这样的结构体非常的通用, 在tcp_ipv4.c中初始化为:

struct proto tcp_prot = {
    name:        "TCP",
    close:        tcp_close,
    connect:    tcp_v4_connect,
    disconnect:    tcp_disconnect,

    ........


而在raw.c中:

struct proto raw_prot = {
    name:        "RAW",
    close:        raw_close,
    connect:    udp_connect,
    disconnect:    udp_disconnect,
    ........


这样就将整个协议都可以使用proto结构来"定义"定义的"动作"在不同的协议中使用的函数,(name是毛线情况?) 而在某处出现tcp_prot[sock->type]->close(sk,XXX)这样类似的结构时 就知道他是什么意思了

阅读(1111) | 评论(0) | 转发(0) |
0

上一篇:gcc核心扩展[ZZ]

下一篇:by myself[1]

给主人留下些什么吧!~~