C 如何正确避免;“铸件增加所需的对准度”;读取(2)结构时发出警告?

C 如何正确避免;“铸件增加所需的对准度”;读取(2)结构时发出警告?,c,system-calls,memory-alignment,C,System Calls,Memory Alignment,许多Linux内核接口(inotify等)都是通过read(2)从某个文件描述符读取结构形式的数据来工作的。这样做的代码通常是这样的: #include <unistd.h> #include <sys/inotify.h> int main() { // all error checking omitted for brevity int inotify_fd = inotify_init(); inotify_add_

许多Linux内核接口(inotify等)都是通过
read(2)
从某个文件描述符读取结构形式的数据来工作的。这样做的代码通常是这样的:

#include <unistd.h>
#include <sys/inotify.h>

int main() {
        // all error checking omitted for brevity
        int inotify_fd = inotify_init();
        inotify_add_watch(inotify_fd, "file_to_watch", IN_ALL_EVENTS);
        char c[4096];
        for(;;) {
                ssize_t len = read(inotify_fd, c, sizeof(c));
                struct inotify_event *s;
                for(char* p = c; p < c + len; p += sizeof(struct inotify_event) + s->len) {
                        s = (struct inotify_event *)p;
                        // do stuff with s
                }
        }
}
我第一次尝试修复此警告是修复对齐方式:我尝试使用
#include
alignas(struct inotify_事件)
,但没有成功

我想修复这个警告,而不是让它安静下来。我怎样才能做到

编辑:以下是在inotify fd上读取(2)的工作方式,由以下人员记录:

每次成功读取(2)都会返回一个缓冲区,其中包含一个或多个 以下结构:

       struct inotify_event {
           int      wd;       /* Watch descriptor */
           uint32_t mask;     /* Mask describing event */
           uint32_t cookie;   /* Unique cookie associating related
                                 events (for rename(2)) */
           uint32_t len;      /* Size of name field */
           char     name[];   /* Optional null-terminated name */
       };
[……]

此文件名以null结尾,可能包括 进一步的空字节('\0'),以将后续读取与适当的 地址边界

len字段统计名称中的所有字节,包括空字节 字节;因此,每个inotify_事件结构的长度为 sizeof(struct inotify_事件)+len

指定读取的缓冲区(2)太小而无法返回时的行为 关于下一个事件的信息取决于内核版本:in 2.6.21之前的内核,read(2)返回0;从内核2.6.21开始,读取(2) 失败,错误为EINVAL。指定大小为的缓冲区

sizeof(struct inotify_event) + NAME_MAX + 1
将足以读取至少一个事件

我无法读取部分结构,例如从固定大小的片段中分别读取名称。如果我没有指定足够大的缓冲区来读取整个结构,我就不会得到任何缓冲区

union {
     char    buf[1];
     struct some_struct mine;
} b;

确保b.buf和b.mine拥有相同的地址;此外,编译器保证任何所需的对齐。几乎不需要属性扩展(例如alignas),让源代码中没有这种积垢有很大的价值。

那么代码应该如何调用
read()
?请注意OP的
sizeof(c)
参数。“我该怎么做”实际上取决于如何编写它以使其正常工作,而不仅仅是修复对齐问题。建议发布数据的写入方式。数据根本不是“写入”的。在实际代码中,我不是从stdin(fd 0)中读取,而是从我提到的一个特殊文件描述符中读取,其中调用read()只会使内核将适当的数据复制到buf中,而不会发生任何相应的write()。特殊的文件描述符将用于文档布局。尽可能发布/链接与特殊文件描述符相关的信息。或者只使用
联合
技巧。@chux inotify就是这样一种特殊的FD。我将请求的信息编辑到问题中。使用expect
char buf[1]-->
charbuf[4096]。作为稳健错误检查的一部分,确保
read()
返回值在
s->len
中有意义。
union {
     char    buf[1];
     struct some_struct mine;
} b;