In the client code, the first called function is socket (). Before this function is called, what did the system do to make the socket () call normal?
First of all, the socket function is actually a system call. It is the code in the kernel. Our application layer calls the system call and calls the system function.
Secondly, at system startup, sock_init () has been called to initialize the socket. Before we call the socket function, the socket initialization part has paved the way for our call.
Void sock_init (void)
{
Int I;
......
For (I = 0; I <nproto; ++ I) POPs [I] = NULL;
Proto_init ();
......
}
Where # define nproto 16/* shocould be enough for now ..*/
When pops [I] is initialized, it is first cleared by the for (I = 0; I <nproto; ++ I) POPs [I] = NULL; statement, and then proto_init (); value corresponding to function fill
Void proto_init (void)
{
Extern struct net_proto protocols [];/* network protocols */
Struct net_proto * pro;
/* Kick all configured protocols .*/
Pro = protocols;
While (Pro-> name! = NULL)
{
(* Pro-> init_func) (Pro );
Pro ++;
}
/* We're all done ...*/
}
The
While (Pro-> name! = NULL)
{
(* Pro-> init_func) (Pro );
Pro ++;
}
Call the initialization function of the corresponding protocol to fill a certain entry in the POPs [] array.
The specific TCP/IP protocol (* pro-> init_func) (Pro) is initialized by executing the inet_proto_init function in the protocols [] array.
Struct net_proto protocols [] = {
......
# Ifdef config_inet
{"Inet", inet_proto_init },
# Endif
......
}
The inet_proto_init () function calls the sock_registe () function to register
Sock_register is called by the inet_proto_init () function to record the array pointer to the POPs [] global variable.
Int sock_register (INT family, struct proto_ops * OPS)
{
......
(Void) sock_register (inet_proto_ops.family, & inet_proto_ops );
......
}
Int sock_register (INT family, struct proto_ops * OPS)
{
Int I;
CLI ();
For (I = 0; I <nproto; I ++)
{
If (pops [I]! = NULL)
Continue;
Pops [I] = OPS;
Pops [I]-> family = family;
STI ();
Return (I );
}
STI ();
Return (-enomem );
}
Pops [I] = OPS; it is the place where the Global Array of POPs [] is initialized. net_proto_ops is defined as follows:
Static struct proto_ops inet_proto_ops = {
Af_inet,
Inet_create,
Inet_dup,
Inet_release,
Inet_bind,
Inet_connect,
Inet_socketpair,
Inet_accept,
Inet_getname,
Inet_read,
Inet_write,
Inet_select,
Inet_ioctl,
Inet_listen,
Inet_send,
Inet_recv,
Inet_sendto,
Inet_recvfrom,
Inet_shutdown,
Inet_setsockopt,
Inet_getsockopt,
Inet_fcntl,
};
In fact, it defines a bunch of functions and uses these functions to initialize the array. In the future, this function will be used to complete specific tasks.
Looking back, what socket initialization does is to register the operation sets corresponding to each protocol in a Global Array and prepare for the application program to call socket () to create a socket, because when we use the static int sock_socket (INT family, int type, int protocol) function to create a socket, we use the int family parameter to specify the required protocol. Through this protocol, then we can scan the global data of POPs [] and find the corresponding function in this array to complete our work.