linux系统下inotify源码分析
Posted 小道安全
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux系统下inotify源码分析相关的知识,希望对你有一定的参考价值。
文章目录
1.inotify调用
inotify_init:用于创建一个 inotify 实例的系统调用,并返回一个指向该实例的文件描述符。
inotify_add_watch:增加对文件或者目录的监控,并指定需要监控哪些事件。
read:读取包含一个或者多个事件信息的缓存。
inotify_rm_watch:从监控列表中移出监控项目。
2.在系统中的实现。
2.1 inotify头文件定义
2.1.1系统中的定位位置
bionic/tools/versioner/dependencies/common/kernel_uapi/linux/inotify.h
2.1.2定义的实现
#ifndef _UAPI_LINUX_INOTIFY_H
#define _UAPI_LINUX_INOTIFY_H
#include <linux/fcntl.h>
#include <linux/types.h>
struct inotify_event {
__s32 wd;
__u32 mask;
__u32 cookie;
__u32 len;
char name[0];
};
#define IN_ACCESS 0x00000001
#define IN_MODIFY 0x00000002
#define IN_ATTRIB 0x00000004
#define IN_CLOSE_WRITE 0x00000008
#define IN_CLOSE_NOWRITE 0x00000010
#define IN_OPEN 0x00000020
#define IN_MOVED_FROM 0x00000040
#define IN_MOVED_TO 0x00000080
#define IN_CREATE 0x00000100
#define IN_DELETE 0x00000200
#define IN_DELETE_SELF 0x00000400
#define IN_MOVE_SELF 0x00000800
#define IN_UNMOUNT 0x00002000
#define IN_Q_OVERFLOW 0x00004000
#define IN_IGNORED 0x00008000
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO)
#define IN_ONLYDIR 0x01000000
#define IN_DONT_FOLLOW 0x02000000
#define IN_EXCL_UNLINK 0x04000000
#define IN_MASK_ADD 0x20000000
#define IN_ISDIR 0x40000000
#define IN_ONESHOT 0x80000000
#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_DELETE | IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF)
#define IN_CLOEXEC O_CLOEXEC
#define IN_NONBLOCK O_NONBLOCK
#endif
2.2 inotify_add_watch实现
2.2.1inotify_add_watch.S在系统的位置
bionic/libc/arch-x86/syscalls/inotify_add_watch.S
2.2.2 inotify_add_watch.S具体代码实现
ENTRY(inotify_add_watch)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
pushl %ecx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ecx, 0
pushl %edx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset edx, 0
call __kernel_syscall
pushl %eax
.cfi_adjust_cfa_offset 4
.cfi_rel_offset eax, 0
mov 20(%esp), %ebx
mov 24(%esp), %ecx
mov 28(%esp), %edx
movl $__NR_inotify_add_watch, %eax
call *(%esp)
addl $4, %esp
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno_internal
addl $4, %esp
1:
popl %edx
popl %ecx
popl %ebx
ret
END(inotify_add_watch)
2.3 inotify_init实现
2.3.1在系统中inotify_init的位置
bionic/libc/arch-x86/syscalls/inotify_init1.S
2.3.2具体的代码实现
ENTRY(inotify_init1)
mov ip, r7
.cfi_register r7, ip
ldr r7, =__NR_inotify_init1
swi #0
mov r7, ip
.cfi_restore r7
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(inotify_init1)
2.4inotify_rm_watch 实现
2.4.1系统中定位的位置
bionic/libc/arch-x86/syscalls/inotify_rm_watch.S
2.4.2具体的实现
ENTRY(inotify_rm_watch)
movl $__NR_inotify_rm_watch, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
negl %eax
movl %eax, %edi
call __set_errno_internal
1:
ret
END(inotify_rm_watch)
2.5 inotify调用
2.5.1在系统中的位置
external/strace/tests/inotify.c
2.5.2调用的实现
```cpp
int main(void)
{
static const struct {
const char *path;
const char *str;
} bogus_path_str = {
ARG_STR("/abc\\1/def\\2/ghi\\3/jkl\\4/mno\\5/pqr\\6/stu\\7/vwx\\10") };
static const kernel_ulong_t bogus_fd =
(kernel_ulong_t) 0xfffffeedfffffaceULL;
static const kernel_ulong_t bogus_mask =
(kernel_ulong_t) 0xffffda7affffdeadULL;
static const char *bogus_mask_str = "IN_ACCESS|IN_ATTRIB|"
"IN_CLOSE_WRITE|IN_OPEN|IN_MOVED_TO|IN_DELETE|IN_DELETE_SELF|"
"IN_MOVE_SELF|IN_Q_OVERFLOW|IN_IGNORED|IN_ONLYDIR|"
"IN_DONT_FOLLOW|IN_EXCL_UNLINK|IN_MASK_ADD|IN_ISDIR|IN_ONESHOT|"
"0x18ff1000";
long rc;
char *bogus_path = tail_memdup(bogus_path_str.path,
strlen(bogus_path_str.path) + 1);
rc = syscall(__NR_inotify_add_watch, 0, NULL, 0);
printf("inotify_add_watch(0, NULL, 0) = %s\\n", sprintrc(rc));
rc = syscall(__NR_inotify_add_watch, bogus_fd, bogus_path + 4096, 0);
printf("inotify_add_watch(%d, %p, %u) = %s\\n",
(int) bogus_fd, bogus_path + 4096, 0, sprintrc(rc));
rc = syscall(__NR_inotify_add_watch, bogus_fd, bogus_path, bogus_mask);
printf("inotify_add_watch(%d, %s, %s) = %s\\n",
(int) bogus_fd, bogus_path_str.str, bogus_mask_str,
sprintrc(rc));
rc = syscall(__NR_inotify_rm_watch, 0, 0);
printf("inotify_rm_watch(0, 0) = %s\\n", sprintrc(rc));
rc = syscall(__NR_inotify_rm_watch, bogus_fd, bogus_fd);
printf("inotify_rm_watch(%d, %d) = %s\\n",
(int) bogus_fd, (int) bogus_fd, sprintrc(rc));
puts("+++ exited with 0 +++");
return 0;
}
3.syscall系统调用
Syscall是通过中断方式实现的,ARM平台上通过swi中断来实现系统调用,实现从用户态切换到内核态,发送软中断swi时,从中断向量表中查看跳转代码,其中异常向量表定义在文件/kernelarch/arm/kernel/entry-armv.S(汇编语言文件)。当执行系统调用时会根据系统调用号从系统调用表中来查看目标函数的入口地址,在calls.S文件中声明了入口地址信息。
总体流程:kill() -> kill.S -> swi陷入内核态 -> 从sys_call_table查看到sys_kill -> ret_fast_syscall -> 回到用户态执行kill()下一行代码。
以上是关于linux系统下inotify源码分析的主要内容,如果未能解决你的问题,请参考以下文章
Linux/Unix 使用inotify,hook函数来监控文件事件
Linux/Unix 使用inotify,hook函数来监控文件事件
(转)Linux下通过rsync与inotify(异步文件系统事件监控机制)实现文件实时同步
基于redis ae实现 Linux中的文件系统监控机制(inotify)
安装源码包inotify启动失败 error while loading shared libraries: libinotifytools.so.0: cannot open shared obje