Многие интерфейсы ядра 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
}
}
}
Когда я компилирую вышеизложенное с помощью clang, я получаю это предупреждение:
inotify.c:13:15: warning: cast from 'char *' to 'struct inotify_event *' increases required alignment from 1 to 4 [-Wcast-align]
s = (struct inotify_event *)p;
^~~~~~~~~~~~~~~~~~~~~~~~~
Моя первая попытка исправить это предупреждение - исправить выравнивание: я пытался использовать #include <stdalign.h>
и alignas(struct inotify_event)
, но безрезультатно.
Я бы хотел исправить это предупреждение, а не просто заставить его замолчать. Как я могу это сделать?
РЕДАКТИРОВАТЬ: Вот как работает read (2) на inotify fd, как документально подтверждено его справочной страницей :
Каждое успешное чтение (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 */
};
[...]
Это имя файла заканчивается на ноль и может включать
дополнительные нулевые байты ('\ 0') для выравнивания последующих чтений с подходящим
граница адреса.
Поле len подсчитывает все байты в имени, включая ноль
байт; таким образом, длина каждой структуры inotify_event
sizeof (struct inotify_event) + len.
Поведение, когда буфер для чтения (2) слишком мал для возврата
Информация о следующем событии зависит от версии ядра: в
ядра до 2.6.21, read (2) возвращает 0; начиная с ядра 2.6.21, читать (2)
не удается с ошибкой EINVAL. Указание буфера размером
sizeof(struct inotify_event) + NAME_MAX + 1
будет достаточно, чтобы прочитать хотя бы одно событие.
Я не могу прочитать частичные структуры, такие как чтение имени отдельно от фрагмента фиксированного размера. Если я не укажу достаточно большой буфер для чтения всей структуры, я ничего не получу.