Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Communication between user Program and Kernel in linux

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the example analysis of the communication between the user program and the kernel in linux, which has a certain reference value, and interested friends can refer to it. I hope you will gain a lot after reading this article.

Brief introduction

Under linux, the ways for user programs to communicate with the kernel are generally ioctl, proc file system, and the remaining one is the Netlink socket. Let's introduce netlink first.

Netlink is a very good way of two-way data transmission between kernel and user applications. User-mode applications can use the powerful functions provided by netlink by using standard socket API, while kernel-mode applications need to use special kernel API to use netlink.

Netlink has the following advantages over system calls, ioctl, and / proc file systems:

1. In order to use netlink, users only need to add a new type of netlink protocol definition to include/linux/netlink.h, such as # define NETLINK_MYTEST 17, and then the kernel and user-mode applications can immediately exchange data using this netlink protocol type through socket API. But the system call needs to add new system calls, ioctl needs to add devices or files, which requires a lot of code, and the proc file system needs to add new files or directories under / proc, which will make the already chaotic / proc even more chaotic.

2. Netlink is an asynchronous communication mechanism. Messages passed between the kernel and user-mode applications are saved in the socket cache queue. Sending messages is only saved in the receiving queue of the receiver's socket, and there is no need to wait for the receiver to receive the message. However, the system call and ioctl are synchronous communication mechanisms. If the transmitted data is too long, it will affect the scheduling granularity.

3. The kernel part using netlink can be implemented as a module, the application part and kernel part using netlink have no compile-time dependence, but the system call has dependence, and the implementation of the new system call must be statically connected to the kernel, it can not be implemented in the module, and the application using the new system call needs to rely on the kernel at compile time.

4.netlink supports multicasting, and kernel modules or applications can multicast messages to a netlink group, and any kernel module or application belonging to the neilink group can receive the message. This feature is used in the kernel event notification mechanism to the user state, and any application interested in kernel events can receive kernel events sent by the subsystem. The use of this mechanism will be introduced in a later article.

5. The kernel can first initiate a session using netlink, but system calls and ioctl can only be initiated by user applications.

6.netlink uses standard socket API, so it is easy to use, but system calls and ioctl require special training to use.

The main purpose of the following two parts of code is to use the netlink mechanism to realize the communication between the user program and the kernel. Specifically, when the user program executes. / netlink-S [I am a parameter] or. / netlink-G, the kernel will return "S know you!" And "I know you!" These two strings are then output. Printing is added to both the kernel and the user program.

Kernel module

1. The compilation rule ruler.dir that Makefile depends on

PWD: = $(shell pwd) all: modules romfs modules: $(MAKE)-C $(KDIR) mm $(PWD) modules @ echo $(OBJ) modules_install: $(MAKE)-C $(KDIR) MB $(PWD) modules_install romfs: cp-rf *. Ko $(MODULES_BUILD_DIR) clean: rm *. O *. Ko *. Mod.* Module.* modules.* rm-rf $(MODULES_BUILD_DIR) obj-m: = $(MOD_NAME). O

2.Makefile

KERNEL_MODULES: = netlink export MODULES_ROOT_DIR: = $(shell pwd) export MODULES_BUILD_DIR: = $(MODULES_ROOT_DIR) / build export KDIR: = / lib/modules/$ (shell uname-r) / build # this line is to retrieve the kernel directory under the system (ubuntu) all: init modules romfs init: mkdir-p $(MODULES_BUILD_DIR) modules:$ (patsubst%, _ dir_%, $(KERNEL_MODULES)) $(patsubst%, _ dir_%) (KERNEL_MODULES): @ echo @ echo Building $(patsubst _ dir_%,%, $@) $(MAKE)-C $(patsubst _ dir_%,%, $@) all romfs: $(patsubst%, _ romfs_%, $(KERNEL_MODULES)) $(patsubst%, _ romfs_%, $(KERNEL_MODULES)): $(MAKE)-C $(patsubst _ romfs_%,%, $@) romfs clean: $(patsubst%, _ clean_% $(KERNEL_MODULES)) $(RM) $(BUILD_DIR) $(patsubst%, _ clean_%, $(KERNEL_MODULES)): @ echo @ echo Cleaning $(patsubst _ dir_%,%, $@) $(MAKE)-C $(patsubst _ clean_%,%, $@) clean .PHONY:

3.. / netlink/netlink.c

