-----------------------------------------------------------------------------------
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)这样类似的结构时 就知道他是什么意思了
阅读(1144) | 评论(0) | 转发(0) |