After three days of hard work, we finally achieved the communication mechanism we needed: the kernel state gives feedback to the user State;
First look at the code, the kernel:
# Include <Linux/init. h> <br/> # include <Linux/module. h> <br/> # include <Linux/Timer. h> <br/> # include <Linux/time. h> <br/> # include <Linux/types. h> <br/> # include <net/sock. h> <br/> # include <net/Netlink. h> // It include Linux/Netlink. h </P> <p> # define netlink_test 17 <br/> # define max_msgsize 1024 </P> <p> struct sock * nl_sk = NULL; </P> <p> // get string's length <br/> int stringlength (char * s) <br/>{< br/> int SL En = 0; </P> <p> for (; * s; s ++) {<br/> slen ++; <br/>}</P> <p> return slen; <br/>}</P> <p> // send message by Netlink <br/> void sendnlmsg (char * message) <br/>{< br/> struct sk_buff * SKB; <br/> struct nlmsghdr * NlH; <br/> int Len = nlmsg_space (max_msgsize ); <br/> int slen = 0; </P> <p> If (! Message |! Nl_sk) {<br/> return; <br/>}</P> <p> // allocate a new sk_buffer <br/> SKB = alloc_skb (Len, gfp_kernel ); <br/> If (! SKB) {<br/> printk (kern_err "my_net_link: alloc_skb error. /n "); <br/> return; <br/>}</P> <p> slen = stringlength (Message ); </P> <p> // initialize the header of Netlink message <br/> NlH = nlmsg_put (SKB, 0, 0, 0, max_msgsize, 0 ); </P> <p> netlink_cb (SKB ). PID = 0; // from kernel <br/> netlink_cb (SKB ). dst_group = 1; // multi cast </P> <p> message [slen] = '/0'; <br/> memcpy (nlmsg_data (NLH), message, slen + 1); <br/> PR Intk ("my_net_link: Send message '% s '. /n ", (char *) nlmsg_data (NLH); </P> <p> // send message by multi cast <br/> netlink_broadcast (nl_sk, SKB, 0, 1, gfp_kernel); <br/> return; <br/>}</P> <p> // initialize Netlink <br/> int netlink_init (void) <br/>{< br/> int I = 10; <br/> struct completion CMPL; </P> <p> nl_sk = netlink_kernel_create (& init_net, netlink_test, 1, <br/> null, null, this_module); </P> <p> If (! Nl_sk) {<br/> printk (kern_err "my_net_link: Create netlink socket error. /n "); <br/> return 1; <br/>}</P> <p> printk (" my_net_link: Create netlink socket OK. /n "); <br/> while (I --) {<br/> init_completion (& CMPL); <br/> wait_for_completion_timeout (& CMPL, 3 * Hz ); <br/> sendnlmsg ("I am from kernel! "); </P> <p >}</P> <p> return 0; <br/>}</P> <p> static void netlink_exit (void) <br/>{< br/> If (nl_sk! = NULL) {<br/> sock_release (nl_sk-> sk_socket); <br/>}</P> <p> printk ("my_net_link: self module exited/N "); <br/>}</P> <p> module_init (netlink_init); <br/> module_exit (netlink_exit ); </P> <p> module_author ("donglp"); <br/> module_license ("GPL ");
User's:
# Include <sys/STAT. h> <br/> # include <unistd. h> <br/> # include <stdio. h> <br/> # include <stdlib. h> <br/> # include <sys/socket. h> <br/> # include <sys/types. h> <br/> # include <string. h> <br/> # include <ASM/types. h> <br/> # include <Linux/Netlink. h> <br/> # include <Linux/socket. h> <br/> # include <errno. h> </P> <p> # define netlink_test 17 <br/> # define max_payload 1024 // maximum payload size </P> <p> int main (INT argc, Char * argv []) <br/>{< br/> struct sockaddr_nl src_addr, dest_addr; <br/> struct nlmsghdr * NlH = NULL; <br/> struct iovec IOV; <br/> struct msghdr MSG; <br/> int sock_fd, retval; </P> <p> // create a socket <br/> sock_fd = socket (pf_netlink, sock_raw, netlink_test); <br/> If (sock_fd =-1) {<br/> printf ("error getting socket: % s", strerror (errno )); <br/> return-1; <br/>}</P> <p> // to prepare bindi Ng <br/> memset (& src_addr, 0, sizeof (src_addr); <br/> src_addr.nl_family = pf_netlink; <br/> src_addr.nl_pid = getpid (); // self PID <br/> src_addr.nl_groups = 1; // multi cast </P> <p> retval = BIND (sock_fd, (struct sockaddr *) & src_addr, sizeof (src_addr); <br/> If (retval <0) {<br/> printf ("bind failed: % s", strerror (errno )); <br/> close (sock_fd); <br/> return-1; <br/>}</P> <p> // to prepare Recv MSG <br/> NlH = (struct nlmsghdr *) malloc (nlmsg_space (max_payload); <br/> If (! NLH) {<br/> printf ("malloc nlmsghdr error! /N "); <br/> close (sock_fd); <br/> return-1; <br/>}</P> <p> memset (NLH, 0, nlmsg_space (max_payload); <br/> IOV. iov_base = (void *) NlH; <br/> IOV. iov_len = nlmsg_space (max_payload); </P> <p> memset (& MSG, 0, sizeof (MSG); <br/> memset (& dest_addr, 0, sizeof (dest_addr); <br/> MSG. msg_name = (void *) & dest_addr; <br/> MSG. msg_namelen = sizeof (dest_addr); <br/> MSG. msg_iov = & IOV; <br/> MSG. msg_iovlen = 1; </P> <p> // read message from kernel <br/> while (1) {<br/> recvmsg (sock_fd, & MSG, 0 ); <br/> printf ("received message: % s/n", nlmsg_data (NLH); <br/>}</P> <p> close (sock_fd ); </P> <p> return 0; <br/>}< br/>
MAKEFILE file:
OBJ-M: = self. O <br/> kernelbuild: =/lib/modules/'uname-R'/build <br/> default: <br/> @ echo "build kmod" <br/> @ Make-C $ (kernelbuild) M = $ (shell PWD) Modules <br/> gcc-o u. c <br/> clean: <br/> @ echo "clean kmod" <br/> @ rM-RF *. O <br/> @ rM-RF. depend. *. CMD *. ko *. mod. c. tmp_versions *. symvers. *. d
Compile method: make directly
View results:
You must first run insmod self. Ko
Then run./U on another terminal.
You can see the effect and follow the dmesg information and./u information;
Here is an article that implements interactive communication between users and the kernel:
Http://prolqspace.spaces.live.com/blog/cns! 7240de3b63f5b841! 939. Entry