fanotify(7) - wariua/manpages-ko GitHub Wiki

NAME

fanotify - ํŒŒ์ผ ์‹œ์Šคํ…œ ์ด๋ฒคํŠธ ๊ฐ์‹œํ•˜๊ธฐ

DESCRIPTION

fanotify API๋ฅผ ํ†ตํ•ด ํŒŒ์ผ ์‹œ์Šคํ…œ ์ด๋ฒคํŠธ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์šฉ๋ก€๋กœ๋Š” ๋ฐ”์ด๋Ÿฌ์Šค ๊ฒ€์‚ฌ๋‚˜ ๊ณ„์ธต์  ์ €์žฅ์†Œ ๊ด€๋ฆฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ํ˜„์žฌ๋Š” ์ œํ•œ๋œ ์ข…๋ฅ˜์˜ ์ด๋ฒคํŠธ๋“ค๋งŒ ์ง€์›ํ•œ๋‹ค. ํŠนํžˆ ์ƒ์„ฑ, ์‚ญ์ œ, ์ด๋™ ์ด๋ฒคํŠธ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค. (์ด ์ด๋ฒคํŠธ๋“ค์„ ์•Œ๋ ค ์ฃผ๋Š” API์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ inotify(7)๋ฅผ ๋ณด๋ผ.)

inotify(7) API์™€ ๋น„๊ตํ•˜์ž๋ฉด ๋งˆ์šดํŠธ ํ•œ ํŒŒ์ผ ์‹œ์Šคํ…œ ๋‚ด์˜ ๋ชจ๋“  ๊ฐ์ฒด๋“ค์„ ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๊ณ , ์ ‘๊ทผ ํ—ˆ์šฉ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค๋ฅธ ์‘์šฉ์—์„œ ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ํŒŒ์ผ์„ ์ฝ๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด API์—์„œ ์“ฐ๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ fanotify_init(2), fanotify_mark(2), read(2), write(2), close(2)์ด๋‹ค.

fanotify_init(), fanotify_mark(), ์•Œ๋ฆผ ๊ทธ๋ฃน

fanotify_init(2) ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ fanotify ์•Œ๋ฆผ ๊ทธ๋ฃน์„ ๋งŒ๋“ค์–ด์„œ ์ดˆ๊ธฐํ™” ํ•˜๋ฉฐ ๊ทธ ์•Œ๋ฆผ ๊ทธ๋ฃน์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

fanotify ์•Œ๋ฆผ ๊ทธ๋ฃน์ด๋ž€ ์ปค๋„ ๋‚ด๋ถ€ ๊ฐ์ฒด๋กœ์„œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋  ํŒŒ์ผ, ๋””๋ ‰ํ„ฐ๋ฆฌ, ํŒŒ์ผ ์‹œ์Šคํ…œ, ๋งˆ์šดํŠธ ์ง€์ ๋“ค์˜ ๋ชฉ๋ก์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

fanotify ์•Œ๋ฆผ ๊ทธ๋ฃน ๋‚ด์˜ ๊ฐ ํ•ญ๋ชฉ๋งˆ๋‹ค ํ‘œ์‹œ(mark) ๋งˆ์Šคํฌ์™€ ๋ฌด์‹œ(ignore) ๋งˆ์Šคํฌ๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ๋น„ํŠธ ๋งˆ์Šคํฌ๊ฐ€ ์žˆ๋‹ค. ํ‘œ์‹œ ๋งˆ์Šคํฌ๋Š” ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋  ํŒŒ์ผ ํ™œ๋™๋“ค์„ ๊ทœ์ •ํ•œ๋‹ค. ๋ฌด์‹œ ๋งˆ์Šคํฌ๋Š” ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์„ ํ™œ๋™๋“ค์„ ๊ทœ์ •ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐ€์ง€ ๋งˆ์Šคํฌ๊ฐ€ ์žˆ์–ด์„œ ์–ด๋–ค ํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋‚˜ ๋งˆ์šดํŠธ ์ง€์ , ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๋Š”๋‹ค๊ณ  ํ‘œ์‹œํ•˜๋ฉด์„œ ๋™์‹œ์— ์–ด๋–ค ๋งˆ์šดํŠธ ์ง€์  ๋‚ด์ง€ ๋””๋ ‰ํ„ฐ๋ฆฌ ์•„๋ž˜์˜ ํŠน์ • ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

fanotify_mark(2) ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ ์•Œ๋ฆผ ๊ทธ๋ฃน์— ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ, ํŒŒ์ผ ์‹œ์Šคํ…œ, ๋งˆ์šดํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ณด๊ณ ํ•ด์•ผ (๋˜๋Š” ๋ฌด์‹œํ•ด์•ผ) ํ•˜๋Š”์ง€ ์ง€์ •ํ•œ๋‹ค. ๋˜๋Š” ๊ทธ๋Ÿฐ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•œ๋‹ค.

๋ฌด์‹œ ๋งˆ์Šคํฌ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋กœ ํŒŒ์ผ ์บ์‹œ๊ฐ€ ์žˆ๋‹ค. ํŒŒ์ผ ์บ์‹œ์—์„œ ๊ด€์‹ฌ ์žˆ๋Š” ์ด๋ฒคํŠธ๋Š” ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋˜๊ณ  ๋‹ซํžˆ๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์บ์‹ฑ ๋Œ€์ƒ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋‚ด์ง€ ๋งˆ์šดํŠธ ์ง€์ ์— ๊ทธ ์ด๋ฒคํŠธ๋“ค์„ ๋ฐ›๊ฒ ๋‹ค๊ณ  ํ‘œ์‹œํ•œ๋‹ค. ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋์Œ์„ ์•Œ๋ฆฌ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋ฉด ๋Œ€์‘ํ•˜๋Š” ์บ์‹œ ํ•ญ๋ชฉ์„ ๋ฌดํšจํ™”ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ํŒŒ์ผ์ด ๋‹ซํž ๋•Œ๊นŒ์ง€ ์ดํ›„์˜ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋Š” ์ค‘์š”์น˜ ์•Š๋‹ค. ๋”ฐ๋ผ์„œ ๋ฌด์‹œ ๋งˆ์Šคํฌ์— ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ซํž˜ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋ฉด ๋ฌด์‹œ ๋งˆ์Šคํฌ์—์„œ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ ์„œ ํŒŒ์ผ ์บ์‹œ ํ•ญ๋ชฉ์„ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

fanotify ์•Œ๋ฆผ ๊ทธ๋ฃน ์•ˆ์˜ ํ•ญ๋ชฉ๋“ค์€ ์•„์ด๋…ธ๋“œ๋ฅผ ํ†ตํ•ด ํŒŒ์ผ๊ณผ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ๋งˆ์šดํŠธ ID๋ฅผ ํ†ตํ•ด ๋งˆ์šดํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ๋™์ผ ๋งˆ์šดํŠธ ๋‚ด์—์„œ ์ด๋ฆ„์ด ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ์ด๋™ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋Œ€์‘ ํ•ญ๋ชฉ์ด ์œ ์ง€๋œ๋‹ค. ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์‚ญ์ œ๋˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋งˆ์šดํŠธ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒฝ์šฐ, ๋˜๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋‚˜ ๋งˆ์šดํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋Œ€์‘ ํ•ญ๋ชฉ์ด ์‚ญ์ œ๋œ๋‹ค.

์ด๋ฒคํŠธ ํ

