http://blog.csdn.net/hustfoxy/article/details/8706275
This article mainly explains through the NetLink communication mechanism, realizes the user state and the kernel state data transmission concretely. Our kernel environment is version 2.6.35.6.
The </usr/include/linux/netlink.h> file contains predefined protocols that have been defined by the NetLink protocol cluster:
[CPP] View Plain copy #define netlink_route 0 /* Routing/device hook */ #define NETLINK_UNUSED 1 /* Unused number */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ #define Netlink_firewall &nbsP; 3 /* firewalling hook */ #define netlink_inet_diag 4 /* inet socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/ iptables ulog */ #define NETLINK_XFRM 6 /* ipsec */ # Define netlink_selinux 7 /* selinux event notifications */ #define NETLINK_ISCSI 8 /* open-iscsi * / #define netlink_audit 9 /* auditing */ #define netlink_fib_lookup 10 #define NETLINK_CONNECTOR 11 #define NETLINK_NETFILTER 12 /* netfilter subsystem */ #define &NBSP;NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG &nbsP; 14 /* decnet routing messages */ #define netlink_kobject_uevent 15 /* Kernel messages to userspace */ #define NETLINK_GENERIC 16 /* leave room for netlink_dm (dm events) */ #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ #define NETLINK_ECRYPTFS 19 #define NETLINK_MYTEST 20
If we develop a new protocol in the NetLink protocol cluster, just define the protocol number in that file, for example, we define a custom protocol with a protocol number of 20 based on the NetLink protocol cluster, as shown above. At the same time remember, the kernel header file directory netlink.h also do the corresponding modification, in my system its path is:/usr/src/kernels/2.6.35.6-45.fc14.i686/include/linux/netlink.h
We can then use this protocol in the development of user space and kernel space modules, it should be explained that if you do not add the protocol number in these two files, you need to add the two protocol numbers in the specific communication implementation code file, which is used in my specific implementation.
User-State communication Code (MYNLUSR.C):
[CPP] View plain copy #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <linux/netlink.h> #include <linux/socket.h> #define NETLINK_MYTEST 20 #define MAX_PAYLOAD 1024 int Main (INT&NBSP;ARGC,&NBSP;CHAR&NBSP;**&NBSP;ARGV) { struct sockaddr_nl src_addr,dest_addr; struct nlmsghdr *nlh = NULL; struct msghdr msg; struct iovec iov; int sock_fd = -1; /* Create socket */ if ( -1 == (sock_fd = Socket (af_netlink,sock_raw,netlink_mytest)) { printf ("Can ' t create netlink socket!\n"); return -1; } /* SET SRC_ADDR structure * * memset (&src_addr, 0, sizeof (src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_ Pid = getpid ()/* own pid*/ src_addr.nl_groups = 0; /* bind sockets and NetLink address structures */ if ( -1 == bind sock_fd, (struct sockaddr*) &src_addr, sizeof (src_ Addr)) {&NBsp; printf ("Can" t bind sock_fd with Sockaddr_nl "); return -1; } if (null == nlh= (struct nlmsghdr*) malloc (Nlmsg_space (max_payload))) { printf ("alloc mem failed!\n"); return -1; } memset (nlh, 0, max_payload); /* Fill NetLink message head */ nlh->nlmsg_len = nlmsg_space (MAX_PAYLOAD); nlh->nlmsg_pid = getpid (); nlh->nlmsg_type = NLMSG_NOOP; nlh->nlmsg_flags = 0; /* Set message content for NetLink */ strcpy (Nlmsg_data (NLH), argv[1]); memset (&iov, 0, sizeof (IOV)); iov.iov_base = (void *) nlh; iov.iov_len = nlh->nlmsg_len; /* Settings dest_ Addr Structure */ memset (&dest_addr, 0, sizeof (dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0;/* is the PID of the destination address, which is sent to the kernel */ dest_addr.nl_groups = 0; memset (&msg, 0 , sizeof (MSg); msg.msg_name = (void *) &dest_addr; msg.msg_namelen = sizeof (dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; /* sends messages through Netlink socket to the content */ sendmsg (sock_fd, &msg, 0); /* accepts kernel messages */ printf ("Waiting message from kernel!\n "); memset ((char *) Nlmsg_data (NLH), 0,1024); recvmsg (sock_fd,&msg,0); printf ("response:%s\n" , Nlmsg_data (NLH)); /* Close netlink socket */ &Nbsp; close (SOCK_FD); free (NLH); return 0; }
Kernel-State Communication Code (MYNLKERN.C):
[CPP] View plain copy #include <linux/kernel.h> #include <linux/module.h> # include <linux/moduleparam.h> #include <linux/skbuff.h> #include <linux/init.h> #include <linux/ip.h> #include <linux/ types.h> #include <linux/sched.h> #include <linux/netlink.h> #include <net/sock.h> #include <net/netlink.h> #define NETLINK_MYTEST 20 #define MAX_MSGSIZE 1024 struct sock *nl_sk = NULL; static void sendnlmsg (char * Message, int dstpid) { struct sk_buff *skb; struct nlmsghdr *nlh; int len = nlmsg_space (max_msgsize); int slen = 0; if (!message | | !nl_sk) { return ; } /* for the new Sk_buffer application space */ &NBSP;SKB&NBSP;=&NBSP;ALLOC_SKB (Len,gfp_kernel); if (!SKB) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_err "my_net_link:alloc_skb error!\n"); return ; } slen = strlen (message); /* use Nlmsg_put to set NetLink message head */ nlh = nlmsg_put (skb,0,0,0,max_msgsize,0); &NBSP;&NBSP;&NBSP;&NBSP;&NBsp; /* Set the NetLink control block */ &NBSP;&NBSP;&NBSP;&NBSP;NETLINK_CB (SKB). PID = 0;/* the ID of the sender of the message, if it is issued within the 0*/ &NBSP;&NBSP;&NBSP;&NBSP;NETLINK_CB (SKB). dst_group = 0;/* If the purpose of the group is the kernel or a process, the field 0*/ message[slen] = '; ' memcpy (Nlmsg_data (NLH), message,slen+1); /* sends messages to user space via Netlink_unicast */ &NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("kernel:begin send\n"); netlink_ Unicast (nl_sk,skb,dstpid,0); printk ("kernel:send ok!\n"); return ; } Static void nl_data_ready ( STRUCT&NBSP;SK_BUFF*&NBSP;SKB) { struct nlmsghdr *nlh; u64 rlen; void *data; while (skb->len >= nlmsg_space (0)) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;NLH&NBSP;=&NBSP;NLMSG_HDR (SKB); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("Nlh->nlmsg_pid=%u skb->len =%d nlmsg_space" (0) =%d\n ", Nlh->nlmsg_pid,skb->len,nlmsg_space (0)); if (nlh->nlmsg_len < nlmsg_hdrlen | | skb->len < nlh->nlmsg_len) return ; rlen = nlmsg_align (Nlh->nlmsg_len); if (rlen&Nbsp;> skb->len) rlen = skb->len; data = nlmsg_data (NLH); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("received netlink message: %s\n", (char *) data); skb_pull (skb, rlen); sendnlmsg (" Send from kernel ", nlh->nlmsg_pid); } &NBSP;&NBSP;PRINTK ("received finished!\n"); } static int __ Init myinit_module (void) { printk ("my netlink in! \ n "); nl_sk = netlink_kernel_create (&init_net, netlink_mytest, 0, nl_data_ready, null, this_module); if (!nl_sk) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_err "My_net_link: create netlink socket error!\n "); return 1; }else{ return 0; } } static void __exit Myexit_module (void) { printk ("my netlink out!\n"); if (nl_sk != null) { sock_release (nl_sk->sk_socket); } }   Module_author ("Fang xieyun"); module_license ("GPL"); Module_init (myinit _module); module_exit (myexit_module);