inotify_add_watch失败上/ SYS /班/网/的eth0 / operstate [英] inotify_add_watch fails on /sys/class/net/eth0/operstate

查看:1291
本文介绍了inotify_add_watch失败上/ SYS /班/网/的eth0 / operstate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Linux中使用的inotify,以获得活动筹得当过网络接口链路的变化。每当接口链路的变化,/ SYS /班/ NET / eth40 / operstate /文件被修改。但即使文件被修改得到以下code段,阅读功能仍处于封锁状态。

\r
\r

的#include<&stdio.h中GT;\r
#包括LT&; SYS / inotify.h>\r
#包括LT&;&stdlib.h中GT;\r
#包括LT&;&limits.h中GT;\r
#包括LT&;&signal.h中GT;\r
#定义FILE_TO_WATCH/ SYS /班/ NET / eth40 / operstate\r
#定义EVENT_SIZE(的sizeof(结构inotify_event))\r
#定义EVENT_BUFFER_LENGTH(1024 * EVENT_SIZE + NAME_MAX + 1)\r
\r
无效print_event(结构inotify_event *事件){\r
\r
    INT RET = 0;\r
    如果(事件 - >&面膜放大器; IN_CREATE则)\r
        的printf(目录\\ n创建的文件);\r
    如果(事件 - >&面膜放大器; IN_DELETE)\r
        的printf(文件目录\\ n删除);\r
    如果(事件 - >&面膜放大器; IN_ACCESS)\r
        的printf(文件访问\\ n);\r
    如果(事件 - >&面膜放大器; IN_CLOSE)\r
        的printf(文件读取或写入\\ n后关闭);\r
    如果(事件 - >&面膜放大器; IN_OPEN)\r
        的printf(文件打开\\ n);\r
\r
    如果(事件 - > LEN)\r
        的printf(名称:%s \\ n,事件 - >名);\r
}\r
\r
INT主(INT ARGC,字符** argv的)\r
{\r
    INT notify_fd;\r
    INT watch_fd;\r
    长input_len;\r
    字符* PTR;\r
    字符缓冲区[EVENT_BUFFER_LENGTH]\r
    结构inotify_event *事件;\r
\r
    notify_fd = inotify_init();\r
    如果(notify_fd℃,){\r
        PERROR(不能初始化inotify的);\r
        出口(EXIT_FAILURE);\r
    }\r
    的printf(DONE1 \\ n);\r
    watch_fd = inotify_add_watch(notify_fd,FILE_TO_WATCH,IN_ACCESS | IN_MODIFY);\r
    如果(watch_fd℃,){\r
        PERROR(不能添加文件);\r
        出口(EXIT_FAILURE);\r
    }\r
    的printf(done2​​ \\ n);\r
    而(1){\r
        input_len =读(notify_fd,缓冲,EVENT_BUFFER_LENGTH);\r
        如果(input_len&下; = 0){\r
            PERROR(从inotify的FD读取错误);\r
            出口(EXIT_FAILURE);\r
        }\r
        的printf(done3 \\ n);\r
        PTR =缓冲;\r
        而(PTR<缓冲区+ input_len){\r
            事件=(结构inotify_event *)PTR;\r
            print_event(事件);\r
            PTR + = sizeof的(结构inotify_event)+事件 - > LEN;\r
        }\r
    }\r
}

\r

\r
\r

am'I失去了一些东西?


解决方案

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

要引用一个内核开发


  

inotify的不和将无法在sysfs的工作。或PROCFS。或devpts。
  或任何数目的网络文件系统。无论怎么说某人
  可能希望它的工作,那是根本行不通的。


有关网络链接事件,你可以使用RT 网络链路,虽然这样的东西几乎没有记载,这里是一个起点,例如,将显示您链接(和一些其他)的事件,你必须弄清楚哪些事件/标志和类似的是有关你的特殊情况。

 的#include<&errno.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; ASM / types.h中>
