Kernel-mode basic socket programming

Source: Internet
Author: User
1. Establish a listener and Connection Service

The code for creating a TCO listener on the server is as follows:

Struct sockaddr_in locaddr; struct socket * sock; struct socket * newsock; int RC; int backlog = 0; int shutdown; char * server_ip = "192.168.0.1 "; __u32 local_ip = (_ u32) inet_addr (server_ip); int local_port = 1123456/* Step 2: Create a socket */rc = sock_create (pf_inet, sock_stream, 0, & sock); If (local_ip! = 0 | local_port! = 0) {memset (& locaddr, 0, sizeof (locaddr); locaddr. sin_family = af_inet; locaddr. sin_port = htons (local_port); locaddr. sin_addr.s_addr = (local_ip = 0 )? Inaddr_any: htonl (local_ip);/* Step 4: bind an IP address or port */rc = sock-> OPS-> BIND (sock, (struct sockaddr *) & locaddr, sizeof (locaddr); If (rc =-eaddrinuse) {printk ("port % d already in use \ n", local_port);} If (RC! = 0) {printk ("error trying to bind to port % d: % d \ n", local_port, RC) ;}/ * Step 2: start listening */rc = (* sockp)-> OPS-> listen (* sockp, backlog); shutdown = RC/* Step 2: Enter the loop and wait for the client to connect, and the global variable shutdown can be used to stop the service */while (! Shutdown) {wait_queue_t wait; struct socket * newsock; struct sockaddr_in sin; init_waitqueue_entry (& wait, current); _ u32 peer_ip; int peer_port; /* kernel-mode socket programming is very important. On the server side, you need to establish the Socket Structure of the client */rc = sock_create_lite (pf_packet, sock-> type, ipproto_tcp, & newsock ); if (RC) {printk ("can't allocate socket \ n"); Return RC;} newsock-> Ops = sock-> OPS; set_current_state (task_interruptible ); /* sleep, waiting for the connection request to be received by the underlying Network Driver Wake up */add_wait_queue (sock-> SK-> sk_sleep, & wait);/* Step 5.1: before being scheduled, try to process whether a connection is received */rc = sock-> OPS-> Accept (sock, newsock, o_nonblock); If (rc =-eagain) {/* Step 5.2: start sleep */schedule ();/* Step 5.3: Wake up, try to process received connections */rc = sock-> OPS-> Accept (sock, newsock, o_nonblock);} remove_wait_queue (sock-> SK-> sk_sleep, & wait); set_current_state (task_running);/* Step 1: obtain the Client IP address and port */rc = newsock-> OPS-> getname (newsock, (struct Sockaddr *) & sin, & Len, remote? 2: 0); peer_ip = ntohl (SIN. sin_addr.s_addr); peer_port = ntohs (SIN. sin_port );}

The code for establishing a TCP connection between the client and the server is as follows:

server=gethostbyname(SERVER_NAME);sockfd=socket(AF_INET,SOCK_STREAM,0);address.sin_family=AF_INET;address.sin_port=htons(PORT_NUM);memcpy(&address.sin_addr,server->h_addr,server->h_length);connect(sockfd,&address,sizeof(address));

The main events that occur during connection initialization and establishment are as follows:

1) sys_socket call: Call socket_creat () to create a socket that meets the input parameters family, type, and Protocol. Call sock_map_fd () to obtain an unused file descriptor, apply for and initialize the corresponding file {} structure.

2) sock_creat (): Create a socket structure. To initialize the Socket Structure of each different family, you need to call different create functions. For iNet-type addresses, the following definitions are completed by calling the sock_register () function during network protocol initialization:
Struct net_proto_family inet_family_ops = {
Pf_inet;
Inet_create
};
Therefore, the inet protocol will finally call the inet_create function.

3) inet_create: Initialize the sock state to ss_unconnected, apply for a new sock structure, and initialize the socket member Ops to inet_stream_ops, while the sock member Prot is initialized to tcp_prot. Call sock_init_data to associate the sock and sock variables of the socket structure.

4) after the system initialization is complete, connect is performed. The system calls connect to associate a file descriptor associated with the socket structure with a remote machine corresponding to the address of the sockaddr {} structure, and call the connect function corresponding to each protocol. Corresponding to the TCP type, sock-> OPS-> connect is inet_stream_connect.

5) inet_stream_connect: Get SK, SK = sock-> SK, lock SK, store the port number of the automatically obtained Sk in SK-> num, and use htons () function Conversion is stored in SK-& gt; sport. Then call the sk-> prot-> connect () function pointer. For TCP, It is the tcp_v4_connect () function. Set the sock-> state to ss_connecting. After the subsequent processing is complete, change the state to ss_connectted.

6) tcp_v4_connect (): Call the ip_route_connect () function to find a suitable route and store it in RT. Ip_route_connect finds the IP address of the next hop twice, finds it in the route cache or fib, and finds the neighbor of the next hop for the second time, and finds it in neigh_table. The TCP Header space is stored in the buff. Modify the IP address data in SK to modify the route, initialize the serial number of a TCP connection, call the tcp_connect () function, initialize the TCP header, and set the timer required for TCP processing. The process of establishing a connect () is over.

The client connection is closed as follows:

1) Close: In the file {} structure corresponding to a socket file descriptor, there is a member f_ops in the file_operations {} structure, and its initialization close function is the sock_close function.

