如何使用netlink套接字与内核模块通信?

我正在尝试编写一个使用netlink与用户进程通信的linux内核模块。我之所以使用netlink,是因为我要交流的用户程序只能使用套接字进行通信,而不能更改它以添加ioctl()或进行其他操作。


问题是我不知道该怎么做。我已经用谷歌搜索过,但是我发现的所有示例都是像这样的旧示例,对于当前的内核版本不再有效。我也看过这个SO问题,但是这里的示例使用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, (struct sockaddr*)&src_addr,  

      sizeof(src_addr));  


    memset(&dest_addr, 0, sizeof(dest_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;  



海绵宝宝撒
浏览 610回答 3
3回答

慕码人2483693

它适用于内核3.2。对于3.6或更高版本的内核,需要对netlink_kernel_create功能进行一些更改。&nbsp;struct netlink_kernel_cfg cfg = {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .groups = 1,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .input = hello_nl_recv_msg,&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; printk("Entering: %s\n", __FUNCTION__);&nbsp; &nbsp; &nbsp; &nbsp; nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
打开App,查看更多内容
随时随地看视频慕课网APP