Linuxã«ãŒãã«ã«ç¹æã®æ©èœã䜿ã
ååãŸã§ã§ãCèšèªã§éçºã§ããæäœéã®ç°å¢ãæŽããŠãããä»åã¯Linuxã«ãŒãã«ã«ç¹æã®æ©èœã䜿ã£ãŠããã°ã©ã ãäœããã³ã³ãã€ã«ããŠå®è¡ããæ¹æ³ã玹ä»ããã
ã³ãã³ãããŠãŒãã£ãªãã£ãã¢ããªã±ãŒã·ã§ã³ã¯ç¹å®ã®åŠçã«é¢ããŠã¯ã«ãŒãã«ã«åŠçãäŸé Œããå¿ èŠããããã«ãŒãã«ã«åŠçãäŸé Œããå Žåã«ã¯ãã·ã¹ãã ã³ãŒã«ããšåŒã°ãã颿°ãåŒã³åºããå©çšããŠãã颿°ãã·ã¹ãã ã³ãŒã«ãªã®ãåŠãã¯ãå©çšããåŽãšããŠã¯ç¹ã«æ°ã«ããå¿ èŠã¯ãªããããããã€ãã®é¢æ°ã¯ã·ã¹ãã ã³ãŒã«ãšåŒã°ããã«ãŒãã«ã«çŽæ¥åŠçãäŸé Œãããã®ã ããšããããšã ãç¥ã£ãŠãããŠããã ãããã
ã·ã¹ãã ã³ãŒã«ã¯ã«ãŒãã«ã«ç¹æã®åŠçã ãUNIXç³»OSã®ã«ãŒãã«ã¯å€§äœå ±éã®ã·ã¹ãã ã³ãŒã«ãæã£ãŠãããããããããã€ãã®ã·ã¹ãã ã³ãŒã«ã¯ããããã®ã«ãŒãã«ã«ç¹æã®ãã®ã§ãã»ãã®ã«ãŒãã«ã¯æã£ãŠããªããCèšèªã§ããã°ã©ã ãæžãããšã§ãããããåã ã®ã«ãŒãã«ã«ç¹æã®åŠçãèªç±ã«å©çšã§ãããã·ã§ã«ã¹ã¯ãªãããã€ã³ã¿ããªã¿èšèªã䜿ããã«Cèšèªãå©çšããã¢ãããŒã·ã§ã³ã®1ã€ã ã
ã·ã¹ãã ã³ãŒã«ãinotify(2)ç³»ã
Linuxã«ãŒãã«ã¯ãã¡ã€ã«ã·ã¹ãã ã€ãã³ããã¢ãã¿ãªã³ã°ããæ©èœãšããŠinotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ãæäŸããŠãããinotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ãå©çšããããšã§ããã£ã¬ã¯ããªããã¡ã€ã«ãã¢ãã¿ãªã³ã°ããŠãã€ãã³ããçºçããå Žåã«åŠçãè¡ããšãã£ãããšãã§ããããã«ãªãã
äŸãã°ããã£ã¬ã¯ããªããã¡ã€ã«ãã¢ãã¿ãªã³ã°ãããã¡ã€ã«ããã£ã¬ã¯ããªã«äœããã®å€æŽãçºçãããŸã§åŠçã忢ããããšãã£ãã³ãã³ããéçºããããšãã§ããïŒãã°ãã¡ã€ã«ã«æžã蟌ã¿ããããŸã§åŸ æ©ããããªã©ïŒããã¡ã€ã«ããã£ã¬ã¯ããªã倿Žããããã©ããã宿çãã€èªåçã«ïŒäŸãã°1ç§ããšã«ïŒèª¿ã¹ãŠãããããªä»çµã¿ãäœãå¿ èŠããªããinotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ãå©çšããã ãã§äºè¶³ãããèªåçã«èª¿ã¹ã«è¡ãæ¹æ³ããã軜éã§é«éã ããæ£ç¢ºã ã
Cèšèªã䜿ã£ãéçºçµéšããªãå Žåãããããã·ã¹ãã ã³ãŒã«ã䜿ã£ãã³ãŒãã£ã³ã°ã¯æ·å± ãé«ããšæãããããã£ãå Žåã«ã¯ãŸããµã³ãã«ã³ãŒããã³ã³ãã€ã«ããŠå©çšããæ¹æ³ã詊ããŠã¿ããšããã
inotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ã«é¢ããŠã¯ããã¥ã¢ã«ã«è¯ããµã³ãã«ã³ãŒããæ²èŒãããŠããã®ã§ããããå©çšãããšããã ããããman inotifyãã§è¡šç€ºãããããã¥ã¢ã«ã«æ²èŒãããŠããæ¬¡ã®ã³ãŒãããã®ãŸãŸäœ¿ã£ãŠã¿ããã
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
/* Read all available inotify events from the file descriptor 'fd'.
wd is the table of watch descriptors for the directories in argv.
argc is the length of wd and argv.
argv is the list of watched directories.
Entry 0 of wd and argv is unused. */
static void
handle_events(int fd, int *wd, int argc, char* argv[])
{
/* Some systems cannot read integer variables if they are not
properly aligned. On other systems, incorrect alignment may
decrease performance. Hence, the buffer used for reading from
the inotify file descriptor should have the same alignment as
struct inotify_event. */
char buf[4096]
__attribute__ ((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *event;
int i;
ssize_t len;
char *ptr;
/* Loop while events can be read from inotify file descriptor. */
for (;;) {
/* Read some events. */
len = read(fd, buf, sizeof buf);
if (len == -1 && errno != EAGAIN) {
perror("read");
exit(EXIT_FAILURE);
}
/* If the nonblocking read() found no events to read, then
it returns -1 with errno set to EAGAIN. In that case,
we exit the loop. */
if (len <= 0)
break;
/* Loop over all events in the buffer */
for (ptr = buf; ptr < buf + len;
ptr += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *) ptr;
/* Print event type */
if (event->mask & IN_OPEN)
printf("IN_OPEN: ");
if (event->mask & IN_CLOSE_NOWRITE)
printf("IN_CLOSE_NOWRITE: ");
if (event->mask & IN_CLOSE_WRITE)
printf("IN_CLOSE_WRITE: ");
/* Print the name of the watched directory */
for (i = 1; i < argc; ++i) {
if (wd[i] == event->wd) {
printf("%s/", argv[i]);
break;
}
}
/* Print the name of the file */
if (event->len)
printf("%s", event->name);
/* Print type of filesystem object */
if (event->mask & IN_ISDIR)
printf(" [directory]\n");
else
printf(" [file]\n");
}
}
}
int
main(int argc, char* argv[])
{
char buf;
int fd, i, poll_num;
int *wd;
nfds_t nfds;
struct pollfd fds[2];
if (argc < 2) {
printf("Usage: %s PATH [PATH ...]\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("Press ENTER key to terminate.\n");
/* Create the file descriptor for accessing the inotify API */
fd = inotify_init1(IN_NONBLOCK);
if (fd == -1) {
perror("inotify_init1");
exit(EXIT_FAILURE);
}
/* Allocate memory for watch descriptors */
wd = calloc(argc, sizeof(int));
if (wd == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
/* Mark directories for events
- file was opened
- file was closed */
for (i = 1; i < argc; i++) {
wd[i] = inotify_add_watch(fd, argv[i],
IN_OPEN | IN_CLOSE);
if (wd[i] == -1) {
fprintf(stderr, "Cannot watch '%s'\n", argv[i]);
perror("inotify_add_watch");
exit(EXIT_FAILURE);
}
}
/* Prepare for polling */
nfds = 2;
/* Console input */
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
/* Inotify input */
fds[1].fd = fd;
fds[1].events = POLLIN;
/* Wait for events and/or terminal input */
printf("Listening for events.\n");
while (1) {
poll_num = poll(fds, nfds, -1);
if (poll_num == -1) {
if (errno == EINTR)
continue;
perror("poll");
exit(EXIT_FAILURE);
}
if (poll_num > 0) {
if (fds[0].revents & POLLIN) {
/* Console input is available. Empty stdin and quit */
while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
continue;
break;
}
if (fds[1].revents & POLLIN) {
/* Inotify events are available */
handle_events(fd, wd, argc, argv);
}
}
}
printf("Listening for events stopped.\n");
/* Close inotify file descriptor */
close(fd);
free(wd);
exit(EXIT_SUCCESS);
}
ã¡ãã£ãšé·ããšæãããããããªããããã®ãµã³ãã«ã³ãŒãã«ã¯inotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ãå©çšããããã®ãšãã»ã³ã¹ãããããå ¥ã£ãŠãããå®éã«äœ¿ããšãã«ã¯ããããå¿ èŠãªãšãããæãåºããŠãèªåãªãã«å¿çšããªãã䜿ã£ãŠããã°ãããšæããé æ¬¡èª¬æããŠããã®ã§ãä»ã¯ãŸã ããããããªããŠã倧äžå€«ã ã
ã³ã³ãã€ã«ãšå®è¡
ãªã³ã©ã€ã³ããã¥ã¢ã«ã«æ²èŒãããŠãããµã³ãã«ã³ãŒãããtryinotify.cããšãããã¡ã€ã«ã«ä¿åãããšããããã®å Žåãæ¬¡ã®ããã«ccã³ãã³ããå®è¡ããã°ãtryinotifyããšãããã€ããªãçæãããã
cc try_inotify.c -o try_inotify
åå玹ä»ããMakefileãæ¬¡ã®ããã«ç·šéããŠå©çšããŠãããã
SRCS= try_inotify.c
CMD= try_inotify
OBJS= ${SRCS:.c=.o}
all: ${OBJS}
cc -o ${CMD} ${OBJS}
.SUFFIXES: .c .c
.c.o:
cc -c $<
clean:
rm -f ${OBJS} ${CMD}
ãã®Makefileã䜿ããªããmakeã§ã³ã³ãã€ã«ïŒãã«ãïŒãå®è¡ãããã
ã§ã¯ãçæããããã€ããªãã¡ã€ã«ïŒtry_inotifyïŒãå®è¡ããŠã¿ããããããšã次ã®ããã«åŒæ°ã«ã¢ãã¿ãªã³ã°å¯Ÿè±¡ã®ãã¡ã€ã«ããã£ã¬ã¯ããªã®æå®ãæ±ããããŠããããšããããã®ã§ã空ã®ãlogããšãããã¡ã€ã«ãäœæããŠåŒæ°ã«æå®ãããšãã¢ãã¿ãªã³ã°ãéå§ãããããšã確èªã§ããã
tryinotifyãå®è¡ããŠããã®ãšã¯å¥ã®ã¿ãŒããã«ã¢ããªã±ãŒã·ã§ã³ã§å ã»ã©äœæããlogãã¡ã€ã«ã«å¯Ÿããæ¬¡ã®ããã«ããŠæååãæžã蟌ããšãtryinotifyã³ãã³ãããã¡ãã»ãŒãžãåºåãããããšã確èªã§ããã
echo log_message > log
次ã®ããã«ã¢ãã¿ãªã³ã°å¯Ÿè±¡ã®ãã¡ã€ã«ãåé€ããŠã¿ãŠããtry_inotifyã³ãã³ããlogãã¡ã€ã«ã«çºçããã€ãã³ããæ€åºããŠåºåããŠããããšã確èªã§ããã
rm log
ãªãããã£ããã¢ãã¿ãªã³ã°å¯Ÿè±¡ã®ãã¡ã€ã«ãåé€ãããšãåãååã®ãã¡ã€ã«ãäœãçŽããŠãããã¢ãã¿ãªã³ã°ã®å¯Ÿè±¡ã«ã¯ãªããªãããªããªãããã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãå€ãã£ãŠããŸãããã ããã¡ã€ã«ãæ°ããäœã£ããªããtry_inotifyã³ãã³ããäžåºŠçµäºããŠããæ¹ããŠå®è¡ããå¿ èŠãããã
å°ããäœã£ãŠè©ŠããŠããã
Cèšèªã®ã³ãŒãã£ã³ã°ãããããšããªãæ¹ã«ã¯ãtry_inotify.cã¯ããªãé£è§£ãªã³ãŒããããããªããããããæç€ºçã«ã·ã¹ãã ã³ãŒã«ãæå³ããã³ãŒãã£ã³ã°ãè¡ãéã®åèã«ããã«ã¯ãªããªãããçŽ æãªã®ã§ãæ¬é£èŒã§ã¯æ°åã«åããŠããã®ãœãŒã¹ã³ãŒãã«ã€ããŠèª¬æããŠãããããšæãã倧åãªã®ã¯ãããªããã¹ãŠãçè§£ããããšããªãã§ãå°ããå°ããçè§£ãšå®è·µãéããŠããããšã ããã®ç©ã¿éãã¯ããã®ãŸãŸã¹ãã«ãšããŠèº«ã«ä»ããããã
ã¡ãªã¿ã«ãinotify(2)ç³»ã®ã·ã¹ãã ã³ãŒã«ã¯Linuxã«ãŒãã«ã«ç¹æã®ãã®ã ããã»ãã®ã«ãŒãã«ã«ã¯ã»ãã®ã«ãŒãã«ã§åæ§ã®æ©èœãå®çŸããããã®ã·ã¹ãã ã³ãŒã«ãçšæãããŠããã代衚çãªãã®ãšããŠã¯ãmacOSãFreeBSDã«ãŒãã«ã®kqueue(2)ã·ã¹ãã ã³ãŒã«ãæãããããkqueueãç¬èªã®ã·ã¹ãã ã³ãŒã«ã ãã*BSDç³»ã®ã«ãŒãã«ã§ã¯å®è£ ãããŠãããæ§èœãæåŸ ã§ããã®ã§ããã©ãŒãã³ã¹ãæ±ããããã°ã©ã ã§ã¯ãã§ã«é·ãã«ããã£ãŠäœ¿ãããŠãããæåãªã·ã¹ãã ã³ãŒã«ã®1ã€ã ã


