在前面的博客《用可变参数扩展printf》中讨论到如何在应用中控制log的输出。
我们假设的情景是,一个长期运行的Linux程序,想在不退出运行的情况下,通过某种机制,可以让程序知道要不要打印出log 。
我们当时的实现是:
- 创建一个文件,写进标志位
- 然后每次要打印log之前先读取这个文件,按照标志位是什么来决定要不要打印log
这样子我们在linux系统上,如果不想打印出这些log,可以向这个文件写其他标志位。
但是,这种做法效率太低了。那如何解决上面的问题呢?
有两种做法:
- 一种是linux inotify机制
- 另外一种是linux 信号机制。注册一个信号,文件更改了,向这个程序发信号,printf_my_log再重新读取。
在本节中,讲的是linux inotify机制。
参考资料http://www.man7.org/linux/man-pages/man7/inotify.7.html
Inotify机制作用:
- Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。
- Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。
inotify既可以监控文件,也可以监控目录。这里我们用来监视文件printlog。
下面讲一下如何在程序中使用Inotify机制。
第一步是创建 inotify 实例。
int fd = inotify_init ();
也可以用inotifyFd = inotify_init1(IN_NONBLOCK) 实现非阻塞
每一个 inotify 实例对应一个独立的排序的队列。
第二步是添加需要被监视的文件。
下面函数用于添加一个 watch:
参数含义:
fd : inotify_init() 返回的文件描述符
path :被监视的目标的路径名(即文件名或目录名)
mask: 是事件掩码
int wd = inotify_add_watch (fd, path, mask);
第三步是读取inotify_event 数据到buf。
numRead = read(inotifyFd,buf,BUF_LEN); //读取不到会阻塞
第四步是解析读取的数据,一般是根据inotify_event结构中的mask成员来判断的。
for(p=buf;p < buf+numRead;p+=sizeof(struct inotify_event) + event->len)
{
event = (struct inotify_event *)p;
if(event->mask & IN_ACCESS) printf("IN_ACCESS\n");
if(event->mask & IN_DELETE_SELF) printf("DELETE_SELF\n");
if(event->mask & IN_MODIFY) printf("IN_MODIFY\n");
if(