我正在尝试为 android 编写内核模块以与用户空间服务通信,以便我的应用程序可以显示有关内核的一些信息。到目前为止,我已经尝试了几个在网上找到的示例,但没有一个有效。这个想法是让内核发送更新,然后服务将接收它们。ioctl 不是解决方案,因为通信需要事件驱动,并从内核启动。如果有人知道如何做到这一点,那么 jni 和内核模块的 C 代码将会很棒。
问问题
4100 次
2 回答
2
这是我使用的代码片段(不包括对返回值的错误检查以求简洁),其中 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(因此您需要在那里添加一些额外的实现)。
希望有帮助!
于 2014-08-01T00:56:22.200 回答
0
我已成功使用 netlink 套接字在 Android 中的内核和用户空间之间进行通信。要在非阻塞模式下使用套接字,请使用 fcntl 和 select 调用。
于 2014-04-24T15:29:53.683 回答