Skip to content

Instantly share code, notes, and snippets.

@lflish
Last active August 7, 2020 02:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lflish/15e85da8bb9200794255439d0563b195 to your computer and use it in GitHub Desktop.
Save lflish/15e85da8bb9200794255439d0563b195 to your computer and use it in GitHub Desktop.
用户层与内核层通信 netlink

用户层与内核层通信

  1. make
  2. 另开一个窗口 运行dmesg -w
  3. insmod ktest.ko
  4. ./utest
/**
* @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);
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
/**
* @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