์•Œ๋ฆผ ๊ทธ๋ฃน์œผ๋กœ ๊ฐ์‹œํ•˜๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด๋“ค์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ๊ธฐ๋ฉด fanotify ์‹œ์Šคํ…œ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ํ์— ๋ชจ์•„ ๋‘”๋‹ค. ๊ทธ๋Ÿฌ๋ฉด fanotify_init(2)์ด ๋ฐ˜ํ™˜ํ•œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—์„œ (read(2) ๋“ฑ์œผ๋กœ) ๊ทธ ์ด๋ฒคํŠธ๋“ค์„ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ์—๋Š” ๋‘ ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋Š”๋ฐ ์•Œ๋ฆผ ์ด๋ฒคํŠธ์™€ ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ์ด๋‹ค. ์•Œ๋ฆผ ์ด๋ฒคํŠธ๋Š” ์ •๋ณด๋ฅผ ์ค„ ๋ฟ์ด๋ฏ€๋กœ ๋ฒ”์šฉ ์ด๋ฒคํŠธ๋กœ ์ „๋‹ฌ๋œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋‹ซ์•„ ์ค˜์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ ์™ธ์—๋Š” ์ˆ˜์‹  ์ธก ์‘์šฉ์—์„œ ์–ด๋–ค ํ–‰๋™๋„ ์ทจํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ด๋ฒคํŠธ๋งˆ๋‹ค ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋‹ซ๋Š” ๊ฑด FAN_REPORT_FID(์•„๋ž˜ ์ฐธ๊ณ )๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  fanotify๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ ์‘์šฉ์—๋งŒ ํ•ด๋‹น๋œ๋‹ค. ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ๋Š” ์–ด๋–ค ํŒŒ์ผ ์ ‘๊ทผ์„ ์Šน์ธํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ˆ˜์‹  ์ธก ์‘์šฉ์—์„œ ํŒ๋‹จํ•ด ๋‹ฌ๋ผ๋Š” ์š”์ฒญ์ด๋‹ค. ์ด ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•œ ์ชฝ์—์„  ์ ‘๊ทผ์„ ์Šน์ธํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์‘๋‹ต์„ ์ค˜์•ผ ํ•œ๋‹ค.

์ด๋ฒคํŠธ๋ฅผ ์ฝ์–ด ๋“ค์ด๋ฉด fanotify ๊ทธ๋ฃน์˜ ์ด๋ฒคํŠธ ํ์—์„œ ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ ์ œ๊ฑฐ๋œ๋‹ค. ์ฝ๊ธฐ๊ฐ€ ์ด๋ค„์ง„ ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ๋Š” fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋กœ ์“ฐ๊ธฐ๋ฅผ ํ•ด์„œ ํ—ˆ๊ฐ€ ํŒ๋‹จ์„ ๋‚ด๋ฆฌ๊ฑฐ๋‚˜ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ๋‹ซํž ๋•Œ๊นŒ์ง€ fanotify ๊ทธ๋ฃน์˜ ๋‚ด๋ถ€ ๋ชฉ๋ก์— ์œ ์ง€๋œ๋‹ค.

fanotify ์ด๋ฒคํŠธ ์ฝ๊ธฐ

fanotify_init(2)์ด ๋ฐ˜ํ™˜ํ•œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์— read(2)๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด (fanotify_init(2) ํ˜ธ์ถœ์—์„œ FAN_NONBLOCK ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด) ํŒŒ์ผ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๊ฑฐ๋‚˜ ์‹œ๊ทธ๋„์— ์˜ํ•ด ํ˜ธ์ถœ์ด ์ค‘๋‹จ(signal(7) ์ฐธ๊ณ )๋  ๋•Œ๊นŒ์ง€ ๋ธ”๋ก ํ•œ๋‹ค.

fanotify_init(2)์— FAN_REPORT_FID ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๊ฐ€ ์ด๋ฒคํŠธ๋งˆ๋‹ค ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ์— ์˜ํ–ฅ์„ ์ค€๋‹ค. read(2) ์„ฑ๊ณต ํ›„์— ์ฝ๊ธฐ ๋ฒ„ํผ์—๋Š” ๋‹ค์Œ ๊ตฌ์กฐ์ฒด๊ฐ€ ํ•œ ๊ฐœ ์ด์ƒ ๋‹ด๊ธด๋‹ค.

struct fanotify_event_metadata {
    __u32 event_len;
    __u8 vers;
    __u8 reserved;
    __u16 metadata_len;
    __aligned_u64 mask;
    __s32 fd;
    __s32 pid;
};

fanotify_init(2)์˜ ํ”Œ๋ž˜๊ทธ ์ค‘ ํ•˜๋‚˜๋กœ FAN_REPORT_FID๋ฅผ ์ค€ ๊ฒฝ์šฐ์—๋Š” ์ฝ๊ธฐ ๋ฒ„ํผ์—์„œ ๊ฐ ๋ฒ”์šฉ fanotify_event_metadata ๊ตฌ์กฐ์ฒด ๋‹ค์Œ์— ์•„๋ž˜ ์„ค๋ช…ํ•˜๋Š” ๊ตฌ์กฐ์ฒด๊ฐ€ ๋”ฐ๋ผ์˜จ๋‹ค.

struct fanotify_event_info_fid {
    struct fanotify_event_info_header hdr;
    __kernel_fsid_t fsid;
    unsigned char file_handle[0];
};

์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜๋ฉด ํฐ ๋ฒ„ํผ(๊ฐ€๋ น 4096๋ฐ”์ดํŠธ)๋ฅผ ์จ์„œ read(2) ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฑธ ๊ถŒ์žฅํ•œ๋‹ค.

read(2)์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ ๋ฒ„ํผ๋กœ ๋“ค์–ด๊ฐ„ ๋ฐ”์ดํŠธ ์ˆ˜์ด๋ฉฐ ์˜ค๋ฅ˜ ์‹œ์—๋Š” -1์ด๋‹ค. (ํ•˜์ง€๋งŒ BUGS ์ฐธ๊ณ .)

fanotify_event_metadata ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

event_len
์ด ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๊ธธ์ด์ด์ž ๋ฒ„ํผ ๋‚ด ๋‹ค์Œ ์ด๋ฒคํŠธ๋กœ์˜ ์˜คํ”„์…‹์ด๋‹ค. FAN_REPORT_FID๋ฅผ ์•ˆ ์“ฐ๋ฉด event_len์˜ ๊ฐ’์€ ํ•ญ์ƒ FAN_EVENT_METADATA_LEN์ด๋‹ค. FAN_REPORT_FID๋ฅผ ์“ฐ๋ฉด event_len์— ๊ฐ€๋ณ€ ๊ธธ์ด ํŒŒ์ผ ์‹๋ณ„์ž ํฌ๊ธฐ๊นŒ์ง€ ๋”ํ•ด์ง„๋‹ค.
vers
์ด ํ•„๋“œ๋Š” ๊ตฌ์กฐ์ฒด์˜ ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ๋‹ด๋Š”๋‹ค. ๊ทธ ๋ฒˆํ˜ธ๋ฅผ FANOTIFY_METADATA_VERSION๊ณผ ๋น„๊ตํ•ด์„œ ๋Ÿฐํƒ€์ž„์— ๋ฐ˜ํ™˜๋œ ๊ตฌ์กฐ์ฒด๊ฐ€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ •์˜๋ผ ์žˆ๋˜ ๊ตฌ์กฐ์ฒด์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•ด์•ผ ํ•œ๋‹ค. ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์‘์šฉ์—์„œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ์‚ฌ์šฉ ์‹œ๋„๋ฅผ ํฌ๊ธฐํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค.
reserved
์ด ํ•„๋“œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
metadata_len
๊ตฌ์กฐ์ฒด์˜ ๊ธธ์ด์ด๋‹ค. ์ด ํ•„๋“œ๋Š” ์ด๋ฒคํŠธ ์œ ํ˜•์— ๋”ฐ๋ฅธ ์„ ํƒ์  ํ—ค๋”๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์ž…๋œ ๊ฒƒ์ด๋‹ค. ํ˜„์žฌ ๊ตฌํ˜„์—์„œ๋Š” ๊ทธ๋Ÿฐ ์„ ํƒ์  ํ—ค๋”๊ฐ€ ์—†๋‹ค.
mask
์ด๋ฒคํŠธ๋ฅผ ๊ธฐ์ˆ ํ•˜๋Š” ๋น„ํŠธ ๋งˆ์Šคํฌ์ด๋‹ค. (์•„๋ž˜ ์ฐธ๊ณ .)
fd

์ ‘๊ทผ์ด ์ด๋ค„์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ์—ด๋ฆฐ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์ด๋‹ค. ํ ๋„˜์นจ์ด ์ผ์–ด๋‚œ ๊ฒฝ์šฐ์—๋Š” FAN_NOFD์ด๋‹ค. ์‘์šฉ์—์„œ FAN_REPORT_FID๋ฅผ ์จ์„œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™” ํ–ˆ๋‹ค๋ฉด ์ˆ˜์‹ ํ•˜๋Š” ์ด๋ฒคํŠธ๋งˆ๋‹ค ์ด ๊ฐ’์ด FAN_NOFD๋กœ ์„ค์ •๋ผ ์žˆ๊ฒŒ ๋œ๋‹ค. ์ด ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์‹œํ•˜๋Š” ํŒŒ์ผ ๋‚ด์ง€ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋‚ด์šฉ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝ๋Š” ์ชฝ ์‘์šฉ์—์„œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋‹ซ์„ ์ฑ…์ž„์ด ์žˆ๋‹ค.

fanotify_init(2) ํ˜ธ์ถœ ์‹œ์— (event_f_flags ์ธ์ž๋ฅผ ํ†ตํ•ด) ์ด ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์— ๋Œ€์‘ํ•˜๋Š” ์—ด๋ฆฐ ํŒŒ์ผ ๊ธฐ์ˆ  ํ•ญ๋ชฉ์— ์„ค์ •ํ•  ๋‹ค์–‘ํ•œ ํŒŒ์ผ ์ƒํƒœ ํ”Œ๋ž˜๊ทธ๋“ค์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”๋ถˆ์–ด ๊ทธ ์—ด๋ฆฐ ํŒŒ์ผ ๊ธฐ์ˆ  ํ•ญ๋ชฉ์—๋Š” (์ปค๋„ ๋‚ด๋ถ€์šฉ์ธ) FMODE_NONOTIFY ํŒŒ์ผ ์ƒํƒœ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์„ค์ •๋œ๋‹ค. ์ด ํ”Œ๋ž˜๊ทธ๋Š” fanotify ์ด๋ฒคํŠธ ์ƒ์„ฑ์„ ๋ง‰๋Š”๋‹ค. ๊ทธ๋ž˜์„œ fanotify ์ด๋ฒคํŠธ ์ˆ˜์‹ ์ž๊ฐ€ ์ด ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ด์šฉํ•ด ์•Œ๋ฆผ ๋Œ€์ƒ ํŒŒ์ผ ๋‚ด์ง€ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ ‘๊ทผํ•  ๋•Œ ์ด๋ฒคํŠธ๊ฐ€ ์ถ”๊ฐ€๋กœ ์ƒ๊ธฐ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

pid

fanotify_init(2)์—์„œ FAN_REPORT_FID ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์ด๋ฒคํŠธ๋ฅผ ์œ ๋ฐœํ•œ ์Šค๋ ˆ๋“œ์˜ TID๋‹ค. ์•„๋‹ˆ๋ผ๋ฉด ์ด๋ฒคํŠธ๋ฅผ ์œ ๋ฐœํ•œ ํ”„๋กœ์„ธ์Šค์˜ PID๋‹ค.

fanotify ์ด๋ฒคํŠธ ์ฒญ์ทจ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด PID๋ฅผ getpid(2)๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” PID์™€ ๋น„๊ตํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ์œ ๋ฐœํ•œ ๊ฒƒ์ด ์ž๊ธฐ ์ž์‹ ์ธ์ง€ ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์˜ ํŒŒ์ผ ์ ‘๊ทผ ๋•Œ๋ฌธ์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.

mask์˜ ๋น„ํŠธ ๋งˆ์Šคํฌ๋Š” ํ•œ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ์–ด๋–ค ์ด๋ฒคํŠธ๋“ค์ด ์ผ์–ด๋‚ฌ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ๊ฐ์‹œ ์ค‘์ธ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์ด ๋งˆ์Šคํฌ์— ์—ฌ๋Ÿฌ ๋น„ํŠธ๊ฐ€ ์„ค์ •๋  ์ˆ˜ ์žˆ๋‹ค. ํŠนํžˆ ๊ฐ™์€ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋™์ผ ํ”„๋กœ์„ธ์Šค์—์„œ ์œ ๋ž˜ํ•œ ์—ฐ์†๋œ ์ด๋ฒคํŠธ๋“ค์ด ํ•œ ์ด๋ฒคํŠธ๋กœ ํ•ฉ์ณ์งˆ ์ˆ˜๋„ ์žˆ๋‹ค. ๋‹จ, ์ ˆ๋Œ€๋กœ ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ ๋‘ ๊ฐœ๊ฐ€ ์งˆ์˜ ํ•ญ๋ชฉ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ง€์ง€๋Š” ์•Š๋Š”๋‹ค.

mask์— ๋“ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋น„ํŠธ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

