汕头网站建设报价,网站建好后维护麻烦吗,免费做网站建设,wordpress 点点主题netlink简介
Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。在Linux标准内核中#xff0c;系统默认集成了很多netlink实例#xff0c;比如日志上报、路由系统等#xff0c;netlink消息是双向的系统默认集成了很多netlink实例比如日志上报、路由系统等netlink消息是双向的应用层可以发送消息到内核同时内核也可以发送消息到应用层进程非常适合涉及到内核信息采集的模块。
与ioctl的区别
netlink采用sock方式实现而ioctl采用驱动注册方式实现。netlink通常用于传输大量消息而ioctl通常用于下发系统命令不支持内核主动发送消息到应用层。 什么情况下用netlink 在开发过程中我们会面临消息通信机制的选型这和应用层消息通信选型一样每个通信方式都有自己的优缺点。采用netlink机制一般需要应用层单独起进程用于监听内核发送上来的消息开发工作量相对于ioctl较大而ioctl主要用于驱动消息下发比如无线驱动的iwpriv命令实现就采用ioctl机制。
内核模块hello_kernel.c
#include linux/module.h
#include net/sock.h
#include linux/netlink.h
#include linux/skbuff.h
#define NETLINK_USER 31struct sock *nl_sk NULL;static void hello_nl_recv_msg(struct sk_buff *skb)
{struct nlmsghdr *nlh;int pid;struct sk_buff *skb_out;int msg_size;char *msg Hello from kernel;int res;printk(KERN_INFO Entering: %s\n, __FUNCTION__);msg_size strlen(msg);nlh (struct nlmsghdr *)skb-data;printk(KERN_INFO Netlink received msg payload:%s\n, (char *)nlmsg_data(nlh));pid nlh-nlmsg_pid; /*pid of sending process */skb_out nlmsg_new(msg_size, 0);if (!skb_out) {printk(KERN_ERR Failed to allocate new skb\n);return;}nlh nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);NETLINK_CB(skb_out).dst_group 0; /* not in mcast group */strncpy(nlmsg_data(nlh), msg, msg_size);res nlmsg_unicast(nl_sk, skb_out, pid);if (res 0)printk(KERN_INFO Error while sending bak to user\n);
}static int __init hello_init(void)
{printk(Entering: %s\n, __FUNCTION__);//nl_sk netlink_kernel_create(init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);struct netlink_kernel_cfg cfg {.input hello_nl_recv_msg,};nl_sk netlink_kernel_create(init_net, NETLINK_USER, cfg);if (!nl_sk) {printk(KERN_ALERT Error creating socket.\n);return -10;}return 0;
}static void __exit hello_exit(void)
{printk(KERN_INFO exiting hello module\n);netlink_kernel_release(nl_sk);
}module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE(GPL);
应用层代码hello.c
#include linux/netlink.h
#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include unistd.h#define NETLINK_USER 31#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;int main()
{sock_fd socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);if (sock_fd 0)return -1;memset(src_addr, 0, sizeof(src_addr));src_addr.nl_family AF_NETLINK;src_addr.nl_pid getpid(); /* self pid */bind(sock_fd, (struct sockaddr *)src_addr, sizeof(src_addr));memset(dest_addr, 0, sizeof(dest_addr));dest_addr.nl_family AF_NETLINK;dest_addr.nl_pid 0; /* For Linux Kernel */dest_addr.nl_groups 0; /* unicast */nlh (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));nlh-nlmsg_len NLMSG_SPACE(MAX_PAYLOAD);nlh-nlmsg_pid getpid();nlh-nlmsg_flags 0;strcpy(NLMSG_DATA(nlh), Hello);iov.iov_base (void *)nlh;iov.iov_len nlh-nlmsg_len;msg.msg_name (void *)dest_addr;msg.msg_namelen sizeof(dest_addr);msg.msg_iov iov;msg.msg_iovlen 1;printf(Sending message to kernel\n);sendmsg(sock_fd, msg, 0);printf(Waiting for message from kernel\n);/* Read message from kernel */recvmsg(sock_fd, msg, 0);printf(Received message payload: %s\n, NLMSG_DATA(nlh));close(sock_fd);return 0;
} Makefile
binhello
obj-m hello_kernel.o
KVERSION $(shell uname -r)
all:$(bin)make -C /lib/modules/$(KVERSION)/build M$(PWD) modules
bin:gcc hello.c -o hello
clean:make -C /lib/modules/$(KVERSION)/build M$(PWD) cleanrm -rf hello.o hello
Makefile问题记录一下
chat:KVERSION $(shell uname -r)去掉shell有什么区别
在Makefile中$(shell ...)是一个用于执行命令并获取其输出的内置函数。在你提到的语句中$(shell uname -r)用于执行uname -r命令来获取当前Linux内核的版本并将结果赋值给KVERSION变量。如果你去掉shell那么整个语句就会变成 KVERSION uname -r 这将不再是一个命令执行语句而是一个简单的变量赋值语句。这意味着KVERSION的值将直接设置为字符串uname -r而不是执行uname -r命令并获取其输出。 因此区别在于 - KVERSION $(shell uname -r)这会执行uname -r命令获取内核版本并将结果作为字符串赋值给KVERSION变量。 - KVERSION uname -r这只是将字符串uname -r赋值给KVERSION变量不会执行命令或获取内核版本。 如果你想要将内核版本赋值给KVERSION变量你应该使用$(shell ...)来执行命令。否则你将只是将命令字符串本身赋值给变量而不会获取命令的输出。
make -C什么意思
make -C 是 make 命令的一个选项用于指定 make 命令应该在哪个目录下执行。 语法为 make -C 目录 其中 目录 是你希望 make 命令执行的目录的路径。 这个选项通常用于在项目的子目录中执行 make 命令以便构建子项目或依赖于其他目录中的代码的项目。这对于在大型项目中管理多个模块或组件的构建过程非常有用因为你可以在每个子目录中维护一个独立的 Makefile 文件并使用 -C 选项来指定要构建的子目录。 例如如果你有一个名为 subproject 的子目录并在该目录中有一个名为 Makefile 的构建文件你可以使用以下命令在 subproject 目录中执行 make make -C subproject 这将导致 make 命令在 subproject 目录中查找并执行 Makefile 文件执行与该子项目相关的构建任务。 运行结果
应用层 内核先加载.ko运行hello之后用dmesg就可查看收到的消息 代码来源
Linux下C语言如何使用 netlink sockets与内核模块通信_c语言nlmsghdr的使用_wellnw的博客-CSDN博客