在描述之前,要说明一下,我代码中的inotify使用方式,这个方式和网上大多方式一样:
#include
#include
#include
static const char kszConfigPath[] = "/usr/local/path/to/config";
static int s_running = 0;
extern int reparse_config();
int inotify_loop()
{
int inot_fd = -1;
int watch_fd = -1;
unsigned int watch_flag = IN_MODIFY;
fd_set read_fds;
struct timeval seltime;
char buffer[16384];
int buffer_i = 0;
int inot_fd = inotify_init();
if (inot_fd < 0) {
printf("inotify_init error %d\n", errno);
return -1;
}
/* Watch config file. */
watch_fd = inotify_add_watch(inot_fd, kszConfigPath, watch_flag);
if (watch_fd < 0) {
printf("inotify_init error %d\n", errno);
close(inot_fd);
return -1;
}
while (s_running) {
int selret = 0;
int read_cnt = 0;
FD_ZERO(&read_fds);
FD_SET(inot_fd, &read_fds);
seltime.tv_sec = 1;
seltime.tv_usec = 0;
selret = select(inot_fd + 1, &read_fds, NULL, NULL, &seltime);
if (selret < 0) {
printf("select error %d\n", errno);
continue;
} else if (selret == 0) {
continue;
}else if (!FD_ISSET(inot_fd, &read_fds)) {
printf("inot_fd not in fdset\n");
continue;
}
read_cnt = read(fd, buffer, sizeof(buffer));
if (read_cnt <= 0) {
printf("read <= 0 (%d)\n", read_cnt);
continue;
}
buffer_i = 0;
while (buffer_i < read_cnt) {
/* Parse events and queue them. */
struct inotify_event* pevent = (struct inotify_event*)&buffer[buffer_i];
if (pevent->mask & IN_MODIFY) {
printf("config %s modified\n", kszConfigPath);
reparse_config();
} else {
printf("Unrecognized event mask %d\n", pevent->mask);
}
buffer_i += sizeof(struct inotify_event) + pevent->len;
}
}
/** Remove watch. */
if (inotify_rm_watch(inot_fd, watch_fd) < 0) {
printf("inotify_rm_watch error %d\n", errno);
}
return 0;
}
一、使用vi编辑a文件,然后保存。程序没有截获IN_MODIFY事件,打印的是Unrecongnized event mask 32768。
#include
#include
#include
static const char kszConfigPath[] = "/usr/local/path/to/config";
static int s_running = 0;
extern int reparse_config();
#ifdef _WIN32
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
int inotify_init(void);
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
int inotify_rm_watch(int fd, int wd);
#endif
int set_non_blocking(fd)
{
int fd_flag = 0;
if (fd < 0)
return EINVAL;
fd_flag = fcntl(fd, F_GETFL, 0);
if (fd_flag < 0)
fd_flag = 0;
return fcntl(fd, F_SETFL, fd_flag | O_NONBLOCK);
}
int rm_inotify_wd(int fd, int wd)
{
char ignore[1024];
if (fd < 0 || wd < 0)
return EINVAL;
while (read(fd, ignore) > 0) {
/* Ignore previous unread notify events. */
continue;
}
return inotify_rm_watch(fd, wd);
}
int inotify_loop()
{
int selret = 0;
int read_cnt = 0;
int inot_fd = -1;
int watch_fd = -1;
int need_parse = 0;
int need_remove_wd = 0;
unsigned int watch_flag = IN_CLOSE_WRITE | IN_CREATE | IN_DELETE
| IN_DELETE_SELF | IN_MOVE | IN_MOVE_SELF;
fd_set read_fds;
struct timeval seltime;
char buffer[16384];
int buffer_i = 0;
if ((inot_fd = inotify_init()) < 0) {
printf("inotify_init error %d\n", errno);
return -1;
}
if (set_non_blocking(inot_fd) < 0) {
printf("set_non_blocking error %d\n", errno);
}
while (s_running) {
new_init= 0;
if (watch_fd < 0) {
/* Watch config file. */
if ((watch_fd = inotify_add_watch(inot_fd, kszConfigPath, watch_flag)) < 0) {
printf("inotify_init error %d\n", errno);
} else {
/* Non-existed -> existed, reparse immediately.*/
reparse_config();
}
}
seltime.tv_sec = 1;
seltime.tv_usec = 0;
if (watch_fd < 0) {
selret = select(NULL, NULL, NULL, NULL, &seltime);
} else {
FD_ZERO(&read_fds);
FD_SET(inot_fd, &read_fds);
selret = select(inot_fd + 1, &read_fds, NULL, NULL, &seltime);
}
if (selret < 0) {
printf("select error %d\n", errno);
continue;
} else if (selret == 0) {
continue;
} else if (!FD_ISSET(inot_fd, &read_fds)) {
printf("inot_fd not in fdset\n");
continue;
}
read_cnt = read(fd, buffer, sizeof(buffer));
if (read_cnt <= 0) {
printf("read <= 0 (%d)\n", read_cnt);
continue;
}
need_parse = 0;
need_remove_wd = 0;
buffer_i = 0;
while (buffer_i < read_cnt) {
/* Parse events and queue them. */
struct inotify_event* pevent = (struct inotify_event*)&buffer[buffer_i];
if (pevent->mask & IN_MODIFY) {
printf("config %s modified\n", kszConfigPath);
} else if (pevent->mask & IN_CLOSE_WRITE) {
printf("config %s close for writing\n", kszConfigPath);
need_parse = 1;
} else if (pevent->mask & IN_CREATE) {
printf("config %s created\n", kszConfigPath);
need_parse = 1;
} else if (pevent->mask & (IN_DELETE | IN_DELETE_SELF)) {
printf("config %s was deleted\n", kszConfigPath);
need_parse = 1;
need_remove_wd = 1;
} else if (pevent->mask & (IN_MOVE | IN_MOVE_SELF)) {
printf("config %s was removed\n", kszConfigPath);
need_parse = 1;
need_remove_wd = 1;
} else {
printf("Unrecognized event mask %d\n", pevent->mask);
}
buffer_i += sizeof(struct inotify_event) + pevent->len;
}
if (need_parse) {
reparse_config();
}
if (need_remove_wd) {
int ret = rm_inotify_wd(inot_fd, watch_fd);
if (ret < 0) {
printf("rm_inotify_wd error %d\n", ret);
}
watch_fd = -1;
}
}
/** Remove watch. */
if (inotify_rm_watch(inot_fd, watch_fd) < 0) {
printf("inotify_rm_watch error %d\n", errno);
}
close(inot_fd);
return 0;
}