FAN_ACCESS
ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ์— (BUGS ์ฐธ๊ณ ) ์ ‘๊ทผ(์ฝ๊ธฐ)์ด ์ด๋ค„์กŒ๋‹ค.
FAN_OPEN
ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์—ด๋ ธ๋‹ค.
FAN_OPEN_EXEC
ํŒŒ์ผ์ด ์‹คํ–‰ํ•˜๋ ค๋Š” ์˜๋„๋กœ ์—ด๋ ธ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ fanotify_mark(2)์˜ NOTES ์ฐธ๊ณ .
FAN_ATTRIB
ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋๋‹ค.
FAN_CREATE
๊ฐ์‹œํ•˜๋Š” ๋ถ€๋ชจ ๋‚ด์—์„œ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋๋‹ค.
FAN_DELETE
๊ฐ์‹œํ•˜๋Š” ๋ถ€๋ชจ ๋‚ด์—์„œ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์‚ญ์ œ๋๋‹ค.
FAN_DELETE_SELF
๊ฐ์‹œํ•˜๋Š” ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ž์ฒด๊ฐ€ ์‚ญ์ œ๋๋‹ค.
FAN_MOVED_FROM
๊ฐ์‹œํ•˜๋Š” ๋ถ€๋ชจ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ๋˜ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋™๋๋‹ค.
FAN_MOVED_TO
๊ฐ์‹œํ•˜๋Š” ๋ถ€๋ชจ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋™๋๋‹ค.
FAN_MOVE_SELF
๊ฐ์‹œํ•˜๋Š” ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋™๋๋‹ค.
FAN_MODIFY
ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋๋‹ค.
FAN_CLOSE_WRITE
์“ฐ๊ธฐ์šฉ(O_WRONLY๋‚˜ O_RDWR)์œผ๋กœ ์—ด๋ฆฐ ํŒŒ์ผ์ด ๋‹ซํ˜”๋‹ค.
FAN_CLOSE_NOWRITE
์ฝ๊ธฐ ์ „์šฉ(O_RDONLY)์œผ๋กœ ์—ด๋ฆฐ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ๋‹ซํ˜”๋‹ค.
FAN_Q_OVERFLOW
์ด๋ฒคํŠธ ํ๊ฐ€ ์ œํ•œ์น˜์ธ 16384๊ฐœ ํ•ญ๋ชฉ์„ ์ดˆ๊ณผํ–ˆ๋‹ค. fanotify_init(2)์„ ํ˜ธ์ถœํ•  ๋•Œ FAN_UNLIMITED_QUEUE ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•˜๋ฉด ๊ทธ ์ œํ•œ์„ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
FAN_ACCESS_PERM
์–ด๋А ์‘์šฉ์—์„œ ๊ฐ€๋ น read(2)๋‚˜ readdir(2)์„ ์ด์šฉํ•ด ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ฝ๊ณ  ์‹ถ์–ด ํ•œ๋‹ค. ๊ทธ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด ์ ‘๊ทผ์„ ์ธ๊ฐ€ํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์‘๋‹ต์„ (์•„๋ž˜ ์„ค๋ช…ํ•˜๋Š” ๋Œ€๋กœ) ์ค˜์•ผ ํ•œ๋‹ค.
FAN_OPEN_PERM
์–ด๋А ์‘์šฉ์—์„œ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์—ด๊ณ  ์‹ถ์–ด ํ•œ๋‹ค. ๊ทธ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด ์—ด๊ธฐ๋ฅผ ์ธ๊ฐ€ํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์‘๋‹ต์„ ์ค˜์•ผ ํ•œ๋‹ค.
FAN_OPEN_EXEC_PERM
์–ด๋А ์‘์šฉ์—์„œ ์‹คํ–‰์„ ์œ„ํ•ด ํŒŒ์ผ์„ ์—ด๊ณ  ์‹ถ์–ด ํ•œ๋‹ค. ๊ทธ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์˜ ์‹คํ–‰ ๋ชฉ์  ์—ด๊ธฐ๋ฅผ ์ธ๊ฐ€ํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์‘๋‹ต์„ ์ค˜์•ผ ํ•œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ fanotify_mark(2)์˜ NOTES ์ฐธ๊ณ .

๋‹ซ๊ธฐ ์ด๋ฒคํŠธ ํ™•์ธ์— ๋‹ค์Œ ๋น„ํŠธ ๋งˆ์Šคํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

FAN_CLOSE

ํŒŒ์ผ์ด ๋‹ซํ˜”๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE

์ด๋™ ์ด๋ฒคํŠธ ํ™•์ธ์— ๋‹ค์Œ ๋น„ํŠธ ๋งˆ์Šคํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

FAN_MOVE

ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋™๋๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

FAN_MOVED_FROM | FAN_MOVED_TO

fanotify_event_info_fid ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

hdr
fanotify_event_info_header ํƒ€์ž… ๊ตฌ์กฐ์ฒด๋‹ค. ์ด๋ฒคํŠธ์— ๋ง๋ถ™์€ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ๊ธฐ์ˆ ํ•˜๋Š” ์ •๋ณด๋ฅผ ๋‹ด์€ ๋ฒ”์šฉ ํ—ค๋”๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด FAN_REPORT_FID๋ฅผ ์จ์„œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ƒ์„ฑํ–ˆ์„ ๋•Œ ์ด ํ—ค๋”์˜ info_type ํ•„๋“œ๊ฐ€ FAN_EVENT_INFO_TYPE_FID๋กœ ์„ค์ •๋œ๋‹ค. ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์—์„œ๋Š” ์ด ํ•„๋“œ๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์ˆ˜์‹ ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ข…๋ฅ˜์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  fanotify_event_info_header์—๋Š” len ํ•„๋“œ๊ฐ€ ์žˆ๋‹ค. ํ˜„์žฌ ๊ตฌํ˜„์—์„œ len์˜ ๊ฐ’์€ ํ•ญ์ƒ (event_len - FAN_EVENT_METADATA_LEN)์ด๋‹ค.
fsid
์ด๋ฒคํŠธ ์—ฐ๊ด€ ๊ฐ์ฒด๋ฅผ ๋‹ด์€ ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๊ณ ์œ  ์‹๋ณ„์ž๋‹ค. __kernel_fsid_t ํƒ€์ž…์˜ ๊ตฌ์กฐ์ฒด์ด๊ณ  statfs(2) ํ˜ธ์ถœ ์‹œ์˜ f_fsid์™€ ๊ฐ™์€ ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋‹ค.
file_handle
file_handle ํƒ€์ž…์˜ ๊ฐ€๋ณ€ ๊ธธ์ด ๊ตฌ์กฐ์ฒด๋‹ค. ํŒŒ์ผ ์‹œ์Šคํ…œ ์ƒ์˜ ํŠน์ • ๊ฐ์ฒด์— ๋Œ€์‘ํ•˜๋Š” ๋ถˆํˆฌ๋ช…ํ•œ ํ•ธ๋“ค์ด๋ฉฐ name_to_handle_at(2)์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ํŒŒ์ผ ์‹œ์Šคํ…œ ์ƒ์˜ ํŒŒ์ผ์„ ์œ ์ผํ•˜๊ฒŒ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ open_by_handle_at(2)์— ์ธ์ž๋กœ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ FAN_CREATE, FAN_DELETE, FAN_MOVE ๊ฐ™์€ ๋””๋ ‰ํ„ฐ๋ฆฌ ํ•ญ๋ชฉ ์ด๋ฒคํŠธ์—์„œ file_handle์€ ์ƒ์„ฑ/์‚ญ์ œ/์ด๋™๋œ ์ž์‹ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋ณ€๊ฒฝ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ž์‹ ๊ฐ์ฒด๋ฅผ ๊ฐ์‹œ ์ค‘์ด๋ผ๋ฉด FAN_ATTRIB, FAN_DELETE_SELF, FAN_MOVE_SELF ์ด๋ฒคํŠธ๊ฐ€ ์ž์‹ ๊ฐ์ฒด์— ๋Œ€ํ•œ file_handle ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ด ์ค€๋‹ค.

fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์— ๋Œ€ํ•ด read(2)๊ฐ€ ๋ฐ˜ํ™˜ํ•œ fanotify ์ด๋ฒคํŠธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋“ค์ด ๋‹ด๊ธด ๋ฒ„ํผ๋ฅผ ์ˆœํšŒํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์Œ ๋งคํฌ๋กœ๋“ค์ด ์žˆ๋‹ค.

FAN_EVENT_OK(meta, len)
์ด ๋งคํฌ๋กœ๋Š” ๋ฒ„ํผ์˜ ๋‚จ์€ ๊ธธ์ด len์„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์˜ ๊ธธ์ด ๋ฐ meta๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์˜ event_len ํ•„๋“œ์™€ ๋น„๊ตํ•ด ๋ณธ๋‹ค.
FAN_EVENT_NEXT(meta, len)
์ด ๋งคํฌ๋กœ๋Š” meta๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์˜ event_len ํ•„๋“œ์— ์žˆ๋Š” ๊ธธ์ด ๊ฐ’์„ ์ด์šฉํ•ด meta ๋‹ค์Œ์— ์˜ค๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์˜ ์ฃผ์†Œ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. len์€ ํ˜„์žฌ ๋ฒ„ํผ์— ๋‚จ์•„ ์žˆ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ฐ”์ดํŠธ ์ˆ˜์ด๋‹ค. meta ๋‹ค์Œ์— ์žˆ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ๊ฑด๋„ˆ๋›ด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด์˜ ๋ฐ”์ดํŠธ ์ˆ˜๋งŒํผ len์„ ์ค„์ธ๋‹ค. (์ฆ‰ len์—์„œ meta->event_len์„ ๋บ€๋‹ค.)

