2014-10-31 63 views
2

我在Linux中使用了inotify,以便在網絡接口鏈接發生更改時引發事件。無論何時接口鏈接改變,/ sys/class/net/eth40/operstate /文件被修改。但是即使文件被修改,在下面的代碼片段中,讀取函數仍處於阻塞狀態。inotify_add_watch在/ sys/class/net/eth0/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; 
 
     } 
 
    } 
 
}

am'I失去了一些東西?

回答

3

/SYS是不是一個普通的文件系統,而是一個特定的內存中的文件系統,稱爲sysfs

引述一個kernel developer

的inotify不,不會對sysfs的工作。或者procfs。或者開發人員。 或任何數量的網絡文件系統。無論有多難 可能希望它工作,這根本不可行。

對於網絡鏈接事件,你可以使用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; 
} 
+0

請問您可以給我建議任何其他方法來監視NIC端口上的網絡鏈接事件。 – 2014-10-31 12:12:02

+0

@MujtabaMohd http://en.wikipedia.org/wiki/Netlink和'人7 netlink' – Jite 2014-10-31 12:15:32

+0

是否有任何方法來實現c中的窗口中的網絡鏈接事件? – 2014-10-31 13:24:15