- make
- 另开一个窗口 运行dmesg -w
- insmod ktest.ko
- ./utest
Last active
August 7, 2020 02:43
-
-
Save lflish/15e85da8bb9200794255439d0563b195 to your computer and use it in GitHub Desktop.
用户层与内核层通信 netlink
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file: ktest.c | |
* @brief: kernel example | |
* @author: lflish | |
* @date: 2018-8-1 | |
* @email: hxy.gold@gmail.com | |
* kernel version: 3.10.0-862 | |
**/ | |
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/skbuff.h> | |
#include <linux/init.h> | |
#include <linux/ip.h> | |
#include <linux/types.h> | |
#include <linux/sched.h> | |
#include <net/sock.h> | |
#include <linux/netlink.h> | |
MODULE_LICENSE("GPL"); | |
MODULE_AUTHOR("lflish"); | |
#define MAX_MSGSIZE 125 | |
#define NETLINK_TEST 30 | |
struct sock *nl_sk = NULL; | |
//向用户空间发送消息的接口 | |
int sendnlmsg(char *message,int pid) | |
{ | |
struct sk_buff *skb; | |
struct nlmsghdr *nlh; | |
int slen = 0; | |
if(!message || !nl_sk){ | |
return -1; | |
} | |
slen = strlen(message); | |
// 为新的 sk_buffer申请空间 | |
skb = nlmsg_new(slen, GFP_ATOMIC); | |
if(!skb){ | |
printk(KERN_ERR "my_net_link: alloc_skb Error./n"); | |
return -2; | |
} | |
//用nlmsg_put()来设置netlink消息头部 | |
nlh = nlmsg_put(skb, 0, 0, NETLINK_TEST, slen, 0); | |
if(nlh == NULL){ | |
printk("nlmsg_put failauer \n"); | |
nlmsg_free(skb); | |
return -1; | |
} | |
memcpy(nlmsg_data(nlh), message, slen); | |
//通过netlink_unicast()将消息发送用户空间由pid所指定了进程号的进程 | |
netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); | |
printk("send OK!\n"); | |
return 0; | |
} | |
static void nl_data_ready(struct sk_buff *skb) | |
{ | |
struct nlmsghdr *nlh = NULL; | |
char *umsg = NULL; | |
char kmsg[] = "hello users!!!"; | |
if(skb->len >= nlmsg_total_size(0)) | |
{ | |
nlh = nlmsg_hdr(skb); | |
umsg = NLMSG_DATA(nlh); | |
if(umsg) | |
{ | |
printk("kernel recv from user: %s\n", umsg); | |
sendnlmsg (kmsg, nlh->nlmsg_pid); | |
} | |
} | |
} | |
struct netlink_kernel_cfg cfg = { | |
.input = nl_data_ready, /* set recv callback */ | |
}; | |
int myinit_module(void) | |
{ | |
printk("my netlink in\n"); | |
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg); | |
if(nl_sk == NULL) | |
printk("kernel_create error\n"); | |
return 0; | |
} | |
void mycleanup_module(void) | |
{ | |
printk("my netlink out!\n"); | |
sock_release(nl_sk->sk_socket); | |
netlink_kernel_release(nl_sk); | |
} | |
module_init(myinit_module); | |
module_exit(mycleanup_module); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MODULE_NAME :=ktest | |
obj-m :=$(MODULE_NAME).o | |
KERNELDIR := /lib/modules/$(shell uname -r)/build | |
PWD := $(shell pwd) | |
all: user kernel | |
kernel: | |
$(MAKE) -C $(KERNELDIR) M=$(PWD) | |
user: utest.c | |
gcc utest.c -o utest | |
clean: | |
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean | |
rm -rf utest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file: ktest.c | |
* @brief: kernel example | |
* @author: lflish | |
* @date: 2018-8-1 | |
* @email: hxy.gold@gmail.com | |
**/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
/* /usr/include/linux/netlink.h */ | |
#include <linux/netlink.h> | |
#define NETLINK_TEST 30 | |
int main() | |
{ | |
/* 建立socket */ | |
int skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST); | |
if(skfd == -1){ | |
perror("create socket error\n"); | |
return -1; | |
} | |
/* netlink socket */ | |
struct sockaddr_nl nladdr; | |
/*init netlink socket */ | |
nladdr.nl_family = AF_NETLINK; /* AF_NETLINK or PE_NETLINK */ | |
nladdr.nl_pad = 0; /* not use */ | |
nladdr.nl_pid = 0; /* 传送到内核 */ | |
nladdr.nl_groups = 0; /* 单播*/ | |
/* bing 绑定netlink socket 与socket */ | |
if( 0 != bind(skfd, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl))){ | |
perror("bind() error\n"); | |
close(skfd); | |
return -1; | |
} | |
/* 构造msg消息*/ | |
struct msghdr msg; | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_name = (void *)&(nladdr); | |
msg.msg_namelen = sizeof(nladdr); | |
#define MAX_MSGSIZE 1024 | |
char buffer[] = "hello kernel!!!"; | |
/* netlink 消息头 */ | |
struct nlmsghdr *nlhdr; | |
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE)); | |
strcpy(NLMSG_DATA(nlhdr),buffer); | |
nlhdr->nlmsg_len = NLMSG_LENGTH(strlen(buffer)); | |
nlhdr->nlmsg_pid = getpid(); /* self pid */ | |
nlhdr->nlmsg_flags = 0; | |
struct iovec iov; | |
iov.iov_base = (void *)nlhdr; | |
iov.iov_len = nlhdr->nlmsg_len; | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
sendmsg(skfd, &msg, 0); | |
/* recv */ | |
//memset((char *)NLMSG_DATA(nlhdr), 0, 1024); | |
recvmsg(skfd, &msg, 0); | |
printf("kernel: %s\n", NLMSG_DATA(nlhdr)); | |
//printf("kernel: %s\n", nlmsg_data(nlhdr)); | |
close(skfd); | |
free(nlhdr); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment