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.
-
One option is to use netlink sockets. http://stackoverflow.com/questions/3299386/how-to-use-netlink-socket-to-communicate-with-a-kernel-module – Anup Warnulkar Apr 17 '14 at 06:40
-
Already tried that using the very same code. On Ubuntu it works fine, but when I try it on Andoid it does nothing. For the worse part it does manage to create socket and bind (I get no err messages), but I get no message that kernel should print once connected and also no read from netlink. Program just blocks on read... – TheMole Apr 24 '14 at 11:11
2 Answers
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).
Kernel module
#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;
}
You'd fire this up as a result of your kernel event, e.g. in response to an ioctl or within your interrupt handling.
User Program
#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);
}
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).
Hope that helps!

- 157
- 1
- 2
- 10
I have successfully used netlink socket to communicate between kernel and user-space in Android. To use socket in non-blocking mode use the fcntl and select call.

- 773
- 1
- 8
- 25
-
I'll try it again when I find time, because we already changed our approach to use something else. If it really works then I probably didn't do something right the first time. Thanks! – TheMole Apr 24 '14 at 17:28