2) sock_close: Call the sock_release () function. The parameter is a pointer of the socket {} structure.

3) sock_release: Call inet_release and release the socket pointer and file space.

4) inet_release: Call the inet_release function corresponding to the SOCKET protocol. If it is TCP, tcp_close is called and SK is released.

2. Data transmission process

Description of main functions and positions of each layer:

1) sock_write: Initialize the msghdr {} structure. Net/socket. c

2) sock_sendmsg: net/socket. c

3) inet_sendmsg: net/IPv4/af_net.c

4) tcp_sendmsg: Apply for a space in the sk_buff {} structure and fill in the data in the msghdr {} structure in the sk_buff space. Net/IPv4/tcp. c

5) tcp_send_skb: net/IPv4/tcp_output.c

6) tcp_transmit_skb: net/IPv4/tcp_output.c

7) ip_queue_xmit: net/IPv4/ip_output.c

8) ip_queue_xmit2: net/IPv4/ip_output.c

9) ip_output: net/IPv4/ip_output.c

10) ip_finish_output: net/IPv4/ip_output.c

11) ip_finish_output2: net/IPv4/ip_output.c

12) neigh_resolve_output: net/CORE/neighbor. c

13) dev_queue_xmit: net/CORE/dev. c

3. Data receiving process

Description of main functions and positions of each layer:

1) sock_read: Initialize msghdr {}'s structure type variable MSG, and pass the address of the data to be received to MSG. msg_iov-> iov_base. Net/socket. c

2) sock_recvmsg: Call the function pointer sock-> OPS-> recvmsg () to complete the data receiving process at the inet socket layer. sock-> ops is initialized as inet_stream_ops, and its member recvmsg function is implemented as inet_recvmsg () function. net/socket. c

3) sys_recv ()/sys_recvfrom (): corresponds to connection-oriented and connection-free protocols. Net/socket. c

4) inet_recvmsg: Call SK-> prot-> recvmsg to receive data. For TCP, this function is tcp_recvmsg net/IPv4/af_net.c.

5) tcp_recvmsg: the action of receiving data from the network protocol stack. The top-down action is triggered until this function ends. A waiting process occurs. the tcp_recvmsg function may passively wait in the sk receiving data queue. That is to say, the system will definitely modify this queue elsewhere so that tcp_recvmsg can proceed. the entry parameter SK is the sock {} pointer corresponding to the network connection. MSG is used to store received data. when receiving data, it will traverse the data in the receiving queue and find the appropriate serial number.

However, when the read queue is empty, tcp_recvmsg will call tcp_v4_do_rcv to fill the receiving queue with the backlog queue.

6) tcp_v4_rcv: The tcp_v4_rcv is called by the ip_local_deliver function. It is a "data to" request submitted from the IP layer protocol to the inet socket layer. The entry parameter SKB stores the received data, len is the length of the received data. This function first moves the SKB-> Data Pointer, points it to the TCP header, and then updates some data statistics on the TCP layer, then, some TCP values are verified. then, from the sock {} Structure Variable created in the inet socket layer, find which item is waiting for the data to arrive. this sock {} structure may have been established, or it is still in the listening port, waiting for data connection status. The returned sock structure pointer is stored in SK. Then, send the SKB to the appropriate location based on the operations of other processes on SK. The call is as follows:

The TCP packet receiver (tcp_v4_rcv) delivers the TCP packet to the destination socket for receiving. when the socket is being locked by the user, the TCP packet will be temporarily discharged into the socket's backup Queue (sk_add_backlog ). at this time, if a user thread attempts to lock the socket (lock_sock), the thread is queued into the socket for backup processing waiting queue (SK-> lock. WQ ). when a user releases a locked socket (release_sock, called in tcp_recvmsg), the TCP packet in the backup queue is immediately injected into the TCP packet processor (tcp_v4_do_rcv) for processing, then, wake up the first user in the queue to obtain the lock permission.
If the socket is not locked, when the user is reading the socket, the TCP packet will be queued into the socket's reserve Queue (tcp_prequeue) and passed to the user thread context for processing. if the bucket is not successfully added to SK-> prequeue, it can be added to the sk-> receive_queue Queue (the user thread can register with the Reserve queue column, wake up the waiting thread when the first package appears in the reserve team column .) /NET/tcp_ipv4.c

7) ip_rcv and ip_rcv_finish: receive data from Ethernet and put it into SKB. check some data and options on the IP layer, and call ip_route_input () for Route processing, determine whether IP Forwarding is performed or whether data is transmitted to a high-layer protocol. when you call the SKB-> DST-> input function pointer, the pointer may be implemented in many situations. If the routing result shows that the packet should be forwarded to other hosts, the input here is ip_forward; if the data packet is sent to the local machine, the input pointer is initialized to the ip_local_deliver function. /NET/IPv4/ip_input.c

8) ip_local_deliver and ip_local_deliver_finish: Enter the SKB parameter to store the data to be transmitted to the upper-layer protocol, and obtain information about whether the split has been obtained from the IP header, call the ip_defrag function to reorganize the data packets. Then call tcp_v4_rcv (TCP) by calling ip_prot-> handler pointer ). Ip_prot is the inet_protocol structure pointer, which is used for IP layer registration protocols, such as UDP, TCP, ICMP and so on. /NET/IPv4/ip_input.c

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.