将文件描述符读入 NULL 是否合法?
Is it legal to read a file descriptor into NULL?
最近,我 fixing the timestep 为了我正在编写的库。经过一些研究,假设我最终得到了这个原型,精确且易于与我的库的通用事件系统结合:
#include <stdio.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <poll.h>
struct pollfd fds[1];
struct itimerspec its;
int main(void) {
fds[0] = (struct pollfd) {timerfd_create(CLOCK_MONOTONIC, 0), POLLIN, 0}; //long live clarity
its.it_interval = (struct timespec) {0, 16666667};
its.it_value = (struct timespec) {0, 16666667};
timerfd_settime(fds[0].fd, 0, &its, NULL);
while(1) {
poll(fds, 1, -1);
if(fds[0].revents == POLLIN) {
long long buffer;
read(fds[0].fd, &buffer, 8);
printf("ROFL\n");
} else {
printf("BOOM\n");
break;
}
}
close(fds[0].fd);
return 0;
}
然而,为了使计时器的文件描述符可重用,我不得不用整个宝贵的 8 字节数据污染我的 CPU 缓存,这严重伤害了我。因此,我尝试用 lseek()
替换 read()
调用,如下所示:
lseek(fds[0].fd, 0, SEEK_END);
不幸的是,这两个甚至 lseek(fds[0].fd, 8, SEEK_CUR);
都给了我 ESPIPE
错误并且无法工作。但是后来,我发现尽管给出了 EFAULT
s:
read(fds[0].fd, NULL, 8);
像这样偏移文件描述符是合法的、已定义的行为吗?如果不是(正如 EFAULT
向我建议的那样,强烈到足以避免使用那个天才),是否存在一个函数可以丢弃读取的数据,而无需将其写下来,或者以其他方式抵消我的计时器的文件描述符?
read(2) 的 POSIX 规范没有指定将空指针作为缓冲区参数传递的后果。没有给出具体的错误代码,也没有说明是否会从描述符中读取任何数据。
Linux man page 有这个错误,但是:
EFAULT
buf is outside your accessible address space.
虽然它并没有说它会读取 8 个字节并在发生这种情况时丢弃它们。
所以我认为您不能依赖它随心所欲地工作。
最近,我 fixing the timestep 为了我正在编写的库。经过一些研究,假设我最终得到了这个原型,精确且易于与我的库的通用事件系统结合:
#include <stdio.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <poll.h>
struct pollfd fds[1];
struct itimerspec its;
int main(void) {
fds[0] = (struct pollfd) {timerfd_create(CLOCK_MONOTONIC, 0), POLLIN, 0}; //long live clarity
its.it_interval = (struct timespec) {0, 16666667};
its.it_value = (struct timespec) {0, 16666667};
timerfd_settime(fds[0].fd, 0, &its, NULL);
while(1) {
poll(fds, 1, -1);
if(fds[0].revents == POLLIN) {
long long buffer;
read(fds[0].fd, &buffer, 8);
printf("ROFL\n");
} else {
printf("BOOM\n");
break;
}
}
close(fds[0].fd);
return 0;
}
然而,为了使计时器的文件描述符可重用,我不得不用整个宝贵的 8 字节数据污染我的 CPU 缓存,这严重伤害了我。因此,我尝试用 lseek()
替换 read()
调用,如下所示:
lseek(fds[0].fd, 0, SEEK_END);
不幸的是,这两个甚至 lseek(fds[0].fd, 8, SEEK_CUR);
都给了我 ESPIPE
错误并且无法工作。但是后来,我发现尽管给出了 EFAULT
s:
read(fds[0].fd, NULL, 8);
像这样偏移文件描述符是合法的、已定义的行为吗?如果不是(正如 EFAULT
向我建议的那样,强烈到足以避免使用那个天才),是否存在一个函数可以丢弃读取的数据,而无需将其写下来,或者以其他方式抵消我的计时器的文件描述符?
read(2) 的 POSIX 规范没有指定将空指针作为缓冲区参数传递的后果。没有给出具体的错误代码,也没有说明是否会从描述符中读取任何数据。
Linux man page 有这个错误,但是:
EFAULT
buf is outside your accessible address space.
虽然它并没有说它会读取 8 个字节并在发生这种情况时丢弃它们。
所以我认为您不能依赖它随心所欲地工作。