gpt4 book ai didi

c - inotify_add_watch 在/sys/class/net/eth0/operstate 上失败

转载 作者:行者123 更新时间:2023-12-02 09:35:32 25 4
gpt4 key购买 nike

我在 Linux 中使用了 inotify,以便在网络接口(interface)链接发生变化时引发事件。每当接口(interface)链接更改时,/sys/class/net/eth40/operstate/文件都会被修改。但在下面的代码片段中,即使文件正在修改,读取功能仍处于阻塞状态。

#include <stdio.h>
#include <sys/inotify.h>
#include <stdlib.h>
#include <limits.h>
#include <signal.h>
#define FILE_TO_WATCH "/sys/class/net/eth40/operstate"
#define EVENT_SIZE (sizeof (struct inotify_event))
#define EVENT_BUFFER_LENGTH (1024 * EVENT_SIZE + NAME_MAX + 1)

void print_event(struct inotify_event *event) {

int ret = 0;
if (event->mask & IN_CREATE)
printf("file created in directory\n");
if (event->mask & IN_DELETE)
printf("file deleted in directory\n");
if (event->mask & IN_ACCESS)
printf("file accessed\n");
if (event->mask & IN_CLOSE)
printf("file closed after reading or writing \n");
if (event->mask & IN_OPEN)
printf("file opened\n");

if (event->len)
printf("name: %s\n", event->name);
}

int main(int argc, char** argv)
{
int notify_fd;
int watch_fd;
long input_len;
char *ptr;
char buffer[EVENT_BUFFER_LENGTH];
struct inotify_event *event;

notify_fd = inotify_init();
if (notify_fd < 0) {
perror("cannot init inotify");
exit(EXIT_FAILURE);
}
printf("done1\n");
watch_fd = inotify_add_watch(notify_fd,FILE_TO_WATCH,IN_ACCESS|IN_MODIFY);
if (watch_fd < 0) {
perror("cannot add file");
exit(EXIT_FAILURE);
}
printf("done2\n");
while (1) {
input_len = read(notify_fd, buffer, EVENT_BUFFER_LENGTH);
if (input_len <= 0) {
perror("error reading from inotify fd");
exit(EXIT_FAILURE);
}
printf("done3\n");
ptr = buffer;
while (ptr < buffer + input_len) {
event = (struct inotify_event *) ptr;
print_event(event);
ptr += sizeof (struct inotify_event) +event->len;
}
}
}

我错过了什么吗?

最佳答案

/sys 不是一个普通的文件系统,而是一个特殊的内存文件系统,叫做sysfs

引用kernel developer :

inotify does not and will not work on sysfs. Or procfs. Or devpts. Or any number of network filesystems. No matter how hard somebody might wish it to work, that's simply not feasible.

对于网络链接事件,您可以使用 rt netlink ,虽然这样的事情几乎没有记录,但这里有一个起点示例,它将向您展示链接(和其他一些)事件,您必须找出与您的特定案例相关的事件/标志和类似事件。

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <asm/types.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>

