This article analyzes kernel-based Linux Kernel 1.2.13
Original works, reproduced please mark http://blog.csdn.net/yming0221/article/details/7488828
See column, Address http://blog.csdn.net/column/details/linux-kernel-net.html
Shuming
The next series of posts will delve into the Linux kernel's network stack implementation principle, see Dr Cao Guiping's analysis, also decided to choose the Linux kernel 1.2.13 version for analysis.
The reasons are as follows:
1. Features and network stack levels are already very clear
2. This version has better cohesion with its subsequent versions
3. Relatively new kernel version of complexity, less complexity, easier to grasp the essence of the network core
4. This kernel version compares system data to query
The initialization process of the Linux kernel Network section begins with a zero-based analysis.
The bootsect is executed after the system is power-up. S,setup. S,head. S, you can refer to the previously analyzed 0.11 cores. Same principle.
- Linux0.11 Kernel-Boot code Analysis BOOTSECT.S
- Linux0.11 Kernel-Boot code Analysis SETUP.S
- Linux0.11 Kernel--idt (initialization of interrupt descriptor descriptor) HEAD.S analysis
After the preparatory work, the system jumps to the Start_kernel function under INIT/MAIN.C.
The hierarchy of network stacks such as: (Note: This picture is from "Linux kernel network stack source code scenario analysis")
Physical layer mainly provides a variety of connected physical equipment, such as various network cards, serial cards, etc.;
Link layer mainly refers to the physical layer to provide access to a variety of interface card driver, such as network card driver;
The role of the network layer is responsible for the transmission of packets to the correct location, the most important network layer protocol is the IP protocol, in fact, the network layer has other protocols such as ICMP,ARP,RARP, but not as the IP is familiar to the majority;
The role of the transport layer is mainly to provide end-to-end, white point is to provide communication between applications, the transport layer is the most famous protocol non-TCP and UDP protocol is the end of the genus;
Application layer, as the name implies, of course, is provided by the application, for the transmission of data semantic interpretation of the "Man-machine Interface" layer, such as http,smtp,ftp, and so on, in fact, the application layer is not what people eventually see that layer, the top layer should be "interpretation layer", Responsible for the final presentation of the data in various form items.
Linux Network protocol stack structure
1, the system calls the interface layer, essentially a user-space application-oriented interface call library, to provide user space applications with the use of network services interface.
2, protocol-independent interface layer, is the socket layer, the purpose of this layer is to shield the underlying different protocols (more accurately, mainly TCP and UDP, of course, including Raw IP, SCTP, etc.), so that the interface with the system call layer can be simple, unified. To put it simply, no matter what protocol we use in the application layer, we have to build a socket through the system call interface, which is actually a huge sock structure, it is connected with the layer of network protocol layer below, shielding the different network protocols, The data section is dedicated to the application layer (presented through the system invocation interface).
3, the Network protocol implementation layer, no doubt, this is the core of the entire protocol stack. This layer mainly implements various network protocols, the most important of course is ip,icmp,arp,rarp,tcp,udp and so on. This layer contains a lot of design techniques and algorithms, quite good.
4, the specific device-independent drive interface layer, the purpose of this layer is to unify the different interface card driver and network protocol layer interface, it will be a variety of different driver functions of the unified abstraction for a few special actions, such as Open,close,init, This layer can block different drivers at the bottom.
5, the driver layer, the purpose of this layer is very simple, is to establish the interface layer with the hardware.
Start_kernel functions are platform-initialized, memory-initialized, trap-initialized, interrupt-initialized, process-scheduled initialized, buffer-initialized, and then execute Socket_init (), and finally Interrupt execution init ().
The implementation of the kernel's network warfare initialization function Socket_init () function in net/socket.c
The following is the implementation of the function
[CPP]View Plaincopy
- void Sock_init (void)//network stack initialization
- {
- int i;
- PRINTK ("Swansea University Computer Society net3.019\n");
- /*
- * Initialize All Address (protocol) families.
- */
- for (i = 0; i < Nproto; ++i) pops[i] = NULL;
- /*
- * Initialize the Protocols module.
- */
- Proto_init ();
- #ifdef config_net
- /*
- * Initialize the DEV module.
- */
- Dev_init ();
- /*
- * and the bottom half handler
- */
- Bh_base[net_bh].routine= Net_bh;
- ENABLE_BH (NET_BH);
- #endif
- }
Where the Address family protocol initializes the statement for (i = 0; i < Nproto; ++i) pops[i] = NULL;
The Nproto defined in the file here is 16
#define NPROTO/* should be enough */
and Pop[i] is how to define it?
static struct Proto_ops *pops[nproto];
What is the PROTO_OPS structure? The structure is defined in the include/linux/net.h, the structure is a specific set of operational functions, is connected to the BSD socket and inet socket interface, can be the BSD socket as a inet socket abstraction, the structure is as follows:
Specifically defined in the Net.h
[CPP]View Plaincopy
- struct Proto_ops {
- int family;
- Int (*create) (struct socket *sock, int protocol);
- Int (*dup) (struct socket *newsock, struct socket *oldsock);
- Int (*release) (struct socket *sock, struct socket *peer);
- Int (*bind) (struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
- Int (*connect) (struct socket *sock, struct sockaddr *uservaddr,
- int Sockaddr_len, int flags);
- Int (*socketpair) (struct socket *sock1, struct socket *sock2);
- Int (*accept) (struct socket *sock, struct socket *newsock,
- int flags);
- Int (*getname) (struct socket *sock, struct sockaddr *uaddr,
- int *usockaddr_len, int peer);
- Int (*read) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- Int (*write) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- Int (*select) (struct socket *sock, int sel_type,
- Select_table *wait);
- Int (*ioctl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
- Int (*listen) (struct socket *sock, int len);
- Int (*send) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- Int (*RECV) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- Int (*sendto) (struct socket *sock, void *buff, int len, int nonblock,
- Unsigned flags, struct sockaddr *, int addr_len);
- Int (*recvfrom) (struct socket *sock, void *buff, int len, int nonblock,
- Unsigned flags, struct sockaddr *, int *addr_len);
- Int (*shutdown) (struct socket *sock, int flags);
- Int (*setsockopt) (struct socket *sock, int level, int optname,
- char *optval, int optlen);
- Int (*getsockopt) (struct socket *sock, int level, int optname,
- char *optval, int *optlen);
- Int (*fcntl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
- };
As you can see, this is actually a series of operations that are somewhat similar to the file_operations in a file system. Pass the socket through the parameters to complete the operation.
Next is the Proto_init () protocol initialization.
[CPP]View Plaincopy
- void Proto_init (void)
- {
- extern struct Net_proto protocols[]; /* Network Protocols global variable, defined in PROTOCOLS.C */
- struct Net_proto *pro;
- /* Kick all configured protocols. */
- Pro = Protocols;
- while (pro->name! = NULL)
- {
- (*pro->init_func) (PRO);
- pro++;
- }
- /* We ' re all done ... */
- }
The global protocols definition is as follows:
[CPP]View Plaincopy
- struct Net_proto protocols[] = {
- #ifdef Config_unix
- {"UNIX", Unix_proto_init},
- #endif
- #if defined (config_ipx) | | Defined (Config_atalk)
- {"802.2", P8022_proto_init},
- {"Snap", Snap_proto_init},
- #endif
- #ifdef config_ax25
- {"ax.25", Ax25_proto_init},
- #endif
- #ifdef config_inet
- {"INET", Inet_proto_init},
- #endif
- #ifdef CONFIG_IPX
- {"IPX", Ipx_proto_init},
- #endif
- #ifdef Config_atalk
- {"DDP", Atalk_proto_init},
- #endif
- {NULL, NULL}
- };
And the definition of structure Net_proto is net.h
[CPP]View Plaincopy
- struct Net_proto {
- Char *name; /* Protocol Name */
- void (*init_func) (struct Net_proto *); /* Bootstrap */
- };
Future focus on the standard inet domain
Let's go back to the Proto_init () function
The Inet_proto_init () function is then executed to initialize the INET domain protocol. The implementation of this function is in net/inet/af_inet.c
One of the
(void) Sock_register (inet_proto_ops.family, &inet_proto_ops);
[CPP]View Plaincopy
- int sock_register (int family, struct proto_ops *ops)
- {
- int i;
- CLI ();//Off interrupt
- for (i = 0; i < Nproto; i++)//Find an available free table entry
- {
- if (pops[i]! = NULL)
- continue;//if not empty, skip
- Pops[i] = ops;//for assignment
- pops[i]->family = family;
- STI ();//interrupt on/off
- return (i);//returns the protocol vector number used for the newly registered
- }
- STI ();//abnormal, also open interrupt
- return (-ENOMEM);
- }
The inet_proto_ops in the parameters are defined as follows:
[CPP]View Plaincopy
- 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,
- };
Where the AF_INET macro is defined as 2, that is, the INET protocol family number is 2, followed by the function pointer, inet Field Operation function.
And then
[CPP]View Plaincopy
- PRINTK ("IP protocols:");
- for (p = inet_protocol_base; p! = NULL;)//Adds an inet_protocol struct inet_protocol_base to the array Inet_protos
- {
- struct Inet_protocol *tmp = (struct Inet_protocol *) p->next;
- Inet_add_protocol (P);
- PRINTK ("%s%s", P->name,tmp ",": "\ n");
- p = tmp;
- }
- /*
- * Set the ARP module up
- */
- Arp_init ();//Initialize the Address resolution layer
- /*
- * Set the IP module up
- */
- Ip_init ();//Initialize the IP layer
The initialization of the Dev_init () device is performed after the protocol initialization is complete.
This is a general initialization process, the discussion is not very detailed, followed by the Linux kernel network stack source code detailed analysis.
Linux kernel--Network stack Implementation Analysis (i)--Network stack initialization