如何使用netlink进行IPC?
Posted
技术标签:
【中文标题】如何使用netlink进行IPC?【英文标题】:How to use netlink for IPC? 【发布时间】:2019-10-08 06:50:46 【问题描述】:我的项目需要使用Netlink做IPC,参考是Netlink unicast。我对代码做了一些更改。首先,我启动了接收者和发送者,然后将发送者的 pid 输入到接收者,然后将接收者的 pid 输入到发送者。但是接收者没有收到消息。我也参考了Is anyone using netlink for IPC?,他们都没有工作。我的代码有什么问题吗?
收货人代码:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdio.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#define NLINK_MSG_LEN 1024
#define NETLINK_USER 31
int main()
int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
//int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
//int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
printf("Inside recv main\n");
if (fd < 0)
printf("Socket creation failed. try again\n");
return -1;
/* Declare for src NL sockaddr, dest NL sockaddr, nlmsghdr, iov, msghr */
struct sockaddr_nl src_addr, dest_addr;
memset(&src_addr, 0, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
//allocate buffer for netlink message which is message header + message payload
struct nlmsghdr *nlh =(struct nlmsghdr *) malloc(NLMSG_SPACE(NLINK_MSG_LEN));
memset(nlh, 0, NLMSG_SPACE(NLINK_MSG_LEN));
//fill the iovec structure
struct iovec iov;
memset(&iov, 0, sizeof(iov));
//define the message header for message
//sending
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
int sender_pid;
printf("Receiver process id: %d\n", getpid());
printf("Sender process id: ");
scanf("%d", &sender_pid);
src_addr.nl_family = AF_NETLINK; //AF_NETLINK socket protocol
src_addr.nl_pid = getpid(); //application unique id
src_addr.nl_groups = 0; //specify not a multicast communication
dest_addr.nl_family = AF_NETLINK; // protocol family
dest_addr.nl_pid = sender_pid; //destination process id
dest_addr.nl_groups = 0;
nlh->nlmsg_len = NLMSG_SPACE(NLINK_MSG_LEN); //netlink message length
nlh->nlmsg_pid = getpid(); //src application unique id
nlh->nlmsg_flags = 0;
iov.iov_base = (void *)nlh; //netlink message header base address
iov.iov_len = nlh->nlmsg_len; //netlink message length
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
//attach socket to unique id or address
if(bind(fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0)
printf("Bind failed");
return -1;
/* Listen forever in a while loop */
while (1)
//receive the message
recvmsg(fd, &msg, 0);
printf("Received message: %s\n", (char *)NLMSG_DATA(nlh));
close(fd); // close the socket
发件人代码:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdio.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#define NLINK_MSG_LEN 1024
#define NETLINK_USER 31
int main()
int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
//int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
//int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
printf("Inside send main\n");
if (fd < 0)
printf("Socket creation failed. try again\n");
return -1;
/* Declare for src NL sockaddr, dest NL sockaddr, nlmsghdr, iov, msghr */
struct sockaddr_nl src_addr, dest_addr;
memset(&src_addr, 0, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
//allocate buffer for netlink message which is message header + message payload
struct nlmsghdr *nlh =(struct nlmsghdr *) malloc(NLMSG_SPACE(NLINK_MSG_LEN));
memset(nlh, 0, NLMSG_SPACE(NLINK_MSG_LEN));
//fill the iovec structure
struct iovec iov;
memset(&iov, 0, sizeof(iov));
//define the message header for message
//sending
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
int receiver_pid;
printf("Sender process id: %d\n", getpid());
printf("Receiver process id: ");
scanf("%d", &receiver_pid);
src_addr.nl_family = AF_NETLINK; //AF_NETLINK socket protocol
src_addr.nl_pid = getpid(); //application unique id
src_addr.nl_groups = 0; //specify not a multicast communication
dest_addr.nl_family = AF_NETLINK; // protocol family
dest_addr.nl_pid = receiver_pid; //destination process id
dest_addr.nl_groups = 0;
nlh->nlmsg_len = NLMSG_SPACE(NLINK_MSG_LEN); //netlink message length
nlh->nlmsg_pid = getpid(); //src application unique id
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello World !"); //copy the payload to be sent
iov.iov_base = (void *)nlh; //netlink message header base address
iov.iov_len = nlh->nlmsg_len; //netlink message length
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
//attach socket to unique id or address
if(bind(fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0)
printf("Bind failed");
return -1;
//send the message
sendmsg(fd, &msg, 0);
printf("Send message %s\n", (char *)NLMSG_DATA(nlh));
close(fd); // close the socket
【问题讨论】:
【参考方案1】:您对socket
使用了错误的协议。唯一可以做你想做的事,用户空间进程之间的IPC,是NETLINK_USERSOCK
。
请记住,在您安排与 PID 通信的方式中,您可能会错过一些消息...为了验证通信是否发生,您可以将 msg_name
NULL
留给接收者 并且不会产生不良影响 - 这样做并更改协议,您的代码将按预期工作。
【讨论】:
我将fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
更改为fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK)
并将msg.msg_name = (void *)&dest_addr
更改为msg.msg_name = NULL
,但仍然无法正常工作。
我将接收者和发送者都更改为msg.msg_name = NULL
,它不起作用。但我意识到并将发件人只改回msg.msg_name = (void *)&dest_addr
,它成功了,谢谢!
抱歉,我意识到我在这一点上太含糊了 - 修正了文本。很高兴你知道了!以上是关于如何使用netlink进行IPC?的主要内容,如果未能解决你的问题,请参考以下文章