inotify
파일 시스템 이벤트를 커널레벨로부터 받을 수 있는 방법임.
리눅스 커널 2.6.13 이상부터 가능함. (그 이전엔 dnotify)
굉장히 간단함.
inotify_init() 로 fd를 얻어서,
inotify_add_watch()로 감시자를 붙임.
inotify_rm_watch()로 감시자 해제.
완전 간단한 예제소스
/*
출처 : http://www.ibm.com/developerworks/kr/library/l-ubuntu-inotify/index.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
int main( int argc, char **argv )
{
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];
fd = inotify_init();
if ( fd < 0 ) {
perror( "inotify_init" );
}
wd = inotify_add_watch( fd, "/home/strike",
IN_MODIFY | IN_CREATE | IN_DELETE );
length = read( fd, buffer, BUF_LEN );
if ( length < 0 ) {
perror( "read" );
}
while ( i < length ) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len ) {
if ( event->mask & IN_CREATE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was created.\n", event->name );
}
else {
printf( "The file %s was created.\n", event->name );
}
}
else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was deleted.\n", event->name );
}
else {
printf( "The file %s was deleted.\n", event->name );
}
}
else if ( event->mask & IN_MODIFY ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was modified.\n", event->name );
}
else {
printf( "The file %s was modified.\n", event->name );
}
}
}
i += EVENT_SIZE + event->len;
}
( void ) inotify_rm_watch( fd, wd );
( void ) close( fd );
exit( 0 );
}
출처 : http://www.ibm.com/developerworks/kr/library/l-ubuntu-inotify/index.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
int main( int argc, char **argv )
{
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];
fd = inotify_init();
if ( fd < 0 ) {
perror( "inotify_init" );
}
wd = inotify_add_watch( fd, "/home/strike",
IN_MODIFY | IN_CREATE | IN_DELETE );
length = read( fd, buffer, BUF_LEN );
if ( length < 0 ) {
perror( "read" );
}
while ( i < length ) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len ) {
if ( event->mask & IN_CREATE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was created.\n", event->name );
}
else {
printf( "The file %s was created.\n", event->name );
}
}
else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was deleted.\n", event->name );
}
else {
printf( "The file %s was deleted.\n", event->name );
}
}
else if ( event->mask & IN_MODIFY ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was modified.\n", event->name );
}
else {
printf( "The file %s was modified.\n", event->name );
}
}
}
i += EVENT_SIZE + event->len;
}
( void ) inotify_rm_watch( fd, wd );
( void ) close( fd );
exit( 0 );
}
event 구조체
struct inotify_event
{
int wd; /* watch descriptor */
uint32_t mask; /* event tag */
uint32_t cookie; /* 두 event(IN_MOVED_FROM, IN_MOVED_TO)를 하나로 묶는 쿠키 */
uint32_t len; /* name 필드에 들어있는 파일 이름 길이 */
char name __flexarr; /* 파일이름, NULL terminated */
}
{
int wd; /* watch descriptor */
uint32_t mask; /* event tag */
uint32_t cookie; /* 두 event(IN_MOVED_FROM, IN_MOVED_TO)를 하나로 묶는 쿠키 */
uint32_t len; /* name 필드에 들어있는 파일 이름 길이 */
char name __flexarr; /* 파일이름, NULL terminated */
}
발생 이벤트
IN_ACCESS : 파일에 접근했음 (read)
IN_ATTRIB : 권한, 시간 등의 메타데이터가 변했음
IN_CLOSE_WRITE : 쓰기(write)를 위해 열린 파일이 닫혔음 (close)
IN_CLOSE_NOWRITE : 쓰기(write)가 아닌 모드로 열린 파일이 닫혔음 (close)
IN_CREATE : 감시하고 있던 디렉토리에 파일/디렉토리가 생성됨
IN_DELETE : 감시하고 있던 디렉토리에서 파일/디렉토리가 삭제됨
IN_DELETE_SELF : 감시하고 있던 파일/디렉토리 자체가 삭제됨
IN_MODIFY : 파일이 변경되었음
IN_MOVE_SELF : 감시하고 있던 파일/디렉토리가 이동함 (move)
IN_MOVED_FROM : 감시하고 있던 디렉토리에서 파일이 이동해 나갔음 (move)
IN_MOVED_TO : 감시하고 있던 디렉토리에 파일이 이동해 들어왔음 (move)
IN_OPEN : 파일이 열렸음
IN_ALL_EVENTS : 상단에 열거한 모든 이벤트들을 모두 지정함
IN_MOVE : IN_MOVED_FROM | IN_MOVED_TO
IN_CLOSE : IN_CLOSE_WRITE | IN_CLOSE_NOWRITE
IN_DONT_FOLLOW : 심볼릭 링크를 dereference 하지 않음
IN_MASK_ADD : 감시하고 있던 경로에 이미 이벤트가 지정되어 있다면 mask를 교체하지 않고 이벤트를 추가함.
IN_ONESHOT : 단 한번의 이벤트만을 감시하고 이벤트 발생시 감시리스트에서 삭제
IN_ONLYDIR : 감시경로가 디렉토리일 경우 경로만을 감시함.
아래의 Bit들은 read 에서 리턴된 다음에만 지정이 가능함.
IN_IGNORED : 감시가 명시적(inotify_rm_watch()) 혹은 자동적(파일이 지워졌거나, 파일시스템이 unmount 되었을 경우)으로 제거됨.
IN_ISDIR : 디렉토리인가...(-_-)
IN_Q_OVERFLOW : 이벤트큐가 overflow 되었는가 (이 경우 wd = -1)
IN_UNMOUNT : 감시하고 있던 파일시스템이 unmouse 되었음.
[참고]
http://en.wikipedia.org/wiki/Inotify
http://www.ibm.com/developerworks/kr/library/l-ubuntu-inotify/index.html
'C, C++' 카테고리의 다른 글
[C/C++] Unix에서 C 언어로 email 보내는 방법 (0) | 2009.04.19 |
---|---|
[C/C++] 스트링 종류들... (0) | 2009.04.18 |
[C/C++] strlen 사용시 warning 뜨는 거 해결 (signed/unsigned mismatch) (0) | 2009.04.18 |
[C (Linux)] TCP/IP 간단한 에코서버 (0) | 2009.04.18 |