Interaction between Linux User and kernel (2)

Source: Internet
Author: User
Interaction between Linux User State and kernel state (2) -- Linux general technology-Linux programming and kernel information. The following is a detailed description. Similarly, the function close is used to close the opened netlink socket. In the program, because the program continuously receives messages that process the kernel, it needs to receive the user's close signal to exit. Therefore, the job of disabling the socket is put in the Custom signal function sig_int for processing: [table = 400] [tr] [td]/* this signal function processes some program exit operations */static void sig_int (int signo) {struct sockaddr_nl kpeer; struct msg_to_kernel message; memset (& kpeer, 0, sizeof (kpeer); kpeer. nl_family = AF_NETLINK; kpeer. nl_pid = 0; kpeer. nl_groups = 0; memset (& message, 0, sizeof (message); message. hdr. nlmsg_len = NLMSG_LENGTH (0); message. hdr. nlmsg_f Lags = 0; message. hdr. nlmsg_type = IMP2_CLOSE; message. hdr. nlmsg_pid = getpid ();/* sends a message to the kernel. The nlmsg_type indicates that the application will shut down */sendto (skfd, & message, message. hdr. nlmsg_len, 0, (struct sockaddr *) (& kpeer), sizeof (kpeer); close (skfd); exit (0 );} [/td] [/tr] [/table] In this end function, send a "I have exited" message to the kernel, and then call the close function to close the netlink socket, exit the program. Kernel spaceWith the application kernel, the kernel space also mainly completes three tasks: n creating a netlink socket n receiving and processing data sent by the user space n sending data to the user space API function netlink_kernel_create is used to create a netlink socket, at the same time, register a callback function to receive messages that process user space: [table = 400] [tr] [td] struct sock * netlink_kernel_create (int unit, void (* input) (struct sock * sk, int len); [/td] [/tr] [/table] parameter unit indicates the netlink protocol type, such as NL_IMP2, the input parameter is the netlink message processing function defined by the kernel module. When a message reaches the netlink socket, the input function pointer is referenced. The sk parameter of the function pointer input is actually the struct sock pointer returned by the function netlink_kernel_create. sock is actually a socket kernel that represents the data structure, the socket created by the user-mode application also has a struct sock structure in the kernel. [Table = 400] [tr] [td] static int _ init (void) {rwlock_init (& user_proc.lock ); /* initialize the read/write lock * // * Create a netlink socket. The protocol type is custom ML_IMP2, and kernel_reveive is the acceptance handler */nlfd = netlink_kernel_create (NL_IMP2, kernel_receive ); if (! Nlfd)/* creation failed */{printk ("can not create a netlink socket \ n"); return-1 ;} /* register a Netfilter hook */return nf_register_hook (& imp2_ops);} [/td] [/tr] [/table] module_init (init ); the user space sends two custom message types to the kernel: IMP2_U_PID and IMP2_CLOSE, which are request and close. The kernel_receive function processes the two types of messages respectively: [table = 400] [tr] [td] DECLARE_MUTEX (receive_sem);/* initialize the semaphore */static void kernel_receive (struct sock * sk, int len) {do {struct sk_buff * skb; if (down_trylock (& receive_sem)/* Get semaphores */return;/* Get skb from the receiving queue, then perform some basic length validity verification */while (skb = skb_dequeue (& sk-> receive_queue ))! = NULL) {struct nlmsghdr * nlh = NULL; if (skb-> len> = sizeof (struct nlmsghdr )) {/* obtain the nlmsghdr structure header */nlh = (struct nlmsghdr *) skb-> data; if (nlh-> nlmsg_len> = sizeof (struct nlmsghdr )) & (skb-> len> = nlh-> nlmsg_len) {/* after the length validation is complete, process the custom message type of the application, it is mainly used to save the user's PID, that is, to save the kernel "send the message to" */if (nlh-> nlmsg_type = IMP2_U_PID) /* Request */{write_lock_bh (& user_proc.pid); user_proc.pid = nlh-> nlmsg_pid; write_unlock_bh (& user_proc. Pid);} else if (nlh-> nlmsg_type = IMP2_CLOSE)/* application close */{write_lock_bh (& user_proc.pid); if (nlh-> nlmsg_pid = user_proc.pid) user_proc.pid = 0; write_unlock_bh (& user_proc.pid) ;}}} kfree_skb (skb);} up (& receive_sem ); /* return semaphore */} while (nlfd & nlfd-> receive_queue.qlen );} [/td] [/tr] [/table] Because the kernel module may be called by multiple processes at the same time, semaphores and locks are used in the function for mutual exclusion. Skb = skb_dequeue (& sk-> receive_queue) is used to obtain messages from the socket sk receiving queue. A structure of struct sk_buff is returned, and skb-> data points to the actual netlink message. The program registers a Netfilter hook. The hook function is get_icmp, which intercepts ICMP data packets and then calls the send_to_user function to send data to the Application Space process. The sent data is the info structure variable, which is the struct packet_info structure. This structure contains two members: Source and Destination addresses. Netfilter Hook is not the focus of this article, skipped. Send_to_user is used to send data to the user space process. The call is completed by the API function netlink_unicast: [table = 400] [tr] [td] int netlink_unicast (struct sock * sk, struct sk_buff * skb, u32 pid, int nonblock); [/td] [/tr] [/table] the sk parameter is the socket returned by the netlink_kernel_create () function, the parameter skb stores the message to be sent. Its data field points to the netlink message structure to be sent. The control block of skb stores the Message address information. The parameter pid is the pid of the message receiving process, the nonblock parameter indicates whether the function is non-blocking. If it is set to 1, the function returns immediately if it does not receive the available cache. If it is set to 0, the function sleeps when it does not receive the available cache. A message sent to a user space process consists of the netlink message header, data section, and control fields. The control field contains the target address and source address to be set when the kernel sends a netlink message, messages in the kernel are managed through sk_buff, linux/netlink. h defines the NETLINK_CB macro to facilitate Message Address Settings: [table = 400] [tr] [td] # define NETLINK_CB (skb) (* (struct netlink_skb_parms *) & (skb)-> cb) for example: NETLINK_CB (skb ). pid = 0; NETLINK_CB (skb ). dst_pid = 0; NETLINK_CB (skb ). dst_group = 1;
The [/td] [/tr] [/table] field pid indicates the ID of the message sender process, that is, the source address. For the kernel, It is 0, and dst_pid indicates the ID of the Message Receiver process, that is, the target address. If the target is a group or kernel, it is set to 0. Otherwise, dst_group indicates the target group address. If the target is a process or kernel, dst_group should be set to 0. [Table = 400] [tr] [td] static int send_to_user (struct packet_info * info) {int ret; int size; unsigned char * old_tail; struct sk_buff * skb; struct nlmsghdr * nlh; struct packet_info * packet;/* calculate the total message length: the message header is added with data addition */size = NLMSG_SPACE (sizeof (* info )); /* allocate a new socket cache */skb = alloc_skb (size, GFP_ATOMIC); old_tail = skb-> tail; /* initialize a netlink message header */nlh = NLMSG_PUT (skb, 0, 0, IMP2_K_MSG, size-sizeof (* nlh);/* skip the message header, point to data zone */packet = NLMSG_DATA (nlh);/* initialize data zone */memset (packet, 0, sizeof (struct packet_info )); /* fill in the data to be sent */packet-> src = info-> src; packet-> dest = info-> dest;/* calculate the length difference of skb twice, that is, the total length of netlink */nlh-> nlmsg_len = skb-> tail-old_tail;/* sets the control field */NETLINK_CB (skb ). dst_groups = 0;/* send data */read_lock_bh (& user_proc.lock); ret = netlink_unicast (nlfd, skb, user_proc.pid, iterator); read_unlock_bh (& user_proc.lock );}
[/Td] [/tr] [/table] function initializes the netlink message header, fills in the data area, and sets the control field. All three parts are included in skb_buff, finally, call the netlink_unicast function to send the data. The function calls an important macro NLMSG_PUT of netlink. It is used to initialize the netlink message header: [table = 400] [tr] [td] # define NLMSG_PUT (skb, pid, seq, type, len) \ ({if (skb_tailroom (skb) <(int) NLMSG_SPACE (len) goto nlmsg_failure; \ _ nlmsg_put (skb, pid, seq, type, len);}) static _ inline _ struct nlmsghdr * _ nlmsg_put (struct sk_buff * skb, u32 pid, u32 seq, int type, int len) {struct nlmsghdr * nlh; int size = NLMSG_LENGTH (len); nlh = (struct nl Msghdr *) skb_put (skb, NLMSG_ALIGN (size); nlh-> nlmsg_type = type; nlh-> nlmsg_len = size; nlh-> nlmsg_flags = 0; nlh-> nlmsg_pid = pid; nlh-> nlmsg_seq = seq; return nlh ;} [/td] [/tr] [/table] This macro must be noted that the nlmsg_failure label is called, so this label should be defined in the program. Use the sock_release function in the kernel to release the netlink socket: void sock_release (struct socket * sock) created by the netlink_kernel_create () function. The program releases netlink sockets and netfilter hook in the exit module: [table = 400] [tr] [td] static void _ exit fini (void) {if (nlfd) {sock_release (nlfd-> socket ); /* release netlink socket */} nf_unregister_hook (& imp2_ops);/* remove the netfilter hook */}
[/Td]
[/Tr] [/table]
Related Article

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.