#包括LT&; ASM / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; Linux的/ netlink.h>
#包括LT&; Linux的/ if.h中>
#包括LT&; Linux的/ rtnetlink.h>#定义ENTRY(X){X,#X}
结构{
    无符号的标志;
    为const char *名称;
} 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)
};
结构{
    无符号类型;
    为const char *名称;
} 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_NEW preFIX)
    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)
};无效print_type(无符号型)
{
    为size_t我;    对于(I = 0; I&下; sizeof的nlmrt_type_map / sizeof的nlmrt_type_map [0];我++){
        如果(类型== nlmrt_type_map [I] .TYPE){
            的printf(\\ t \\ TMSG类型:%S \\ n,nlmrt_type_map [我]。名称);
            返回;
        }
    }    的printf(\\ t \\ TMSG类型:未知(%D)\\ n型);
}
无效print_flags(无符号标志,符号的变化)
{
    为size_t我;    的printf(\\ t \\ tflags:);    对于(I = 0; I&下; sizeof的ifi_flag_map / sizeof的ifi_flag_map [0];我++){
        如果(旗&安培; ifi_flag_map [I] .flag){
            如果(其他城市&安培; ifi_flag_map [I] .flag){
                的printf(%S(C),ifi_flag_map [我]。名称);
            }其他{
                的printf(%S,ifi_flag_map [我]。名称);
            }
        }
    }
    卖出期权();
}
OID read_msg(INT FD)
{
    INT LEN;
    焦炭BUF [4096];
    结构iovec的IOV = {buf中,sizeof的(BUF)};
    结构sockaddr_nl SA;
    结构指向msghdr味精= {(无效*)及SA,的sizeof(SA),放大器; IOV,1,NULL,0,0};
    结构nlmsghdr * NH;    LEN = recvmsg(FD,和放大器;味精,0);
    如果(LEN == -1){
        PERROR(recvmsg);
        返回;
    }    对于(NH =(结构nlmsghdr *)BUF; NLMSG_OK(NH,LEN);
         NH = NLMSG_NEXT(NH,LEN)){
         结构ifinfomsg * ifimsg;
        / *多部分消息的结束。 * /
         的printf(网络链路消息:LEN =%U,键入=%U,旗帜=为0x%X,SEQ =%U,PID =%U \\ N,
            NH-GT&; nlmsg_len,
            NH-GT&; nlmsg_type,
            NH-GT&; nlmsg_flags,
            NH-GT&; nlmsg_seq,
            NH-GT&; nlmsg_pid);        如果(NH-GT&; nlmsg_type == NLMSG_DONE)
            返回;       如果(NH-GT&; nlmsg_type == NLMSG_ERROR){
            继续;
       }       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-GT&; nlmsg_type);
       print_flags(ifimsg-> ifi_flags,ifimsg-> ifi_change);
    }
}
INT主(INT ARGC,CHAR *的argv [])
{
    结构sockaddr_nl SA;
    INT的fd;    memset的(安培; SA,0,sizeof的(SA));
    sa.nl_family = AF_NETLINK;
    sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;    FD =插座(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
    如果(FD == -1){
        PERROR(插座);
        返回1;
    }    如果(绑定(FD,(结构sockaddr *)及SA,的sizeof(SA))== -1){
        PERROR(绑定);
        返回1;
    }
    为(;;){
        read_msg(FD);
    }    返回0;
}

I have used inotify in Linux, to get the event raised when ever the network interface link changes. whenever interface link changes, /sys/class/net/eth40/operstate/ file gets modified. But in the below code snippet even though the file is getting modified, read function is still in blocked state.

#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;
        }
    }
}

am'I missing something?

解决方案

/sys is not a regular file system, but a special in-memory file system called sysfs

To quote a 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.

For network link events you can use rtnetlink, though stuff like this is hardly documented, here's an starting point example that will show you link (and a few other) events, you'll have to figure out which events/flags and similar that is relevant for your particular case.

#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;
}

这篇关于inotify_add_watch失败上/ SYS /班/网/的eth0 / operstate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