我正在尝试编写一个使用netlink与用户进程通信的linux内核模块.我正在使用netlink,因为我想要通信的用户程序只使用套接字进行通信,我无法改变它来添加ioctl()或任何东西.
问题是我无法弄清楚如何做到这一点.我用Google搜索,但我发现所有的例子都是老喜欢这一个,不再适用于当前的内核版本.我也看了这个问题,但这里的示例使用libnl进行套接字操作,但我想坚持使用标准套接字函数(定义sys/socket.h).那么有些人可以在这里指导我一些教程或指南或一些可以帮助我理解netlink的界面和用法的东西.我非常感谢一个工作示例,没什么特别的,只是一个非常基本的例子,说明如何建立从用户程序中的套接字到内核中的套接字的连接,然后将数据从用户进程发送到内核并从内核接收回来.
另请不要告诉我查看内核代码.我已经在做了,但这需要花费很多时间,而且我没有留下很多东西.
更新:
经过大量的试验和错误后,我有以下代码将消息从用户程序发送到内核,但是从内核到用户程序的消息即使用netlink_unicast()不起作用.它不仅没有工作,呼叫挂起系统,然后我必须重新启动机器.有人可以看看,告诉我我在做什么错.该netlink_unicast()调用在以下代码中进行了注释.它应该是内核到用户程序消息的未注释.
#include <sys/socket.h>
#include <linux/netlink.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;
void 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 */
/* interested in group 1<<0 */
bind(sock_fd, …Run Code Online (Sandbox Code Playgroud) 我试图将一个结构从LKM发送到userland,基于这个答案:使用3.X linux内核的C中的Netlink套接字
答案本身的代码是完全可编译的,但是当我尝试发送struct而不是a时char *,我会在userland中获得段错误.
这是我改变的:
netlinkKernel.c
我加:
typedef struct test{
int a;
char *b;
} s_test;
Run Code Online (Sandbox Code Playgroud)
并替换
char *msg = "Hello from kernel";
---
msg_size = strlen(msg);
---
strncpy(nlmsg_data(nlh),msg,msg_size);
Run Code Online (Sandbox Code Playgroud)
同
s_test x;
x.a = 42;
x.b = "The answer";
---
msg_size(sizeof(x));
---
memcpy(nlmsg_data(nlh), &x, msg_size);
Run Code Online (Sandbox Code Playgroud)
netlinkUser.c
我添加相同的结构和替换
printf("Received message payload: %s\n", (char *)NLMSG_DATA(nlh));
Run Code Online (Sandbox Code Playgroud)
同
s_test *x = (s_test *)NLMSG_DATA(nlh);
printf("Received message payload: %d - %s\n", x->a, x->b);
Run Code Online (Sandbox Code Playgroud)
问题出在哪儿?