我已在目标中为gps连接创建了/ dev / ttyACM0端口。由于某种原因,当目标运行时,此端口正在断开连接。每当断开连接时,我都会得到kobject-uevent,而不是我正在使用netlinl示例程序捕获此事件,如下所示。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_TEST 17
#define MYGROUP 1
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
int ret, fd;
char *temp;
fd = open("/dev/ttyACM1", O_RDWR);
if (fd < 0) {
printf("Unable to open port\n");
return -1;
}
printf("Creating socket\n");
sock_fd=socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(sock_fd<0) {
printf("Socket creating failed\n");
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
src_addr.nl_groups = MYGROUP;
/* interested in group 1<<0 */
ret = bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
if (ret < 0) {
printf("Bind Failed\n");
perror("bind:");
return -1;
}
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_flags = 0;
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Waiting for message from kernel\n");
/* Read message from kernel */
while (1) {
recvmsg(sock_fd, &msg, 0);
temp = strstr(NLMSG_DATA(nlh), "tty/ttyACM1");
printf("Received message payload: %s\n", temp);
}
close(sock_fd);
return 0;
}
使用这个程序我的输出低于输出。
Received message payload: 0000:00/0000:00:15.0/usb1/1-4/1-4:1.0/tty/ttyACM1
这是发生断开连接的设备的路径。但是,当我检查/lib/kobject_uevent.c代码时,我看到它正在发送带有设备路径的 action_string ,在我的情况下 remove 。
如果我想捕获此action_string我该如何捕获它?
答案 0 :(得分:1)
嗨由于Prabhakar在评论中的一些研究和建议,我开始知道我们必须使用libudev.so库来获得用户空间中的正确uevent。
但是出于测试目的,我浏览了libudev源代码,发现libudev也使用netlink捕获uevent。只有libudev代码的不同之处在于它使用的是union {},其中包含&#39; struct nlmsghdr&#39;和&#39; char buf [SIZE]&#39;。因此,我们可以使用buf打印nlmsghdr结构中的数据。
因此,作为一个黑客,我使用了联合而不是&#34; struct nlmsghdr * nlh&#34;并在该联合中创建了一个原始缓冲区以及此结构,如下所示
union {
struct nlmsghdr nlh;
char raw[8192];
} buf;
此更改后的完整工作程序如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_TEST 17
#define MYGROUP 1
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
union {
struct nlmsghdr nlh;
char raw[8192];
} buf;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
int ret, fd, i;
char *event_buf;
char action[50];
#if 1
fd = open("/dev/ttyACM1", O_RDWR);
if (fd < 0) {
printf("Unable to open port\n");
return -1;
}
#endif
printf("Creating socket\n");
sock_fd=socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(sock_fd<0) {
printf("Socket creating failed\n");
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
src_addr.nl_groups = MYGROUP;
/* interested in group 1<<0 */
ret = bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
if (ret < 0) {
printf("Bind Failed\n");
perror("bind:");
return -1;
}
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
memset(&buf, 0, sizeof(buf));
iov.iov_base = &buf;
iov.iov_len = sizeof(buf);
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
#if 1
/* Read message from kernel */
while (1) {
recvmsg(sock_fd, &msg, 0);
if (strstr(buf.raw, "/tty/ttyACM1") != NULL) {
event_buf = buf.raw;
for (i = 0; event_buf[i] != '@'; i++)
action[i] = event_buf[i];
action[i] = '\0';
printf("ACTION = %s\n", action);
if ((strcmp(action, "remove")) == 0) {
close(fd);
printf("ACM port closed\n");
}
}
}
end:
close(sock_fd);
#endif
return 0;
}
在buf.raw中,我正在使用action_string获取uevent消息。例如:
remove@/devices/pci0000:00/0000:00:15.0/usb1/1-3/1-3:1.0/tty/ttyACM2
其中&#34;删除&#34;是&#39; @&#39;之后的动作字符串和其余字符串是该事件的设备路径。