/ * * netlink.c * * Created on: 2014 * Author: cr * / # include # include "usrlink.h" MODULE_LICENSE ("Dual BSD/GPL"); MODULE_AUTHOR ("MDAXIA"); struct sock * netlink_fd; static void netlink_to_user (int dest, void * buf, int len) {struct nlmsghdr * nl; struct sk_buff * skb; int size Size = NLMSG_SPACE (len); skb = alloc_skb (size, GFP_ATOMIC); if (! skb | |! buf) {printk (KERN_ALERT "netlink_to_user skb of buf null!\ n"); return;} nl = nlmsg_put (skb, 0,0,0, NLMSG_SPACE (len)-sizeof (struct nlmsghdr), 0); NETLINK_CB (skb). Pid = 0; NETLINK_CB (skb). Dst_group = 0 Memcpy (NLMSG_DATA (nl), buf, len); nl- > nlmsg_len = (len > 2)? (len-2): len; netlink_unicast (netlink_fd, skb, dest, MSG_DONTWAIT); printk (KERN_ALERT "K send packet success\ n");} static int process_hello_get (int dest, void * buf, int len) {printk (KERN_ALERT "In process_hello get!\ n"); memcpy (buf, "I known you!", 13); netlink_to_user (dest, buf, 13); return NET_OK } static int process_hello_set (int dest, void * buf, int len) {printk (KERN_ALERT "In process_hello set!% s\ n", (char *) buf); memcpy (buf, "S known you!", 13); netlink_to_user (dest, buf, 13); return NET_OK;} static void netlink_process_packet (struct nlmsghdr * nl) {int ret Switch (nl- > nlmsg_type) {case HELLO_GET: ret = process_hello_get (nl- > nlmsg_pid, NLMSG_DATA (nl), nl- > nlmsg_len); break; case HELLO_SET: ret = process_hello_set (nl- > nlmsg_pid, NLMSG_DATA (nl), nl- > nlmsg_len); break; default:break;} static void netlink_recv_packet (struct sk_buff * _ skb) {struct sk_buff * skb; struct nlmsghdr * nlhdr Skb = skb_get (_ _ skb); if (skb- > len > = sizeof (struct nlmsghdr)) {nlhdr = (struct nlmsghdr *) skb- > data; if (nlhdr- > nlmsg_len > = sizeof (struct nlmsghdr) & & _ skb- > len > = nlhdr- > nlmsg_len) {netlink_process_packet (nlhdr);}} else printk (KERN_ALERT "Kernel receive msg length error!\ n") } static int _ init netlink_init (void) {netlink_fd = netlink_kernel_create (& init_net, USER_NETLINK_CMD, 0, netlink_recv_packet, NULL, THIS_MODULE); if (NULL = = netlink_fd) {printk (KERN_ALERT "Init netlink!\ n"); return-1;} printk (KERN_ALERT "Init netlink success!\ n"); return 0 } static void _ exit netlink_exit (void) {netlink_kernel_release (netlink_fd); printk (KERN_ALERT "Exit netlink!\ n");} module_init (netlink_init); module_exit (netlink_exit)

4.. / netlink/usrlink.h

/ * usrlink.h * * Created on: 2014 Qian? 7 "? * Author: cr * / # ifndef USRLINK_H_ # define USRLINK_H_ # define USER_NETLINK_CMD 25 # define MAXMSGLEN 1024 typedef enum error_e {NET_ERROR, NET_OK, NET_PARAM, NET_MEM, NET_SOCK,} netlink_err; typedef enum module_e {HELLO_CMD = 1,} netlink_module; typedef enum type_e {HELLO_SET, HELLO_GET,} netlink_type # endif / * USRLINK_H_ * /

5.. / netlink/Makefile

MOD_NAME: = netlink $(MOD_NAME)-objs: netlink.o-include $(MODULES_ROOT_DIR) / rules.dir .PHONY:

6. Compilation mode.

Makefile and rulers.dir are under Knetlink/, and netlink.c, netlink.h and Makefile are under Knetlink/netlink/ directory. When compiling, execute Make under the Knetlink directory.

User program

The Makefile of the user program will not be released here. I built the project directly under eclipse and compiled it automatically.

1. Netlink.c

/ * usrlink.c * * Created on: 2014 Qian? Author: cr * / # include # include "usrlink.h" int netlink_sock_init (netlink_sock * netlink_s, int module, int protocol) {netlink_s- > sock = socket (PF_NETLINK, SOCK_RAW, protocol); if (netlink_s- > sock)

< 0) return NET_SOCK; memset(&netlink_s->

Src, 0, sizeof (netlink_s- > src); netlink_s- > src.nl_family = AF_NETLINK; netlink_s- > src.nl_pid = module; netlink_s- > src.nl_groups = 0; if (netlink_s- > sock, (struct sockaddr *) & netlink_s- > src, sizeof (netlink_s- > src))

< 0) return NET_SOCK; netlink_s->

