我很困惑与read()
调用获得通知事件。
代码如下:
#define EVENT_SIZE sizeof(inotify_event)
int fd = inotify_init();
int wd = inotify_add_watch(fd, dir, IN_MODIFY);
void* p = malloc(sizeof(EVENT_SIZE));
read(wd, p, (EVENT_SIZE + 10));
我的测试文件是a.txt
。gdb中调试后的输出如下:
{wd = 0, mask = 0, cookie = 0, len = 0, name = 0x558f05d002d0 ""}
现在,当我将最后一行改为read(fd, p, (EVENT_SIZE + 16));
时,我在gdb中得到的输出是:
{wd = 1, mask = 2, cookie = 0, len = 16, name = 0x5625cdd422d0 ".a.txt.swp"}
Q1。为什么我没有得到一个溢出错误,因为在这两种情况下,我写的比分配的缓冲区p
多?
Q2。如果没有错误,那么我的第一个程序也应该工作,因为我的文件名小于10,但它不起作用,它只对16起作用。我遗漏了什么?
编译器-g++ 9.3.0
os -ubuntu 20.04
谢谢。
- 在数组边界外写入的行为是undefined。另外,
read
读取到 - ? ?
Q1
-
如果你的进程试图访问一个不属于它的内存地址,你会得到一个段错误。
-
malloc - "通常,malloc()从堆中分配内存,并根据需要使用sbrk(2)调整堆的大小。">
-
sbrk - "sbrk()将程序的数据空间以增量字节增加。">
1。2。和3。有(可能)空间,你可以写,但数据(如果有的话)后,你分配的内存肯定是损坏的!
Q2
请阅读inotify的文档
inotify_event结构的字段含义:
面具包含描述发生事件的位(见下文)。
和
len字段计算name中的所有字节,包括空字节;因此,每个inotify_event结构的长度为
sizeof(struct inotify_event)+len
。
和
名称字段仅在为监视目录中的文件返回事件时才存在;它标识被监视目录中的文件名。该文件名以null结尾,并且可能包含更多的空字节(' '),以便将后续读取对齐到合适的地址边界。
和
当给read(2)的缓冲区太小而不能返回下一个事件的信息时的行为取决于内核版本:在2.6.21之前的内核中,read(2)返回0;从2.6.21内核开始,read(2)会失败并报错EINVAL。指定一个大小为
sizeof(struct inotify_event) + NAME_MAX + 1
的缓冲区将足以读取至少一个事件。