终于搞定了自己需要的这种通信机制:由内核态向用户态反馈信息;
先看代码,内核的:
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/timer.h>
- #include <linux/time.h>
- #include <linux/types.h>
- #include <net/sock.h>
- #include <net/netlink.h> //it include linux/netlink.h
-
- #define NETLINK_TEST 17
- #define MAX_MSGSIZE 1024
-
- struct sock *nl_sk = NULL;
-
-
- int stringlength(char *s)
- {
- int slen = 0;
-
- for(; *s; s++){
- slen++;
- }
-
- return slen;
- }
-
-
- void sendnlmsg(char *message)
- {
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- int len = NLMSG_SPACE(MAX_MSGSIZE);
- int slen = 0;
-
- if(!message || !nl_sk){
- return;
- }
-
-
- skb = alloc_skb(len, GFP_KERNEL);
- if(!skb){
- printk(KERN_ERR "my_net_link: alloc_skb Error./n");
- return;
- }
-
- slen = stringlength(message);
-
-
- nlh = nlmsg_put(skb, 0, 0, 0, MAX_MSGSIZE, 0);
-
- NETLINK_CB(skb).pid = 0;
- NETLINK_CB(skb).dst_group = 1;
-
- message[slen] = '/0';
- memcpy(NLMSG_DATA(nlh), message, slen+1);
- printk("my_net_link: send message '%s'./n", (char *)NLMSG_DATA(nlh));
-
-
- netlink_broadcast(nl_sk, skb, 0, 1, GFP_KERNEL);
- return;
- }
-
-
- int netlink_init(void)
- {
- int i = 10;
- struct completion cmpl;
-
- nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 1,
- NULL, NULL, THIS_MODULE);
-
- if(!nl_sk){
- printk(KERN_ERR "my_net_link: create netlink socket error./n");
- return 1;
- }
-
- printk("my_net_link: create netlink socket ok./n");
- while(i--){
- init_completion(&cmpl);
- wait_for_completion_timeout(&cmpl, 3 * HZ);
- sendnlmsg("I am from kernel!");
-
- }
-
- return 0;
- }
-
- static void netlink_exit(void)
- {
- if(nl_sk != NULL){
- sock_release(nl_sk->sk_socket);
- }
-
- printk("my_net_link: self module exited/n");
- }
-
- module_init(netlink_init);
- module_exit(netlink_exit);
-
- MODULE_AUTHOR("donglp");
- MODULE_LICENSE("GPL");
用户的:
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <string.h>
- #include <asm/types.h>
- #include <linux/netlink.h>
- #include <linux/socket.h>
- #include <errno.h>
-
- #define NETLINK_TEST 17
- #define MAX_PAYLOAD 1024 // maximum payload size
-
-
- int main(int argc, char* argv[])
- {
- struct sockaddr_nl src_addr, dest_addr;
- struct nlmsghdr *nlh = NULL;
- struct iovec iov;
- struct msghdr msg;
- int sock_fd, retval;
-
-
- sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
- if(sock_fd == -1){
- printf("error getting socket: %s", strerror(errno));
- return -1;
- }
-
-
- memset(&src_addr, 0, sizeof(src_addr));
- src_addr.nl_family = PF_NETLINK;
- src_addr.nl_pid = getpid();
- src_addr.nl_groups = 1;
-
- retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
- if(retval < 0){
- printf("bind failed: %s", strerror(errno));
- close(sock_fd);
- return -1;
- }
-
-
- nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
- if(!nlh){
- printf("malloc nlmsghdr error!/n");
- close(sock_fd);
- return -1;
- }
-
- memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
- iov.iov_base = (void *)nlh;
- iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
-
- memset(&msg, 0, sizeof(msg));
- memset(&dest_addr, 0, sizeof(dest_addr));
- msg.msg_name = (void *)&dest_addr;
- msg.msg_namelen = sizeof(dest_addr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
-
- while(1){
- recvmsg(sock_fd, &msg, 0);
- printf("Received message: %s/n", NLMSG_DATA(nlh));
- }
-
- close(sock_fd);
-
- return 0;
- }
Makefile文件:
- obj-m := self.o
- KERNELBUILD := /lib/modules/`uname -r`/build
- default:
- @echo " BUILD kmod"
- @make -C $(KERNELBUILD) M=$(shell pwd) modules
- gcc -o u u.c
- clean:
- @echo " CLEAN kmod"
- @rm -rf *.o
- @rm -rf .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers .*.d
编译方法:直接make
如何看效果:
必须先运行insmod self.ko
然后在另外一个终端运行./u
就能看到效果,关注dmesg信息和./u显示出来的信息。