This article analyzes kernel-based Linux kernel 1.2.13
Original works, reprint please mark http://blog.csdn.net/yming0221/article/details/7488828
For more please refer to the column, address http://blog.csdn.net/column/details/linux-kernel-net.html
Author: Yan Ming
Later series of blog posts will deeply analyze the network stack implementation principles of the Linux kernel. After Dr. Cao Guiping's analysis, he decided to select Linux kernel 1.2.13 for analysis.
The reason is as follows:
1. The function and network stack layers are already very clear
2. This version has better compatibility with subsequent versions.
3. The complexity is relatively small compared with the new kernel version, and the complexity is low, making it easier to grasp the essence of the network kernel.
4. This kernel version can be used to query system information.
The following describes the initialization process of the Linux kernel network.
Bootsect. S, setup. S, head. s after the system power-on can be referred to the 0.11 kernel previously analyzed. Same principle.
- Linux0.11 kernel-boot guide code analysis bootsect. s
- Linux0.11 kernel -- start the boot code analysis setup. s
- Linux0.11 kernel -- IDT (Interrupt Descriptor Table initialization) head. s analysis
After preparation, the system jumps to the start_kernel function execution under init/Main. C.
The hierarchy of the network stack is shown in Figure :( Note: This figure is taken from the Linux kernel network stack source code scenario analysis.)
The physical layer mainly provides various connected physical devices, such as various NICs and serial ports;
The Link Layer mainly refers to the drivers of various interface cards that provide access to the physical layer, such as NIC drivers;
The role of the network layer is to transmit network data packets to the correct location. The most important network layer protocol is the IP protocol. In fact, there are other network layer protocols such as ICMP, ARP, and RARP, it's just not as familiar to most people as IP addresses;
The role of the transport layer is mainly to provide end-to-end services. To put it bluntly, communication between applications is provided. The most famous Protocol on the transport layer is not the end of TCP and UDP protocols;
The application layer, as its name implies, is of course a "man-machine interface" layer provided by applications for semantic interpretation of transmitted data, such as HTTP, SMTP, and FTP, in fact, the application layer is not the layer that people finally see. The top layer should be the "Interpretation layer", which is responsible for presenting data to people in various forms of table items.
Linux network protocol stack structure
1. The system call interface layer is essentially an interface call library for user space applications, providing interfaces for user space applications to use network services.
2. The protocol-independent interface layer is the socket layer, which aims to shield different underlying protocols (more accurately, TCP and UDP, and of course raw IP addresses, sctp, etc.), so that the interface with the System Call layer can be simple and unified. Simply put, no matter what protocol we use at the application layer, a socket must be built through the system call interface. This socket is actually a huge sock structure, it is associated with the network protocol layer at the following layer, shielding the differences between different network protocols. Only the data is presented to the application layer (presented through the system call interface ).
3. The network protocol implementation layer is undoubtedly the core of the entire protocol stack. This layer mainly implements various network protocols, including IP, ICMP, ARP, RARP, TCP, and UDP. This layer contains a lot of design techniques and algorithms, which are quite good.
4. The driver interface layer unrelated to the specific device. The purpose of this layer is to unify the drivers of different interface cards and the interfaces of the network protocol layer, it abstracts the functions of various drivers into several special actions, such as open, close, and init. This layer can shield different underlying drivers.
5. The purpose of the driver layer is very simple. It is to establish an interface layer with the hardware.
The start_kernel function is initialized by the platform, memory initialization, trap initialization, interrupt initialization, process scheduling initialization, and buffer initialization. Then, socket_init () is executed, and init () is executed when the interrupt is enabled ().
The socket_init () function of the kernel's network warfare initialization function is implemented in net/socket. C.
Below is the implementation of this function
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}
The address family protocol initialization statement for (I = 0; I <nproto; ++ I) POPs [I] = NULL;
The nproto defined in this file is 16
# Define nproto16/* shocould be enough for now ..*/
How is pop [I] defined?
Static struct proto_ops * pops [nproto];
What is the proto_ops struct? The struct is defined in include/Linux/net. in H, this struct is a set of specific operation functions. It is an interface connecting the BSD socket and the inet socket. You can regard the BSD socket as an abstraction of the inet socket. The structure is as follows:
The specific definition is in net. h.
struct proto_ops { intfamily; 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 operation functions, a bit similar to file_operations in the file system. The operation is completed by passing the socket parameter.
The next step is proto_init () protocol initialization.
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 is defined as follows:
struct net_proto protocols[] = {#ifdefCONFIG_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 #ifdefCONFIG_INET { "INET",inet_proto_init},#endif#ifdef CONFIG_IPX { "IPX",ipx_proto_init },#endif#ifdef CONFIG_ATALK { "DDP",atalk_proto_init },#endif { NULL,NULL}};
The net. h struct defined in net_proto is
struct net_proto {char *name;/* Protocol name */void (*init_func)(struct net_proto *);/* Bootstrap */};
In the future, we will focus on discussing standard Inet domains.
Let's return to the proto_init () function.
Next, we will execute the inet_proto_init () function to initialize the inet domain protocol. The function is implemented in net/inet/af_inet.c.
The
(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 ++) // find an available idle table item {If (pops [I]! = NULL) continue; // skip pops [I] = ops if it is not empty; // assign pops [I]-> family = family; STI (); // enable interrupt return (I); // return the Protocol vector number that has just been registered} STI (); // if an exception occurs, enable interrupt return (-enomem );}
The inet_proto_ops parameter 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,};
The af_inet macro is defined as 2, that is, the inet protocol family is 2, followed by function pointers and Inet domain operation functions.
Then
Printk ("IP protocols:"); For (P = inet_protocol_base; P! = NULL;) // Add an inet_protocol struct to the inet_protocol 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
After the protocol initialization is complete, initialize the dev_init () device.
This is a general initialization process, which is not discussed in detail. the Linux kernel network stack source code will be analyzed in detail in the future.