๋˜ํ•œ ๋‹ค์Œ ๋งคํฌ๋กœ๊ฐ€ ์žˆ๋‹ค.

FAN_EVENT_METADATA_LEN
์ด ๋งคํฌ๋กœ๋Š” fanotify_event_metadata ๊ตฌ์กฐ์ฒด์˜ (๋ฐ”์ดํŠธ ๋‹จ์œ„) ํฌ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋ฒคํŠธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ ์ตœ์†Œ ํฌ๊ธฐ(๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ๋Š” ์œ ์ผํ•œ ํฌ๊ธฐ)์ด๋‹ค.

fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—์„œ ์ด๋ฒคํŠธ ๊ฐ์‹œํ•˜๊ธฐ

fanotify ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ epoll(7), poll(2), select(2)์— ์ฃผ๋ฉด ์ฝ๊ธฐ ๊ฐ€๋Šฅ์œผ๋กœ ํ‘œ์‹œ๋œ๋‹ค.

๊ถŒํ•œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌํ•˜๊ธฐ

ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ์˜ ๊ฒฝ์šฐ ์‘์šฉ์—์„œ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋กœ ๋‹ค์Œ ํ˜•ํƒœ์˜ ๊ตฌ์กฐ์ฒด๋ฅผ write(2) ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

struct fanotify_response {
    __s32 fd;
    __u32 response;
};

์ด ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

fd
fanotify_event_metadata ๊ตฌ์กฐ์ฒด์—์„œ ์˜จ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์ด๋‹ค.
response
์ด ํ•„๋“œ๋Š” ๋™์ž‘์„ ์ธ๊ฐ€ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ํŒŒ์ผ ๋™์ž‘์„ ํ—ˆ์šฉํ•˜๋Š” FAN_ALLOW๊ฑฐ๋‚˜ ํŒŒ์ผ ๋™์ž‘์„ ๊ฑฐ๋ถ€ํ•˜๋Š” FAN_DENY์—ฌ์•ผ ํ•œ๋‹ค.

์ ‘๊ทผ์„ ๊ฑฐ๋ถ€ํ•˜๋ฉด ์š”์ฒญ ์ธก ์‘์šฉ ํ˜ธ์ถœ์ด EPERM ์˜ค๋ฅ˜๋ฅผ ๋ฐ›๊ฒŒ ๋œ๋‹ค.

fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋‹ซ๊ธฐ

fanotify ์•Œ๋ฆผ ๊ทธ๋ฃน์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ชจ๋“  ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ๋‹ซํž ๋•Œ fanotify ๊ทธ๋ฃน์ด ํ•ด์ œ๋˜๊ณ  ๊ทธ ์ž์›์„ ์ปค๋„์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. close(2) ์‹œ์— ๋ฏธ์ฒ˜๋ฆฌ ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ๋Š” ํ—ˆ์šฉ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

/proc/[pid]/fdinfo

/proc/[pid]/fdinfo/[fd] ํŒŒ์ผ์ด ํ”„๋กœ์„ธ์Šค pid์˜ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd์— ๋Œ€ํ•œ fanotify ํ‘œ์‹œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ proc(5) ์ฐธ๊ณ .

ERRORS

fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—์„œ ์ฝ๊ธฐ๋ฅผ ํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ read(2) ์˜ค๋ฅ˜์— ๋”ํ•ด์„œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

EINVAL
๋ฒ„ํผ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๋‹ด๊ธฐ์— ๋„ˆ๋ฌด ์ž‘๋‹ค.
EMFILE
์—ด๋ฆฐ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐœ์ˆ˜์— ๋Œ€ํ•œ ํ”„๋กœ์„ธ์Šค๋ณ„ ์ œํ•œ์— ๋„๋‹ฌํ–ˆ๋‹ค. getrlimit(2)์˜ RLIMIT_NOFILE ์„ค๋ช… ์ฐธ๊ณ .
ENFILE
์—ด๋ฆฐ ํŒŒ์ผ ์ด๊ฐœ์ˆ˜์— ๋Œ€ํ•œ ์‹œ์Šคํ…œ ์ „์—ญ ์ œํ•œ์— ๋„๋‹ฌํ–ˆ๋‹ค. proc(5)์˜ /proc/sys/fs/file-max ์ฐธ๊ณ .
ETXTBSY
fanotify_init(2) ํ˜ธ์ถœ ์‹œ event_f_flags ์ธ์ž์— O_RDWR๋‚˜ O_WRONLY๋ฅผ ์ง€์ •ํ–ˆ์œผ๋ฉฐ ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ๊ฐ์‹œ ๋Œ€์ƒ ํŒŒ์ผ์— ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ read(2)๊ฐ€ ์ด ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์— ์“ฐ๊ธฐ๋ฅผ ํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ write(2) ์˜ค๋ฅ˜์— ๋”ํ•ด์„œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

EINVAL
์ปค๋„ ๊ตฌ์„ฑ์—์„œ fanotify ์ ‘๊ทผ ํ—ˆ๊ฐ€๊ฐ€ ์ผœ์ ธ ์žˆ์ง€ ์•Š๊ฑฐ๋‚˜ ์‘๋‹ต ๊ตฌ์กฐ์ฒด์˜ response ๊ฐ’์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค.
ENOENT
์‘๋‹ต ๊ตฌ์กฐ์ฒด์˜ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค. ํ—ˆ๊ฐ€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์ด๋ฏธ ์จ ์ค€ ๊ฒฝ์šฐ์— ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

VERSIONS

๋ฆฌ๋ˆ…์Šค ์ปค๋„ ๋ฒ„์ „ 2.6.36์—์„œ fanotify API๊ฐ€ ๋„์ž…๋˜์—ˆ๊ณ  ๋ฒ„์ „ 2.6.37์—์„œ ํ™œ์„ฑํ™”๋˜์—ˆ๋‹ค. ๋ฒ„์ „ 3.8์—์„œ fdinfo ์ง€์›์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

CONFORMING TO

fanotify API๋Š” ๋ฆฌ๋ˆ…์Šค ์ „์šฉ์ด๋‹ค.

NOTES

fanotify API๋Š” CONFIG_FANOTIFY ๊ตฌ์„ฑ ์˜ต์…˜์„ ์ผœ์„œ ์ปค๋„์„ ๋นŒ๋“œ ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋”๋ถˆ์–ด fanotify ๊ถŒํ•œ ์ฒ˜๋ฆฌ๋Š” CONFIG_FANOTIFY_ACCESS_PERMISSIONS ๊ตฌ์„ฑ ์˜ต์…˜์ด ์ผœ์ง„ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ•œ๊ณ„๊ณผ ์ฃผ์˜์ 

fanotify๋Š” ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ํŒŒ์ผ ์‹œ์Šคํ…œ API๋ฅผ ํ†ตํ•ด ์œ ๋ฐœํ•œ ์ด๋ฒคํŠธ๋งŒ์„ ๋ณด๊ณ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋„คํŠธ์›Œํฌ ํŒŒ์ผ ์‹œ์Šคํ…œ ์ƒ์—์„œ ์ผ์–ด๋‚˜๋Š” ์›๊ฒฉ ์ด๋ฒคํŠธ๋Š” ์žก์ง€ ๋ชปํ•œ๋‹ค.