Dest.nl_family = AF_NETLINK; netlink_s- > dest.nl_pid = 0; netlink_s- > dest.nl_groups = 0; return NET_OK;} int netlink_send (netlink_sock * netlink_s, int type, char * sbuf, int slen, char * rbuf, int * rlen) {struct msghdr msg; struct nlmsghdr * nlhdr = NULL; struct iovec iov; int ret; nlhdr = (struct nlmsghdr *) malloc (NLMSG_SPACE (MAXMSGLEN)); if (NULL = nlhdr) return NET_MEM Memcpy (NLMSG_DATA (nlhdr), sbuf, slen); nlhdr- > nlmsg_len = NLMSG_SPACE (slen); nlhdr- > nlmsg_pid = netlink_s- > src.nl_pid; nlhdr- > nlmsg_type = type; nlhdr- > nlmsg_flags = 0; iov.iov_base = (void *) nlhdr; iov.iov_len = nlhdr- > nlmsg_len; msg.msg_name = (void *) & (netlink_s- > dest); msg.msg_namelen = sizeof (netlink_s- > dest) Msg.msg_iov = & iov; msg.msg_iovlen = 1; ret = sendmsg (netlink_s- > sock, & msg, 0); if (ret

< 0) { printf("Send fail\n"); goto error; } ret = recvmsg(netlink_s->

Sock, & msg, 0); if (ret

< 0) { printf("Read fail\n"); goto error; } memcpy(rbuf, NLMSG_DATA(nlhdr), nlhdr->

Nlmsg_len); * rlen = nlhdr- > nlmsg_len; return NET_OK; error: free (nlhdr); return NET_SOCK;} int netlink_sock_deinit (netlink_sock * netlink_s) {close (netlink_s- > sock); memset (netlink_s, 0, sizeof (netlink_sock)); return NET_OK;}

2. Netlink.h

/ * * usrlink.h * * Created on: 2014 * Author: cr * / # include # ifndef USRLINK_H_ # define USER_NETLINK_CMD 25 # define MAXMSGLEN 1024 typedef enum error_e {NET_ERROR, NET_OK, NET_PARAM, NET_MEM, NET_SOCK,} netlink_err; typedef enum module_e {HELLO_CMD = 1,} netlink_module Typedef enum type_e {HELLO_SET, HELLO_GET,} netlink_type; typedef struct usr_sock_h {int sock; struct sockaddr_nl dest; struct sockaddr_nl src;} netlink_sock; int netlink_sock_init (netlink_sock * netlink_s, int module, int protocol); int netlink_sock_deinit (netlink_sock * netlink_s); int netlink_send (netlink_sock * netlink_s, int type, char * sbuf, int slen, char * rbuf, int * rlen) # endif / * USRLINK_H_ * /

3. Main.c

/ * main.c * * Created on: 2014 Qian? 7 "? * Author: cr * / # include # include" usrlink.h "int parse_ret (int ret) {switch (ret) {case NET_OK: return ret; case NET_ERROR: printf (" error\ n "); goto exit_p; case NET_MEM: printf (" Memory error\ n "); goto exit_p; case NET_PARAM: printf (" Param error\ n "); goto exit_p Case NET_SOCK: printf ("Socket error\ n"); goto exit_p; default:break;} exit_p: return NET_ERROR;} void usage (void) {printf ("Usage: Netlink-G\ n\ tMurray S\ n");} int main (int argc, char * * argv) {netlink_sock hackers argv; char rbuf [1024]; char sbuf [1024]; int ret, type, slen = 0, rlen = 0 Ret = netlink_sock_init (& h_sock, HELLO_CMD, USER_NETLINK_CMD); if (NET_OK! = parse_ret (ret)) goto exit_p; bzero (& rbuf, sizeof (rbuf)); bzero (& sbuf, sizeof (sbuf)); if (argc)

< 3) { usage(); goto exit_p; } if(!strncmp("-G", argv[1], 2)) type = HELLO_GET; else if(!strncmp("-S", argv[1], 2)) type = HELLO_SET; strcpy(sbuf, argv[2]); slen = strlen(sbuf); ret = netlink_send(&h_sock, type, sbuf, slen, rbuf, &rlen); if(NET_OK != parse_ret(ret)) goto exit_p; if(rlen >

0) {rbuf [rlen] ='\ 0mm; printf ("K rep [len =% d]:% s\ n", rlen, rbuf);} printf ("K [len =% d]:% s\ n", rlen, rbuf); exit_p: netlink_sock_deinit (& h_sock); return 0 } Thank you for reading this article carefully. I hope the article "sample Analysis of user Program Communication with Kernel in linux" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report