sysfs
파일 변경 사항(예 : )을 모니터링 /sys/class/net/eth0/statistics/operstate
하고 콘텐츠 변경 사항에 대한 명령을 실행하는 방법은 무엇입니까?
inotify
작동하지 않습니다sysfs
- 나는 투표하고 싶지 않습니다. 콜백 루틴을 사용하여 리스너를 한 번 설정하고 싶습니다.
답변1
나는 padding에 대한 소스 코드를 읽지 않았지만 operstate
일반적으로 sysfs에서 파일을 읽으면 읽고 있는 바이트를 반환하는 커널 측의 일부 코드가 실행됩니다. 따라서 읽지 않았다면 operstate
"상태"가 없습니다. 값은 어디에도 저장되지 않습니다.
sysfs 파일 변경 사항을 모니터링하는 방법
이는 실제로 파일이 아니기 때문에 "변경"이라는 개념이 존재하지 않습니다.
아마도 당신이 원하는 것을 달성하는 더 좋은 방법이 있을 것입니다! netlink
디자인되었습니다구체적으로네트워크 상태를 모니터링하는 작업입니다.인터페이스가 용이함. 예를 들어, 최소한으로 수정된 다음 예제 코드로 man 7 netlink
문제가 해결되었을 수 있습니다.
struct sockaddr_nl sa;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
// Link state change notifications:
sa.nl_groups = RTMGRP_LINK;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
bind(fd, (struct sockaddr *) &sa, sizeof(sa));
일반적으로 이것이 이더넷 수준 연결이 아니라 일부 IP 네트워크(또는 인터넷)에 대한 연결에 관한 것이라면 systemd/NetworkManager는 최신 시스템에서 사용하는 경로입니다.
답변2
훌륭한 뮐러가 이미 설명했듯이,감시 장치 sysfs
파일은 가상 파일 시스템의 일부이고 유사하지 않기 때문입니다.일반 문서.
나는 결국 테스트를 거치지 않았고 보기에도 좋지 않았지만 여전히 형편없는 C를 사용하게 되었습니다.이것의 단편netlink
, 및 의 더 넓은 예로서rnetlink
:
./realtimnetlink
Monitoring
RTM NEWLINK enp12s0 DOWN
RTM NEWLINK enp12s0 UP
RTM NEWLINK eth10 DOWN
RTM NEWADDR eth10
RTM NEWLINK eth10 UP
컴파일 및 통과gcc -o foo foo.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#define E_PRINT(f_, ...) fprintf(stderr, ("ERROR NetLink: %s" f_ "\n"), ##__VA_ARGS__)
int open_netlink()
{
int soc; // fd
struct sockaddr_nl sa;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
soc = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (soc < 0) {
perror("INIT socket: ");
return -1;
}
if (bind(soc, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("INIT bind_socket:");
return -1;
}
return soc;
}
int event_read(
int sockint,
int (*msg_handler)(struct nlmsghdr *)
) {
int status;
int ret = 0;
char buf[4096];
struct iovec iov = { buf, sizeof buf };
struct sockaddr_nl snl;
struct msghdr msg = {
(void*)&snl,
sizeof snl,
&iov, 1, NULL, 0, 0
};
struct nlmsghdr *hdr;
status = recvmsg(sockint, &msg, 0);
if (status < 0) {
/* Socket non-blocking so bail out once we have read everything */
if (errno == EWOULDBLOCK || errno == EAGAIN)
return ret;
/* Anything else is an error */
E_PRINT("recvmsg: %d", "EVT_READ", status);
perror("ERROR read_netlink: ");
return status;
} else if (status == 0) {
E_PRINT("recvmsg: EOF", "EVT_READ");
}
/* We need to handle more than one message per 'recvmsg' */
for (
hdr = (struct nlmsghdr *) buf;
NLMSG_OK (hdr, (unsigned int)status);
hdr = NLMSG_NEXT (hdr, status)
) {
/* Finish reading */
if (hdr->nlmsg_type == NLMSG_DONE)
return ret;
/* Message is some kind of error */
if (hdr->nlmsg_type == NLMSG_ERROR) {
E_PRINT("Decode to be done", "EVT_READ");
return -1;
}
/* Call message handler */
if (msg_handler) {
ret = (*msg_handler)(hdr);
if (ret < 0) {
E_PRINT("msg_handler: %d", "EVT_READ", ret);
return ret;
}
} else {
E_PRINT("NULL message handler", "EVT_READ");
return -1;
}
}
return ret;
}
static int msg_handler(struct nlmsghdr *msg)
{
struct ifinfomsg *ifi = NLMSG_DATA(msg);
struct ifaddrmsg *ifa = NLMSG_DATA(msg);
char ifname[1024];
switch (msg->nlmsg_type) {
case RTM_NEWADDR:
if_indextoname(ifa->ifa_index, ifname);
printf("RTM NEWADDR %s\n", ifname);
break;
case RTM_DELADDR:
if_indextoname(ifa->ifa_index, ifname);
printf("RTM DELADDR %s\n", ifname);
break;
case RTM_NEWLINK:
if_indextoname(ifi->ifi_index, ifname);
printf("RTM NEWLINK %s %s\n",
ifname,
(ifi->ifi_flags & IFF_UP) ? "UP" : "DOWN"
);
break;
case RTM_DELLINK:
if_indextoname(ifi->ifi_index, ifname);
printf("RTM DELLINK %s\n", ifname);
break;
default:
fprintf(stderr,
"RTM UNKNOWN nlmsg_type %d\n",
msg->nlmsg_type
);
break;
}
return 0;
}
int main(void)
{
int nls = open_netlink();
if (nls < 0) {
E_PRINT("Open Error!", "INIT");
return 1;
}
fprintf(stderr, "Monitoring\n");
while (1)
event_read(nls, msg_handler);
return 0;
}