簡體   English   中英

如何使用netlink套接字進行內核 - 用戶空間通信Android

[英]How to use netlink sockets for kernel - userspace communication Android

我正在嘗試編寫用於android的內核模塊與用戶空間服務進行通信,以便我的應用程序可以顯示有關內核的一些信息。 到目前為止,我已經嘗試了幾個我在網上找到的例子,但沒有一個可行。 我們的想法是讓內核發送更新,服務然后將它們接收。 ioctl不是解決方案,因為通信需要由事件驅動,並從內核啟動。 如果有人知道如何執行此操作,jni和內核模塊的C代碼將會很棒。

這是我使用的代碼片段(不包括對簡潔性的返回值的錯誤檢查),其中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(所以你需要在那里添加一些額外的實現)。

希望有所幫助!

我已成功使用netlink socket在Android中的內核和用戶空間之間進行通信。 要在非阻塞模式下使用套接字,請使用fcntl並選擇call。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM