结构体 inet_protosw ,代表了socket的类型(套接字类型和相应的协议):
/* This is used to register socket interfaces for IP protocols. */
struct inet_protosw {
struct list_head list;
/* These two fields form the lookup key. */
unsigned short type; /* This is the 2nd argument to socket(2). */
unsigned short protocol; /* This is the L4 protocol number. */
struct proto *prot;
const struct proto_ops *ops;
unsigned char flags; /* See INET_PROTOSW_* below. */
};
初始化结构体inet_protosw 的静态数组,总共有4个元素:
/* Upon startup we insert all the elements in inetsw_array[] into
* the linked list inetsw.
*/
static struct inet_protosw inetsw_array[] =
{
{
.type = SOCK_STREAM,
.protocol = IPPROTO_TCP,
.prot = &tcp_prot,
.ops = &inet_stream_ops,
.flags = INET_PROTOSW_PERMANENT |
INET_PROTOSW_ICSK,
},
{
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
.prot = &udp_prot,
.ops = &inet_dgram_ops,
.flags = INET_PROTOSW_PERMANENT,
},
{
.type = SOCK_DGRAM,
.protocol = IPPROTO_ICMP,
.prot = &ping_prot,
.ops = &inet_sockraw_ops,
.flags = INET_PROTOSW_REUSE,
},
{
.type = SOCK_RAW,
.protocol = IPPROTO_IP, /* wild card */
.prot = &raw_prot,
.ops = &inet_sockraw_ops,
.flags = INET_PROTOSW_REUSE,
}
};
把这个数组中的静态变量注册进数组inetsw,这是一个通过list组织起来的数据结构。虽然代码有点多,但是功能很简单。
static struct list_head inetsw[SOCK_MAX];
static int __init inet_init(void)
{
/* Register the socket-side information for inet_create. */
for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
INIT_LIST_HEAD(r);
for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
inet_register_protosw(q);
}
函数inet_register_protosw的作用是向inetsw里面添加元素。
1. void inet_register_protosw(struct inet_protosw *p)
2. {
3. struct list_head *lh;
4. struct inet_protosw *answer;
5. int protocol = p->protocol;
6. struct list_head *last_perm;
7.
8. printk("[%s %d] p->type: %d. protocol: %d .\n",
9. __func__, __LINE__, p->type, protocol);
10. dump_stack();
11.
12. spin_lock_bh(&inetsw_lock);
13.
14. if (p->type >= SOCK_MAX)
15. goto out_illegal;
16.
17. /* If we are trying to override a permanent protocol, bail. */
18. last_perm = &inetsw[p->type];
19. list_for_each(lh, &inetsw[p->type]) {
20. answer = list_entry(lh, struct inet_protosw, list); //container of
21. /* Check only the non-wild match. */
22. if ((INET_PROTOSW_PERMANENT & answer->flags) == 0)
23. break;
24. if (protocol == answer->protocol)
25. goto out_permanent;
26. last_perm = lh;
27. }
28.
29. /* Add the new entry after the last permanent entry if any, so that
30. * the new entry does not override a permanent entry when matched with
31. * a wild-card protocol. But it is allowed to override any existing
32. * non-permanent entry. This means that when we remove this entry, the
33. * system automatically returns to the old behavior.
34. */
35. list_add_rcu(&p->list, last_perm);
36. out:
37. spin_unlock_bh(&inetsw_lock);
38.
39. return;
40.
41. out_permanent:
42. pr_err("Attempt to override permanent protocol %d\n", protocol);
43. goto out;
44.
45. out_illegal:
46. pr_err("Ignoring attempt to register invalid socket type %d\n",
47. p->type);
48. goto out;
49. }
50. EXPORT_SYMBOL(inet_register_protosw);