#define ENTRY(x) {x, #x}
struct {
unsigned flag;
const char *name;
} ifi_flag_map[] = {
ENTRY(IFF_UP),
ENTRY(IFF_BROADCAST),
ENTRY(IFF_DEBUG),
ENTRY(IFF_LOOPBACK),
ENTRY(IFF_POINTOPOINT),
ENTRY(IFF_NOTRAILERS),
ENTRY(IFF_RUNNING),
ENTRY(IFF_NOARP),
ENTRY(IFF_PROMISC),
ENTRY(IFF_ALLMULTI),
ENTRY(IFF_MASTER),
ENTRY(IFF_SLAVE),
ENTRY(IFF_MULTICAST),
ENTRY(IFF_PORTSEL),
ENTRY(IFF_AUTOMEDIA),
ENTRY(IFF_DYNAMIC),
ENTRY(IFF_LOWER_UP),
ENTRY(IFF_DORMANT),
ENTRY(IFF_ECHO),
};
struct {
unsigned type;
const char *name;
} nlmrt_type_map[] = {
ENTRY(RTM_NEWLINK ),
ENTRY(RTM_DELLINK),
ENTRY(RTM_GETLINK),
ENTRY(RTM_SETLINK),
ENTRY(RTM_NEWADDR ),
ENTRY(RTM_DELADDR),
ENTRY(RTM_GETADDR),
ENTRY(RTM_NEWROUTE ),
ENTRY(RTM_DELROUTE),
ENTRY(RTM_GETROUTE),
ENTRY(RTM_NEWNEIGH ),
ENTRY(RTM_DELNEIGH),
ENTRY(RTM_GETNEIGH),
ENTRY(RTM_NEWRULE ),
ENTRY(RTM_DELRULE),
ENTRY(RTM_GETRULE),
ENTRY(RTM_NEWQDISC ),
ENTRY(RTM_DELQDISC),
ENTRY(RTM_GETQDISC),
ENTRY(RTM_NEWTCLASS ),
ENTRY(RTM_DELTCLASS),
ENTRY(RTM_GETTCLASS),
ENTRY(RTM_NEWTFILTER ),
ENTRY(RTM_DELTFILTER),
ENTRY(RTM_NEWACTION ),
ENTRY(RTM_DELACTION),
ENTRY(RTM_GETACTION),
ENTRY(RTM_NEWPREFIX ),
ENTRY(RTM_GETMULTICAST ),
ENTRY(RTM_GETANYCAST ),
ENTRY(RTM_NEWNEIGHTBL ),
ENTRY(RTM_GETNEIGHTBL ),
ENTRY(RTM_SETNEIGHTBL),
ENTRY(RTM_NEWNDUSEROPT ),
ENTRY(RTM_NEWADDRLABEL ),
ENTRY(RTM_DELADDRLABEL),
ENTRY(RTM_GETADDRLABEL),
ENTRY(RTM_GETDCB ),
ENTRY(RTM_SETDCB),
ENTRY(RTM_NEWNETCONF ),
ENTRY(RTM_GETNETCONF ),
ENTRY(RTM_NEWMDB ),
ENTRY(RTM_DELMDB ),
ENTRY(RTM_GETMDB ),
};

void print_type(unsigned type)
{
size_t i;

for (i = 0; i < sizeof nlmrt_type_map/sizeof nlmrt_type_map[0]; i++) {
if (type == nlmrt_type_map[i].type) {
printf("\t\tMsg Type: %s\n", nlmrt_type_map[i].name);
return;
}
}

printf("\t\tMsg Type: unknown(%d)\n", type);
}
void print_flags(unsigned flags, unsigned change)
{
size_t i;

printf("\t\tflags: ");

for (i = 0; i < sizeof ifi_flag_map/sizeof ifi_flag_map[0]; i++) {
if (flags & ifi_flag_map[i].flag) {
if (change & ifi_flag_map[i].flag) {
printf("%s(C) ", ifi_flag_map[i].name);
} else {
printf("%s ", ifi_flag_map[i].name);
}
}
}
puts("");
}
oid read_msg(int fd)
{
int len;
char buf[4096];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;
struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nh;

len = recvmsg(fd, &msg, 0);
if(len == -1) {
perror("recvmsg");
return;
}

for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
nh = NLMSG_NEXT (nh, len)) {
struct ifinfomsg *ifimsg;
/* The end of multipart message. */
printf("netlink message: len = %u, type = %u, flags = 0x%X, seq = %u, pid = %u\n",
nh->nlmsg_len,
nh->nlmsg_type,
nh->nlmsg_flags,
nh->nlmsg_seq,
nh->nlmsg_pid);

if (nh->nlmsg_type == NLMSG_DONE)
return;

if (nh->nlmsg_type == NLMSG_ERROR) {
continue;
}

ifimsg = NLMSG_DATA(nh);
printf("\tifi_family = %u, ifi_type = %u, ifi_index = %u, ifi_flags = 0x%X, ifi_change = 0x%X\n",
ifimsg->ifi_family ,
ifimsg->ifi_type ,
ifimsg->ifi_index ,
ifimsg->ifi_flags ,
ifimsg->ifi_change);
print_type(nh->nlmsg_type);
print_flags(ifimsg->ifi_flags, ifimsg->ifi_change);
}
}
int main(int argc, char *argv[])
{
struct sockaddr_nl sa;
int fd;

memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(fd == -1) {
perror("socket");
return 1;
}

if(bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind");
return 1;
}
for(;;) {
read_msg(fd);
}

return 0;
}

关于c - inotify_add_watch 在/sys/class/net/eth0/operstate 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26672414/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com