fanotify API๋Š” mmap(2), msync(2), munmap(2) ๋•Œ๋ฌธ์— ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ ์ ‘๊ทผ ๋ฐ ๋ณ€๊ฒฝ์— ๋Œ€ํ•ด ์•Œ๋ ค ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ ์ž์ฒด๋ฅผ ์—ด๊ณ  ์ฝ๊ณ  ๋‹ซ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ƒ๊ธด๋‹ค. ํ‘œ์‹œํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ์ž์‹์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•ด๋„ ๊ฐ์‹œ ๋Œ€์ƒ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ž์ฒด์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.

fanotify์—์„œ์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฐ์‹œ๋Š” ์žฌ๊ท€์ ์ด์ง€ ์•Š๋‹ค. ๋””๋ ‰ํ„ฐ๋ฆฌ ์•„๋ž˜ ์„œ๋ธŒ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๊ฐ์‹œํ•˜๋ ค๋ฉด ๊ฐ์‹œ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. (ํ•˜์ง€๋งŒ fanotify API์—์„œ๋Š” ํ‘œ์‹œํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์•„๋ž˜์— ์„œ๋ธŒ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ƒ๊ธด ๊ฑธ ํƒ์ง€ํ•  ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์žฌ๊ท€์ ์ธ ๊ฐ์‹œ๊ฐ€ ์–ด๋ ต๋‹ค.) ๋งˆ์šดํŠธ๋ฅผ ๊ฐ์‹œํ•˜๋ฉด ๋””๋ ‰ํ„ฐ๋ฆฌ ํŠธ๋ฆฌ ์ „์ฒด๋ฅผ ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ๊ฐ์‹œํ•˜๋ฉด ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  ๋งˆ์šดํŠธ ์ธ์Šคํ„ด์Šค์—์„œ ์ผ์–ด๋‚œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฒคํŠธ ํ๊ฐ€ ๋„˜์น  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ด๋ฒคํŠธ๊ฐ€ ์œ ์‹ค๋œ๋‹ค.

BUGS

๋ฆฌ๋ˆ…์Šค 3.19 ์ „์—์„œ fallocate(2)๊ฐ€ fanotify ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•˜๋‹ค. ๋ฆฌ๋ˆ…์Šค 3.19๋ถ€ํ„ฐ fallocate(2) ํ˜ธ์ถœ์ด FAN_MODIFY ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๋ฆฌ๋ˆ…์Šค 3.17 ํ˜„์žฌ ๋‹ค์Œ ๋ฒ„๊ทธ๋“ค์ด ์กด์žฌํ•œ๋‹ค.

  • ๋ฆฌ๋ˆ…์Šค์—์„œ ์–ด๋–ค ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๊ฒฝ๋กœ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ผ ์‹œ์Šคํ…œ ์ผ๋ถ€๋ฅผ mount(8)์˜ --bind ์˜ต์…˜์œผ๋กœ ๋‹ค์‹œ ๋งˆ์šดํŠธ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋งˆ์šดํŠธ์— ํ‘œ์‹œ๋ฅผ ํ•œ ๋ฆฌ์Šค๋„ˆ๋Š” ํ•ด๋‹น ๋งˆ์šดํŠธ๋ฅผ ์“ฐ๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ์œ ๋ฐœ๋œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ๋งŒ ์•Œ๋ฆผ์„ ๋ฐ›๊ฒŒ ๋œ๋‹ค. ๋‹ค๋ฅธ ์ด๋ฒคํŠธ๋Š” ์•Œ๋ฆผ์ด ์ด๋ค„์ง€์ง€ ์•Š๋Š”๋‹ค.

  • ์ด๋ฒคํŠธ๊ฐ€ ์ƒ๊ธธ ๋•Œ ํŒŒ์ผ์— ๋Œ€ํ•œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด ์ฃผ๊ธฐ ์ „์— ์ˆ˜์‹  ์ธก ํ”„๋กœ์„ธ์Šค์˜ ์‚ฌ์šฉ์ž ID๊ฐ€ ํŒŒ์ผ์— ์ฝ๊ธฐ ๋‚ด์ง€ ์“ฐ๊ธฐ ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋น„ํŠน๊ถŒ ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•œ ํ”„๋กœ๊ทธ๋žจ์— CAP_SYS_ADMIN ์—ญ๋Šฅ์ด ์„ค์ •๋ผ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ณด์•ˆ ์œ„ํ—˜์ด ๋œ๋‹ค.

  • read(2) ํ˜ธ์ถœ ๋‚ด์—์„œ fanotify ํ์˜ ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ๋ฅผ ๊บผ๋‚ด ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์— ๋ฐ˜ํ™˜ ๊ฐ’์€ ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์ „๊นŒ์ง€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๋ฒ„ํผ๋กœ ์„ฑ๊ณต์ ์œผ๋กœ ๋ณต์‚ฌํ•œ ์ด๋ฒคํŠธ๋“ค์˜ ์ด ๊ธธ์ด๊ฐ€ ๋œ๋‹ค. ์ฆ‰ ๋ฐ˜ํ™˜ ๊ฐ’์ด -1์ด ์•„๋‹ˆ๊ณ  errno๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ฝ๋Š” ์ชฝ ์‘์šฉ์—์„œ ์˜ค๋ฅ˜๋ฅผ ํƒ์ง€ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.

EXAMPLE

์•„๋ž˜์˜ ๋‘ ์˜ˆ์‹œ ํ”„๋กœ๊ทธ๋žจ์ด fanotify API ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค€๋‹ค.

์˜ˆ์‹œ ํ”„๋กœ๊ทธ๋žจ: fanotify_example.c

์ฒซ ๋ฒˆ์งธ ํ”„๋กœ๊ทธ๋žจ์€ ์ด๋ฒคํŠธ ๊ฐ์ฒด ์ •๋ณด๊ฐ€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๋„๋ก ํ•ด์„œ fanotify๋ฅผ ์“ฐ๋Š” ์˜ˆ์‹œ์ด๋‹ค. ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ช…๋ นํ–‰ ์ธ์ž๋กœ ๋ฐ›์€ ๋งˆ์šดํŠธ ์ง€์ ์— ํ‘œ์‹œ๋ฅผ ํ•˜๊ณ ์„œ FAN_OPEN_PERM ๋ฐ FAN_CLOSE_WRITE ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. ๊ถŒํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด FAN_ALLOW ์‘๋‹ต์„ ์ค€๋‹ค.

๋‹ค์Œ ์…ธ ์„ธ์…˜์€ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์˜ˆ๋ฅผ ๋ณด์—ฌ ์ค€๋‹ค. ์ด ์„ธ์…˜๊ณผ ๋”๋ถˆ์–ด ํŒŒ์ผ /home/user/temp/notes ํŽธ์ง‘์ด ์ด๋ค„์กŒ๋‹ค. ํŒŒ์ผ์„ ์—ด๊ธฐ ์ „์—๋Š” FAN_OPEN_PERM ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ํŒŒ์ผ์„ ๋‹ซ์€ ํ›„์—๋Š” FAN_CLOSE_WRITE ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์—”ํ„ฐ ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์ด ๋๋‚œ๋‹ค.

# ./fanotify_example /home
Press enter key to terminate.
Listening for events.
FAN_OPEN_PERM: File /home/user/temp/notes
FAN_CLOSE_WRITE: File /home/user/temp/notes

Listening for events stopped.

ํ”„๋กœ๊ทธ๋žจ ์†Œ์Šค: fanotify_example.c

#define _GNU_SOURCE     /* O_LARGEFILE ์ •์˜๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fanotify.h>
#include <unistd.h>

/* ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ 'fd'์—์„œ ๊ฐ€์šฉ fanotify ์ด๋ฒคํŠธ๋ฅผ ๋ชจ๋‘ ์ฝ์–ด ๋“ค์ด๊ธฐ */

static void
handle_events(int fd)
{
    const struct fanotify_event_metadata *metadata;
    struct fanotify_event_metadata buf[200];
    ssize_t len;
    char path[PATH_MAX];
    ssize_t path_len;
    char procfd_path[PATH_MAX];
    struct fanotify_response response;

    /* fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋™์•ˆ ๋ฐ˜๋ณต */

    for (;;) {

        /* ์ด๋ฒคํŠธ ์ฝ๊ธฐ */

        len = read(fd, (void *) &buf, sizeof(buf));
        if (len == -1 && errno != EAGAIN) {
            perror("read");
            exit(EXIT_FAILURE);
        }

        /* ๊ฐ€์šฉ ๋ฐ์ดํ„ฐ ๋์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ํ™•์ธ */

        if (len <= 0)
            break;

        /* ๋ฒ„ํผ์˜ ์ฒซ ๋ฒˆ์งธ ์ด๋ฒคํŠธ ๊ฐ€๋ฆฌํ‚ค๊ธฐ */

        metadata = buf;

        /* ๋ฒ„ํผ ๋‚ด ๋ชจ๋“  ์ด๋ฒคํŠธ ๋Œ๊ธฐ */

        while (FAN_EVENT_OK(metadata, len)) {

            /* ๋Ÿฐํƒ€์ž„ ๊ตฌ์กฐ์ฒด์™€ ์ปดํŒŒ์ผ ํƒ€์ž„ ๊ตฌ์กฐ์ฒด๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ */

            if (metadata->vers != FANOTIFY_METADATA_VERSION) {
                fprintf(stderr,
                        "Mismatch of fanotify metadata version.\n");
                exit(EXIT_FAILURE);
            }

            /* metadata->fd๋Š” ํ ๋„˜์นจ์„ ๋‚˜ํƒ€๋‚ด๋Š” FAN_NOFD๊ฑฐ๋‚˜
               ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(์Œ์ˆ˜ ์•„๋‹Œ ์ •์ˆ˜)์ž„. ์—ฌ๊ธฐ์„œ ํ ๋„˜์นจ์€
               ๊ทธ๋ƒฅ ๋ฌด์‹œํ•จ. */

            if (metadata->fd >= 0) {

                /* ์—ด๊ธฐ ๊ถŒํ•œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ */

                if (metadata->mask & FAN_OPEN_PERM) {
                    printf("FAN_OPEN_PERM: ");

                    /* ํŒŒ์ผ ์—ด๊ธฐ ํ—ˆ์šฉ */

                    response.fd = metadata->fd;
                    response.response = FAN_ALLOW;
                    write(fd, &response,
                          sizeof(struct fanotify_response));
                }

                /* ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ํŒŒ์ผ ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ */

                if (metadata->mask & FAN_CLOSE_WRITE)
                    printf("FAN_CLOSE_WRITE: ");

                /* ์ ‘๊ทผ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ช… ์–ป์–ด์„œ ์ฐ๊ธฐ */

                snprintf(procfd_path, sizeof(procfd_path),
                         "/proc/self/fd/%d", metadata->fd);
                path_len = readlink(procfd_path, path,
                                    sizeof(path) - 1);
                if (path_len == -1) {
                    perror("readlink");
                    exit(EXIT_FAILURE);
                }

                path[path_len] = '\0';
                printf("File %s\n", path);

                /* ์ด๋ฒคํŠธ์˜ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋‹ซ๊ธฐ */

                close(metadata->fd);
            }

            /* ๋‹ค์Œ ์ด๋ฒคํŠธ๋กœ */

            metadata = FAN_EVENT_NEXT(metadata, len);
        }
    }
}

int main(int argc, char *argv[])
{
    char buf;
    int fd, poll_num;
    nfds_t nfds;
    struct pollfd fds[2];

    /* ๋งˆ์šดํŠธ ์ง€์  ์ฃผ์–ด์กŒ๋Š”์ง€ ํ™•์ธ */

    if (argc != 2) {
        fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    printf("Press enter key to terminate.\n");

    /* fanotify API ์ ‘๊ทผ์„ ์œ„ํ•œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋งŒ๋“ค๊ธฐ */

    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
                       O_RDONLY | O_LARGEFILE);
    if (fd == -1) {
        perror("fanotify_init");
        exit(EXIT_FAILURE);
    }

    /* ๋งˆ์šดํŠธ์— ๋‹ค์Œ ํ‘œ์‹œ:
       - ํŒŒ์ผ ์—ด๊ธฐ ์ „ ๊ถŒํ•œ ์ด๋ฒคํŠธ
       - ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋‹ซ์€ ํ›„
         ์•Œ๋ฆผ ์ด๋ฒคํŠธ */

    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
                      argv[1]) == -1) {
        perror("fanotify_mark");
        exit(EXIT_FAILURE);
    }

    /* ํด๋ง ์ค€๋น„ */

    nfds = 2;

    /* ์ฝ˜์†” ์ž…๋ ฅ */

    fds[0].fd = STDIN_FILENO;
    fds[0].events = POLLIN;

    /* fanotify ์ž…๋ ฅ */

    fds[1].fd = fd;
    fds[1].events = POLLIN;

    /* ์ด๋ฒคํŠธ ์ž…๋ ฅ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฃจํ”„ */

    printf("Listening for events.\n");

    while (1) {
        poll_num = poll(fds, nfds, -1);
        if (poll_num == -1) {
            if (errno == EINTR)     /* ์‹œ๊ทธ๋„์— ์˜ํ•ด ์ค‘๋‹จ */
                continue;           /* poll() ์žฌ์‹œ์ž‘ */

            perror("poll");         /* ์˜ˆ์ƒ ๋ชปํ•œ ์˜ค๋ฅ˜ */
            exit(EXIT_FAILURE);
        }

        if (poll_num > 0) {
            if (fds[0].revents & POLLIN) {

                /* ์ฝ˜์†” ์ž…๋ ฅ ์žˆ์Œ. stdin ๋น„์šฐ๊ณ  ๋๋‚ด๊ธฐ */

                while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\0')
                    continue;
                break;
            }

            if (fds[1].revents & POLLIN) {

                /* inotify ์ด๋ฒคํŠธ ์žˆ์Œ */

                handle_events(fd);
            }
        }
    }

    printf("Listening for events stopped.\n");
    exit(EXIT_SUCCESS);
}

์˜ˆ์‹œ ํ”„๋กœ๊ทธ๋žจ: fanotify_fid.c

๋‘ ๋ฒˆ์งธ ํ”„๋กœ๊ทธ๋žจ์€ FAN_REPORT_FID๋ฅผ ์ผœ์„œ fanotify๋ฅผ ์“ฐ๋Š” ์˜ˆ์‹œ์ด๋‹ค. ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ช…๋ นํ–‰ ์ธ์ž๋กœ ๋ฐ›์€ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ํ‘œ์‹œ๋ฅผ ํ•˜๊ณ ์„œ FAN_CREATE ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. ์ด๋ฒคํŠธ ๋งˆ์Šคํฌ๋ฅผ ๋ณด๋ฉด ์–ด๋–ค ์ข…๋ฅ˜์˜ (ํŒŒ์ผ ๋˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ) ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋ฒ„ํผ์—์„œ ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ์ฝ์–ด์„œ ์ฐจ๋ก€๋กœ ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ํ”„๋กœ๊ทธ๋žจ์„ ๊ทธ๋Œ€๋กœ ์ข…๋ฃŒํ•œ๋‹ค.

