【问题标题】:How to use netlink sockets for kernel - userspace communication Android如何为内核使用 netlink 套接字 - 用户空间通信 Android
【发布时间】:2014-05-05 05:30:01
【问题描述】:

我正在尝试为 android 编写内核模块以与用户空间服务通信,以便我的应用程序可以显示有关内核的一些信息。到目前为止,我已经尝试了几个在网上找到的示例,但没有一个有效。这个想法是让内核发送更新,然后服务将接收它们。 ioctl 不是解决方案,因为通信需要事件驱动,并从内核启动。如果有人知道怎么做,jni 和内核模块的 C 代码会很棒。

【问题讨论】:

  • 一种选择是使用 netlink 套接字。 stackoverflow.com/questions/3299386/…
  • 已经尝试过使用相同的代码。在 Ubuntu 上它运行良好,但是当我在 Andoid 上尝试它时,它什么也没做。更糟糕的是,它确实设法创建套接字和绑定(我没有收到错误消息),但我没有收到内核一旦连接就应该打印的消息,也没有从 netlink 读取。程序只是在读取时阻塞...

标签: android sockets kernel netlink


【解决方案1】:

这是我使用过的代码 sn-p(不包括对返回值的错误检查以求简洁),其中 netlink 套接字通信由内核驱动(即内核是发送者,用户程序是接收者)。

内核模块

#include <net/sock.h>
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <string.h>

#define MY_GROUP    1

struct sock* socket;
struct sk_buff* socket_buff;

static void nl_receive_callback (struct sk_buff *skb)                                                     
{                                                                                                     
    nlmsg_free(skb);                                                                                  
}                                                                                                     

static void kernel_send_nl_msg(void)                                                                  
{                                                                                                     
    struct nlmsghdr *nlsk_mh;                                                                         
    char* msg = "hello kernel";

    socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 1, nl_receive_callback, NULL, THIS_MODULE);                                                                                            

    socket_buff = nlmsg_new(256, GFP_KERNEL);                                                                                                                                                                                                                                                 
    nlsk_mh = nlmsg_put(socket_buff, 0, 0, NLMSG_DONE, strlen(msg), 0);                       
    NETLINK_CB(socket_buff).pid = 0;    // kernel pid                                                   
    NETLINK_CB(socket_buff).dst_group = MY_GROUP;                                                     
    strcpy(nlmsg_data(nlsk_mh), msg);                                                                

    nlmsg_multicast(socket, socket_buff, 0, MY_GROUP, GFP_KERNEL);                    

    return;                                                                                           
} 

你会因为你的内核事件而触发它,例如响应 ioctl 或在您的中断处理中。

用户程序

#include <sys/socket.h>
#include <linux/netlink.h>

#define MY_GROUP    1

void user_recieve_nl_msg(void)
{
    int sock_fd;
    struct sockaddr_nl user_sockaddr;
    struct nlmsghdr *nl_msghdr;
    struct msghdr msghdr;
    struct iovec iov;

    char* kernel_msg;

    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);

    memset(&user_sockaddr, 0, sizeof(user_sockaddr));
    user_sockaddr.nl_family = AF_NETLINK;
    user_sockaddr.nl_pid = getpid();
    user_sockaddr.nl_groups = MY_GROUP; 

    bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));
    while (1) {
        nl_msghdr = (struct nlmsghdr*) malloc(NLMSG_SPACE(256));
        memset(nl_msghdr, 0, NLMSG_SPACE(256));

        iov.iov_base = (void*) nl_msghdr;
        iov.iov_len = NLMSG_SPACE(256);

        msghdr.msg_name = (void*) &user_sockaddr;
        msghdr.msg_namelen = sizeof(user_sockaddr);
        msghdr.msg_iov = &iov;
        msghdr.msg_iovlen = 1;

        recvmsg(sock_fd, &msghdr, 0);

        kernel_msg = (char*)NLMSG_DATA(nl_msghdr);
        print("Kernel message: %s\n", kernel_msg); // print to android logs
    }

    close(sock_fd);
}

我在内核中使用 nlmsg_multicast() 而不是 nlmsg_unicast() 因为要进行单播,内核模块需要知道您的用户进程的进程 ID(因此您需要在那里添加一些额外的实现)。

希望有帮助!

【讨论】:

    【解决方案2】:

    我已成功使用 netlink 套接字在 Android 中的内核和用户空间之间进行通信。要在非阻塞模式下使用套接字,请使用 fcntl 并选择调用。

    【讨论】:

    • 有时间我会再试一次,因为我们已经改变了使用其他方法的方法。如果它真的有效,那么我可能第一次没有做正确的事情。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-03-02
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    相关资源
    最近更新 更多