一切都要从函数start_kernel说起:
asmlinkage void start_kernel(void)
{
...
sock_init();
...
}
函数start_kernel定义在init/main.c中,是系统启动过程中运行的第一个C函数,由head.s中的startup_32直接调用。
void sock_init(void)
{
struct socket *sock;
int i;
/* Set up our SOCKET VFS major device */
if (register_chrdev(SOCKET_MAJOR, "socket", &net_fops) < 0)
{
return;
}
/* Release all sockets */
for (sock = sockets; sock<= last_socket; ++sock)
{
sock->state = SS_FREE;
}
/* Initialize all address(protocol) familied */
for (i = 0; i < NRPOTO; ++i)
{
pops[i] = NULL;
}
/* Initialize the DDI module */
ddi_init();
}
其中,
sockets和
pops的定义在
/net/socket.c如下:
#define NSOCKETS 128 /* should be dynamic, later... */
#define NPROTO 16 /* should be enought for now */
static struct socket sockets[NSOCKETS];
static struct proto_ops *pops[NPROTO];
结构体
socket和
proto_ops的定义在
/include/linux/net.h文件中。
void ddi_init(void)
{
struct ddi_proto *pro;
struct ddi_device *dev;
/* First off, kick all configured protocols */
pro = protocols;
while (pro->name != NULL)
{
(*pro->init)(pro); pro++;
}
/* Done. Now kick all configured device drivers */
dev = devices;
while (dev->title != NULL)
{
(*dev->init)(dev); dev++;
}
/* We're all done... */
}
函数
ddi_init做了两件事:初始化所有(定义)的
protocols和
devices。
struct ddi_proto portocols[] = {
{"UNIX", unix_proto_init},
{"INET", inet_proto_init}
};
其中
protocols中(暂时只)定义了如上的两类。
void inet_proto_init(struct ddi_proto *pro) { struct inet_protocol *p; int i; /* Set up our UNIX VFS major device */ if (register_chrdev(AF_INET_MAJOR, "af_inet", &inet_fops) < 0) return; /* Tell SOCKET that we are alive... */ (void) socket_register(inet_proto_ops.family, &inet_proto_ops); seq_offset = CURRENT_TIME * 250; /* Add all the protocols */ for (i = 0; i < SOCK_ARRAY_SIZE; i++) { tcp_prot.sock_array[i] = NULL; udp_prot.sock_array[i] = NULL; raw_prot.sock_array[i] = NULL; } for (p = inet_protocol_base; p != NULL; ) { struct inet_protocol *tmp; tmp = (struct inet_protocol *) p->next; p = tmp; } dev_init(); bh_base[INET_BH].routine = inet_bh; }
函数sock_register完成了proto_ops的设定:/* This function is called by a protocol handler that wants to * advertise its address family, and have it linked into the * SOCKET module */ int sock_register(int family, struct proto_ops *ops) { int i; cli(/* clear interrupt-enable flag */); for (i = 0; i < NPROTO; i++) { if (pops[i] != NULL) continue; pops[i] = ops; pops[i]->family = family; sti(/* set interrupt-enable flag */); return(i); } sti(/* set interrupt-enable flag */); return(-ENOMEM); }