티스토리 뷰
리눅스 프로그래밍중 특정 폴더를 감시해야 하는 경우가 있습니다.
해당 기능을 구현하기 위한 방안은 여러가지가 있는데요, 이를테면, 그 폴더의 SIGIO를 등록해서 폴더의 input/output을 감시할 수 있습니다.
하지만 이 경우에는 create / write / close / delete 등을 별도로 구분하지 못하는 부족함이 있습니다. 또한 signal의 경우 중복으로 요청이 들어올 경우 앞선 signal을 잃어버리는 경우도 발생하기 때문에 좋은 방안은 아닌듯 보이죠.. (fcntl 를 이용한 signal 처리에도 create/rename/close 등을 구분할 수는 있네요^^;)
이때 대안이 되는방법이 inotify_add_watch() 라는 함수를 사용하는 것 입니다. 일단 형태는 아래와 같습니다.
#include <sys/inotify.h>
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
세번째 인자인 mask는 감시 대상의 상태 변화를 표현합니다. 표현할 수 있는 mask에는 아래와 같습니다.
/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */
#define IN_ACCESS 0x00000001 /* File was accessed. */
#define IN_MODIFY 0x00000002 /* File was modified. */
#define IN_ATTRIB 0x00000004 /* Metadata changed. */
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
#define IN_OPEN 0x00000020 /* File was opened. */
#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */
#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
#define IN_CREATE 0x00000100 /* Subfile was created. */
#define IN_DELETE 0x00000200 /* Subfile was deleted. */
#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */
#define IN_MOVE_SELF 0x00000800 /* Self was moved. */
/* Events sent by the kernel. */
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted. */
#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed. */
#define IN_IGNORED 0x00008000 /* File was ignored. */
/* Helper events. */
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
/* Special flags. */
#define IN_ONLYDIR 0x01000000 /* Only watch the path if it is a
directory. */
#define IN_DONT_FOLLOW 0x02000000 /* Do not follow a sym link. */
#define IN_MASK_ADD 0x20000000 /* Add to the mask of an already
existing watch. */
#define IN_ISDIR 0x40000000 /* Event occurred against dir. */
#define IN_ONESHOT 0x80000000 /* Only send event once. */
/* All events which a program can wait on. */
#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \
| IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \
| IN_MOVED_TO | IN_CREATE | IN_DELETE \
| IN_DELETE_SELF | IN_MOVE_SELF)
자, 이제 사용방법을 살펴봅니다. inotify_add_watch() 를 사용하기 위해서는 등록이 필요하겠죠, 아래 함수를 사용합니다.
#include <sys/inotify.h>
int inotify_init(void)
연계해서 간단한 파일의 이동을 감시하는 구문을 작성해보면 아래와 같습니다.
// init
fd = inotify_init();
// 감시 PATH 등록
wd = inotify_add_watch(fd, PATH, IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVED_TO | IN_CLOSE ...);
length = read( fd, buffer, BUF_LEN );
while ( i < length ) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len ) {
if ( event->mask & IN_MOVED_TO) { // 해당 조건처럼 & 연산을 통해 else if 추가 등록
if ( event->mask & IN_ISDIR ) {
printf("The directory %s was move.\n", event->name );
}
else {
printf("The file %s was move.\n", event->name );
}
}
i += EVENT_SIZE + event->len;
}
}
inotify_event 구조체를 통해 파일의 이름 등 알수 있는 정보가 다양한데, 구조체는 아래와 같습니다.
/* Structure describing an inotify event. */
struct inotify_event
{
int wd; /* Watch descriptor. */
uint32_t mask; /* Watch mask. */
uint32_t cookie; /* Cookie to synchronize two events. */
uint32_t len; /* Length (including NULs) of name. */
char name __flexarr; /* Name. */
};
이제 inotify_add_watch()의 사용으로 특정 폴더의 상태 변화를 감지할 수 있는 코드를 작성 할 수 있습니다.
단, 커널에 아래 옵션이 활성화 되어 있어야 합니다.
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
(커널 2.6.13 이상 부터 지원)
'개발 > Linux' 카테고리의 다른 글
리눅스 콘솔 글씨 색상 지정 (0) | 2013.09.16 |
---|---|
applicatioin에서 call trace 출력 (message) (0) | 2013.09.11 |
vi 문자열 치환 (0) | 2013.07.18 |
Why do a lot of #defines in the kernel use do { ... } while(0)? (0) | 2013.05.09 |
커널에서 사용 가능한 DNS 개수? (0) | 2012.06.27 |
- Total
- Today
- Yesterday