๋‹ค์Œ ๋‘ ๋ฒˆ์˜ ์…ธ ์„ธ์…˜์€ ๊ฐ์‹œ ๋Œ€์ƒ ๊ฐ์ฒด์— ๋‹ค๋ฅธ ๋™์ž‘์„ ํ•˜๋ฉด์„œ ํ”„๋กœ๊ทธ๋žจ์„ ํ˜ธ์ถœํ•œ ๊ฒƒ์ด๋‹ค.

์ฒซ ๋ฒˆ์งธ ์„ธ์…˜์—์„  /home/user์— ํ‘œ์‹œ๊ฐ€ ์ด๋ค„์ง€๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ๋‹ค์Œ์— ์ •๊ทœ ํŒŒ์ผ /home/user/testfile.txt ์ƒ์„ฑ์ด ์ด๋ค„์ง„๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํŒŒ์ผ์˜ ๋ถ€๋ชจ์ธ ๊ฐ์‹œ ๋Œ€์ƒ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฐ์ฒด์— ๋Œ€ํ•ด FAN_CREATE ์ด๋ฒคํŠธ๊ฐ€ ์ƒ๊ฒจ์„œ ๋ณด๊ณ ๋œ๋‹ค. ๊ทธ๋Ÿฌ๊ณ ์„œ ๋ฒ„ํผ์— ์žกํžŒ ์ด๋ฒคํŠธ๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋‚˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์ด ๋๋‚œ๋‹ค.

# ./fanotify_fid /home/user
Listening for events.
FAN_CREATE (file created): Directory /home/user has been modified.
All events processed successfully. Program exiting.

$ touch /home/user/testing              # ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ

๋‘ ๋ฒˆ์งธ ์„ธ์…˜์—์„  /home/user์— ํ‘œ์‹œ๊ฐ€ ์ด๋ค„์ง€๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ๋‹ค์Œ์— ๋””๋ ‰ํ„ฐ๋ฆฌ /home/user/testdir ์ƒ์„ฑ์ด ์ด๋ค„์ง„๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ”„๋กœ๊ทธ๋žจ์—์„œ FAN_CREATE ๋ฐ FAN_ONDIR ์ด๋ฒคํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

# ./fanotify_fid /home/user
Listening for events.
FAN_CREATE | FAN_ONDIR (subdirectory created):
        Directory /home/user has been modified.
All events processed successfully. Program exiting.

$ mkdir -p /home/user/testing          # ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ

ํ”„๋กœ๊ทธ๋žจ ์†Œ์Šค: fanotify_fid.c

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fanotify.h>
#include <unistd.h>

#define BUF_SIZE 256

int
main(int argc, char **argv)
{
    int fd, ret, event_fd;
    ssize_t len, path_len;
    char path[PATH_MAX];
    char procfd_path[PATH_MAX];
    char events_buf[BUF_SIZE];
    struct file_handle *file_handle;
    struct fanotify_event_metadata *metadata;
    struct fanotify_event_info_fid *fid;

    if (argc != 2) {
        fprintf(stderr, "Invalid number of command line arguments.\0);
        exit(EXIT_FAILURE);
    }

    /* FAN_REPORT_FID ํ”Œ๋ž˜๊ทธ๋กœ fanotify ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ
       ํ”„๋กœ๊ทธ๋žจ์ด fid ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๊ฒŒ ํ•œ๋‹ค. */

    fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
    if (fd == -1) {
        perror("fanotify_init");
        exit(EXIT_FAILURE);
    }

    /* argv[1]๋กœ ๋ฐ›์€ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ฐ์ฒด์— ํ‘œ์‹œ๋ฅผ ํ•œ๋‹ค. */

    ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
                        FAN_CREATE | FAN_ONDIR,
                        AT_FDCWD, argv[1]);
    if (ret == -1) {
        perror("fanotify_mark");
        exit(EXIT_FAILURE);
    }

    printf("Listening for events.\0);

    /* ์ด๋ฒคํŠธ ํ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฝ์–ด์„œ ๋ฒ„ํผ๋กœ */

    len = read(fd, (void *) &events_buf, sizeof(events_buf));
    if (len == -1 && errno != EAGAIN) {
        perror("read");
        exit(EXIT_FAILURE);
    }

    /* ๋ฒ„ํผ์˜ ๋ชจ๋“  ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ */

    for (metadata = (struct fanotify_event_metadata *) events_buf;
            FAN_EVENT_OK(metadata, len);
            metadata = FAN_EVENT_NEXT(metadata, len)) {
        fid = (struct fanotify_event_info_fid *) (metadata + 1);
        file_handle = (struct file_handle *) fid->handle;

        /* ์ด๋ฒคํŠธ ์ •๋ณด์˜ ํƒ€์ž…์ด ๋งž๋Š”์ง€ ํ™•์ธ */

        if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
            fprintf(stderr, "Received unexpected event info type.\0);
            exit(EXIT_FAILURE);
        }

        if (metadata->mask == FAN_CREATE)
            printf("FAN_CREATE (file created):");

        if (metadata->mask == FAN_CREATE | FAN_ONDIR)
            printf("FAN_CREATE | FAN_ONDIR (subdirectory created):");

        /* FAN_REPORT_FID๊ฐ€ ์ผœ์ ธ ์žˆ์œผ๋ฉด metadata->fd๊ฐ€ FAN_NOFD๋กœ
           ์„ค์ •๋ผ ์žˆ๋‹ค. ์ด๋ฒคํŠธ ๊ด€๋ จ ํŒŒ์ผ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ
           ์–ป์œผ๋ ค๋ฉด fanotify_event_info_fid ์•ˆ์— ์žˆ๋Š” struct
           file_handle์„ open_by_handle_at(2) ์‹œ์Šคํ…œ ํ˜ธ์ถœ๊ณผ ํ•จ๊ป˜
           ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์‹œ์Šคํ…œ ํ˜ธ์ถœ ์ „์— ๊ทธ ๊ฐ์ฒด๊ฐ€ ์‚ญ์ œ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ
           ๋Œ€๋น„ํ•ด์„œ ESTALE ๊ฒ€์‚ฌ๋ฅผ ํ•œ๋‹ค. */

        event_fd = open_by_handle_at(AT_FDCWD, file_handle, O_RDONLY);
        if (ret == -1) {
            if (errno == ESTALE) {
                printf("File handle is no longer valid. "
                        "File has been deleted\0);
                continue;
            } else {
                perror("open_by_handle_at");
                exit(EXIT_FAILURE);
         }
        }

        snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
                event_fd);

        /* ๋ณ€๊ฒฝ๋œ dentry์˜ ๊ฒฝ๋กœ ๊ฐ€์ ธ์™€์„œ ์ฐ๊ธฐ */

        path_len = readlink(procfd_path, path, sizeof(path) - 1);
        if (path_len == -1) {
            perror("readlink");
            exit(EXIT_FAILURE);
        }

        path[path_len] = '\ ';
        printf("\tDirectory '%s' has been modified.\0, path);

        /* ์ด ์ด๋ฒคํŠธ์˜ ์—ฐ๊ด€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋‹ซ๊ธฐ */

        close(event_fd);
    }

    printf("All events processed successfully. Program exiting.\0);
    exit(EXIT_SUCCESS);
}

SEE ALSO

fanotify_init(2), fanotify_mark(2), inotify(7)


2019-08-02

โš ๏ธ **GitHub.com Fallback** โš ๏ธ