与 read() 系统调用混淆

时间:2021-01-23 14:18:02

标签: c system inotify

我对获取 inotify 事件的 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"}

第一季度。为什么我没有收到溢出错误,因为在这两种情况下,我写入的内容都超过了分配的缓冲区 p

第 2 季度。如果没有错误,那么我的第一个程序也应该可以运行,因为我的文件名小于 10,但它不起作用,并且只能处理 16。我在这里缺少什么?

编译器 - g++ 9.3.0

操作系统 - ubuntu 20.04

谢谢。

2 个答案:

答案 0 :(得分:0)

  1. 在数组边界之外写入的行为是未定义。此外,read 读取最多给定的字节数。
  2. ???

答案 1 :(得分:0)

第一季度

  1. 如果您的进程尝试访问不属于它的内存地址,则会出现段错误。

  2. malloc - “通常,malloc() 从堆分配内存,并根据需要调整堆的大小,使用 sbrk(2)。”

  3. sbrk - “sbrk() 将程序的数据空间增加字节。”

从 1.、2. 和 3. 开始:(可能)还有空间可供您写入,但分配的内存后的数据(如果有)肯定已损坏!

第二季度

阅读 inotify 的文档。

inotify_event 结构体的字段含义:

<块引用>

ma​​sk 包含描述发生的事件的位(见下文)。

<块引用>

len 字段计算 name 中的所有字节,包括空字节;因此,每个 inotify_event 结构的长度为 sizeof(struct inotify_event)+len

<块引用>

name 字段仅在为监视目录中的文件返回事件时出现;它标识了监视目录中的文件名。此文件名以空字符结尾,并且可能包含更多空字节 ('\0') 以将后续读取对齐到合适的地址边界。

<块引用>

当提供给 read(2) 的缓冲区太小而无法返回有关下一个事件的信息时的行为取决于内核版本:在 2.6.21 之前的内核中,read(2) 返回 0;从内核 2.6.21 开始,read(2) 失败并显示错误 EINVAL。指定大小为 sizeof(struct inotify_event) + NAME_MAX + 1 的缓冲区足以读取至少一个事件。

相关问题