linux系统文件系统坏了监控,Linux中的文件系统监控机制(inotify)

1 What’s inotify

The inotify API provides a mechanism for monitoring file system events. Inotify can be used to monitor individual files, or to monitor directories. When a directory is monitored, inotify will return events for the directory itself, and for files inside the directory.

2 How to use inotify

2.1 system calls used with this API

The following system calls are used with this API: inotify_init(orinotify_init1), inotify_add_watch, inotify_rm_watch,read, and close.

2.1.1 inotify_initIt creates an inotify instance and returns a file descriptor referring to the inotify instance. The more recent inotify_init1is like inotify_init, but provides some extra functionality.

2.1.2 inotify_add_watch

It manipulates the "watch list" associated with an inotify instance. Each item ("watch") in the watch list specifies the pathname of a file or directory, along with some set of events that the kernel should monitor for the file referred to by that pathname.

inotify_add_watcheither creates a new watch item, or modifies an existing watch. Each watch has a unique "watch descriptor", an integer returned byinotify_add_watchwhen the watch is created.

2.1.3inotify_rm_watch

It removes an item from an inotify watch list.

When all file descriptors referring to an inotify instance have been closed, the underlying object and its resources are freed for reuse by the kernel; all associated watches are automatically freed.

2.1.4 read

To determine what events have occurred, an applicationreads from the inotify file descriptor. If no events have so far occurred, then, assuming a blocking file descriptor,readwill block until at least one event occurs (unless interrupted by a signal, in which case the call fails with the error EINTR; seesignal(7)).

Each successful readreturns a buffer containing one or more of the following structures:

struct inotify_event {

int      wd;       /* Watch descriptor */

uint32_t mask;     /* Mask of events */

uint32_t cookie;   /* Unique cookie associating related events (forrename) */

uint32_t len;      /* Size of name field */

char     name[];   /* Optional null-terminated name */

};

2.2 Inotify events

Theinotify_add_watchmask argument and the mask field of the inotify_event structure returned whenreading an inotify file descriptor are both bit masks identifying inotify events. The following bits can be specified in mask when callinginotify_add_watchand may be returned in the mask field returned byread:

IN_ACCESSFile was accessed (read) (*).

IN_ATTRIBMetadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*).

IN_CLOSE_WRITEFile opened for writing was closed (*).

IN_CLOSE_NOWRITEFile not opened for writing was closed (*).

IN_CREATEFile/directory created in watched directory (*).

IN_DELETEFile/directory deleted from watched directory (*).

IN_DELETE_SELFWatched file/directory was itself deleted.

IN_MODIFYFile was modified (*).

IN_MOVE_SELFWatched file/directory was itself moved.

IN_MOVED_FROMFile moved out of watched directory (*).

IN_MOVED_TOFile moved into watched directory (*).

IN_OPENFile was opened (*).

……

2.3 The flow for the systme calls used with inotify

1372595857_db270539.jpg

3 Example used with Inotify

3.1 Description:

There are three subfunctions below : input_run, worker_thread,worker_cleanup.

The subfunction "input_run" is called by the main function .when it’s called,the input_run will creat a thread "worker_thread". when the thread is exit it will call the "worker_cleanup".

In the worker_thread we monitor the folder “/temp”.If a file(here it’s a picture) is move to the folder, we open it ,copy it’s context to a frame buffer for using ,then we delete the file if necessary.

3.2 source code:

#include

#include

#include

#include

#include

/* global variables for this plugin */

static char*folder = /temp;

staticintfd, rc, wd, size;

staticstructinotify_event *ev;

intinput_run(intid)

{

pglobal->in[id].buf = NULL;

rc = fd = inotify_init();

if(rc == -1) {

perror("could not initilialize inotify");

return1;

}

rc = wd = inotify_add_watch(fd, folder, IN_CLOSE_WRITE | IN_MOVED_TO | IN_ONLYDIR);

if(rc == -1) {

perror("could not add watch");

return1;

}

size =sizeof(structinotify_event) + (1 << 16);

ev =malloc(size);

if(ev == NULL) {

perror("not enough memory");

return1;

}

if(pthread_create(&worker, 0, worker_thread, NULL) != 0) {

free(pglobal->in[id].buf);

fprintf(stderr,"could not start worker thread\n");

exit(EXIT_FAILURE);

}

pthread_detach(worker);

return0;

}

/* the single writer thread */

void*worker_thread(void*arg)

{

charbuffer[1<<16];

intfile;

size_t filesize = 0;

structstat stats;

/* set cleanup handler to cleanup allocated ressources */

pthread_cleanup_push(worker_cleanup, NULL);

while(!pglobal->stop) {

/* wait for new frame, read will block until something happens */

rc =read(fd, ev, size);

if(rc == -1) {

perror("reading inotify events failed");

break;

}

/* sanity check */

if(wd != ev->wd) {

fprintf(stderr,"This event is not for the watched directory (%d != %d)\n", wd, ev->wd);

continue;

}

if(ev->mask & (IN_IGNORED | IN_Q_OVERFLOW | IN_UNMOUNT)) {

fprintf(stderr,"event mask suggests to stop\n");

break;

}

/***************** your reaction to the enent******************/

/* prepare filename */

/* check if the filename matches specified parameter (if given)*/

/* open file for reading */

/* approximate size of file */

/* copy frame from file to global buffer */

pthread_mutex_lock(&pglobal->in[plugin_number].db);

/* allocate memory for frame */

/* signal fresh_frame */

pthread_cond_broadcast(&pglobal->in[plugin_number].db_update);

pthread_mutex_unlock(&pglobal->in[plugin_number].db);

/* close file */

/* delete file if necessary */

/***************** your reaction to the event*******************/

}

DBG("leaving input thread, calling cleanup function now\n");

/* call cleanup handler, signal with the parameter */

pthread_cleanup_pop(1);

returnNULL;

}

voidworker_cleanup(void*arg)

{

staticunsignedcharfirst_run = 1;

if(!first_run) {

DBG("already cleaned up ressources\n");

return;

}

first_run = 0;

DBG("cleaning up ressources allocated by input thread\n");

if(pglobal->in[plugin_number].buf != NULL)free(pglobal->in[plugin_number].buf);

free(ev);

rc = inotify_rm_watch(fd, wd);

if(rc == -1) {

perror("could not close watch descriptor");

}

rc =close(fd);

if(rc == -1) {

perror("could not close filedescriptor");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值