如何将Netlink套接字用于内核-用户空间通信Android [英] How to use netlink sockets for kernel - userspace communication Android

查看:567
本文介绍了如何将Netlink套接字用于内核-用户空间通信Android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为Android编写内核模块以与Userspace Service通信,以便我的应用程序可以显示有关内核的一些信息.到目前为止,我已经尝试了一些在网络上找到的示例,但都无济于事.这个想法是让内核发送更新,然后服务将接收它们. ioctl不是解决方案,因为通信需要事件驱动,并需要从内核启动.如果有人知道如何执行jni和内核模块的C代码,那就太好了.

I'm trying to write kernel module for android to communicate with userspace Service so my app can display some information about the kernel. So far I've tried several examples I found on the web and none of them works. The idea is for kernel to send updates and service would then pick them up. ioctl is not a solution because the communication needs to be event driven, and initiated from kernel. C code for both jni and kernel module would be great if anyone knows how to do this.

推荐答案

这是我使用的代码段(为简洁起见,不包括对返回值的错误检查),其中netlink套接字通信由内核(即内核)驱动是发送方,用户程序是接收方).

Here's a code snippet that I've used (excluding error checking of return values for conciseness) where the netlink socket communication is driven by the kernel (i.e. the kernel is the sender, user program is the receiver).

内核模块

#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或在您的中断处理之内.

You'd fire this up as a result of your kernel event, e.g. in response to an ioctl or within your interrupt handling.

用户程序

#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(因此,您需要在其中添加一些额外的实现).

I use nlmsg_multicast() in the kernel rather than nlmsg_unicast() because to do a unicast, the kernel module would need to know the process id of your user process (so you'd need to add some extra implementation there).

希望有帮助!

这篇关于如何将Netlink套接字用于内核-用户空间通信Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