荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: ykwch.bbs@bbs.cqupt.edu.cn (心蓝--雨下), 信区: Linux
标  题: 协议初始化2
发信站: 幽幽黄桷兰 (Sat Apr  5 15:27:03 2003)
转信站: SZU!news.tiaozhan.com!news.happynet.org!CQUPT

协议初始化-2
    其中的sock_register函数的作用已经在前面说了,现在来看看struct inet_proto
col和inet_add_protocol函数。前面的结构体
是在include/net/protocol.h里面:
struct inet_protocol
{
int (*handler)(struct sk_buff *skb, unsigned short len);
void (*err_handler)(struct sk_buff *skb, unsigned char *dp, int len);
struct inet_protocol *next;
unsigned char protocol;
unsigned char copy:1;
void *data;
const char *name;
};
    第一个函数是用来接收数据的callback函数,第二个是错误处理函数,其它的copy
是用来协议共享的,这个以后再说,data当然就是这个结构体的私有数据了。
    inet_add_protocol函数是在net/ipv4/protocol.c里面的:
void inet_add_protocol(struct inet_protocol *prot)
{
unsigned char hash;
struct inet_protocol *p2;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
prot ->next = inet_protos[hash];
inet_protos[hash] = prot;
prot->copy = 0;
p2 = (struct inet_protocol *) prot->next;
while(p2 != NULL)
{
if (p2->protocol == prot->protocol)
{
prot->copy = 1;
break;
}
p2 = (struct inet_protocol *) p2->next;
}
}
    显然这个函数就是建立一个hash表,然后每个hash表项都是一个链表头,然后通过
这个hash表加链表的方式访问每个协议结构体。在这里你也见到了copy成员的用法了把

    arp_init函数是在net/ipv4/arp.c里面的(假定没有定义CONFIG_SYSCTL):
neigh_table_init(&arp_tbl);
dev_add_pack(&arp_packet_type);
proc_net_register(&proc_net_arp);
    不知道是不是有人眼睛一亮啊,呵呵,看到了dev_add_pack函数。
    还是一步步来把。
    neigh_table_init函数在net/core/neighbour.c中间:
void neigh_table_init(struct neigh_table *tbl)
{
unsigned long now = jiffies;
tbl->parms.reachable_time = neigh_rand_reach_time(
tbl->parms.base_reachable_time);
init_timer(&tbl->gc_timer);
tbl->gc_timer.data = (unsigned long)tbl;
tbl->gc_timer.function = neigh_periodic_timer;
tbl->gc_timer.expires = now + tbl->gc_interval +
tbl->parms.reachable_time;
add_timer(&tbl->gc_timer);
init_timer(&tbl->proxy_timer);
tbl->proxy_timer.data = (unsigned long)tbl;
tbl->proxy_timer.function = neigh_proxy_process;
skb_queue_head_init(&tbl->proxy_queue);
tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time*20;
tbl->next = neigh_tables;
neigh_tables = tbl;
}
    jiffies是当前系统的时间,在i386系统上面好象一个jiffies代表50ms,显然这个
函数就是生成两个timer将一个放在系统的timerlist里面。那个gc_timer的意思是garb
age collect timer,因为每过一段时间arp的cache就应该更新,所以要有一个expires
时间,这段时间过了以后就要更新arp地址了,那个proxy_timer还没有看是什么,不过
我假定我的机器不使用proxy也不做成proxy,所以proxy相关的都没有管:P
    那个timer的function显然是时钟到期的回调函数,data是这个回调函数要使用的私
有数据了。
    下面是dev_add_pack函数,它在net/core/dev.c里面:
void dev_add_pack(struct packet_type *pt)
{
int hash;
#ifdef CONFIG_NET_FASTROUTE
/* Hack to detect packet socket */
if (pt->data) {
netdev_fastroute_obstacles++;
dev_clear_fastroute(pt->dev);
}
#endif
if(pt->type==htons(ETH_P_ALL))
{
netdev_nit++;
pt->next=ptype_all;
ptype_all=pt;
}
else
{
hash=ntohs(pt->type)&15;
pt->next = ptype_base[hash];
ptype_base[hash] = pt;
}
}
    显然系统保留了两个表,一个是ptype_all,用来接收所有类型的包的链表,一个是
一个hash数组+链表的结构,用来接收特定类型的包。
    struct packet_type的定义在include/linux/netdevice.h里面,我保留原来的注释
,这样就不用我多说了:)
{
unsigned short type;
/* This is really htons(ether_type). */
struct device *dev;
/* NULL is wildcarded here */
int (*func) (struct sk_buff *,
struct device *, struct packet_type *);
void *data;
/* Private to the packet type */
struct packet_type *next;
};
    其中的func当然是回调函数了,举个例子来说,arp_packet_type是这样的:
static struct packet_type arp_packet_type =
{
__constant_htons(ETH_P_ARP),
NULL, /* All devices */
arp_rcv,
NULL,
NULL
};
    arp_init函数还有最后一个proc_net_register函数,这个函数在include/linux/p
roc_fs.h里面:
static inline int proc_net_register(struct proc_dir_entry * x)
{
return proc_register(proc_net, x);
}
    而proc_register在fs/proc/root.c里面,主要作用是在proc_net对应的目录下面生
成每个协议的子目录,例如TCP等在/proc目录下面生成相应的目录,用户可以通过访问
/proc/net目录下面的相应目录得到每个协议的统计参数。

--
也许轮回里早已经注定
今生就该我还给你
一颗心在风雨里飘来飘去
只是为你
※ 来源:·幽幽黄桷兰 bbs.cqupt.edu.cn·[FROM: BlueCrystal]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店