【发布时间】:2021-03-04 08:12:32
【问题描述】:
我正在尝试对https://man7.org/linux/man-pages/man2/eventfd.2.html 中提供的示例进行稍微修改的版本。
include <sys/eventfd.h>
#include <unistd.h>
#include <inttypes.h> /* Definition of PRIu64 & PRIx64 */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition of uint64_t */
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int efd;
uint64_t u;
ssize_t s;
int j;
int retval;
fd_set rfds;
struct timeval tv;
int count = 0;
if (argc < 2) {
fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
exit(EXIT_FAILURE);
}
efd = eventfd(0, EFD_CLOEXEC | EFD_SEMAPHORE);
if (efd == -1)
handle_error("eventfd");
switch (fork()) {
case 0:
for (j = 1; j < argc; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("write");
}
printf("Child completed write loop\n");
sleep(60);
for (j = 1; j < argc; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("write");
}
sleep(10);
for (j = 1; j < 10; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("write");
}
exit(EXIT_SUCCESS);
default:
FD_ZERO(&rfds);
FD_SET(efd, &rfds);
tv.tv_sec = 5;
printf("Parent about to read\n");
while(1) {
count++;
printf("entering\n");
retval = select(efd + 1, &rfds, NULL, NULL, &tv);
printf("THE RETVAL IS %d\n", retval);
if (retval == -1) {
printf("fetched nothing\n");
}
else if (retval > 0) {
s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
printf("Parent read %"PRIu64" (%#"PRIx64") from efd\n", u, u);
}
printf("count...%d\n", count);
}
case -1:
handle_error("fork");
}
return 0;
}
输出:
./a.out 10 3 4 5
event fd is 3
Parent about to read
entering
Child writing 10 to efd
Child writing 3 to efd
Child writing 4 to efd
Child writing 5 to efd
hey THE RETVAL IS 1
Child completed write loop
Parent read 1 (0x1) from efd
count...1
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...2
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...3
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...4
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...5
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...6
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...7
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...8
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...9
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...10
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...11
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...12
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...13
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...14
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...15
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...16
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...17
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...18
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...19
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...20
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...21
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...22
entering
Child writing 10 to efd
Child writing 3 to efd
Child writing 4 to efd
Child writing 5 to efd
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...23
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...24
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...25
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...26
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...27
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...28
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...29
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...30
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...31
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...32
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...33
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...34
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...35
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...36
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...37
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...38
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...39
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...40
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...41
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...42
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...43
entering
hey THE RETVAL IS 1
Parent read 1 (0x1) from efd
count...44
entering
.... upto 66
我的目标是基本上使用父进程中的select() 监视事件 fd,然后进行read() 调用。从输出来看,似乎父进程的 select 调用仅在子进程执行某些写入操作时才对 fd 起作用。如果子进程不做任何事情,即如果它处于睡眠状态,那么父进程就会阻止 select 调用,即使 5 秒过去了,它也永远不会超时。我在这里还缺少什么吗?
【问题讨论】:
-
您忘记初始化
tv结构的tv_usec成员。现在它将有一个 indeterminate 值,这可能导致未定义的行为。 -
两者都必须申报吗?此外,
tv_usec必须初始化为与秒相同的值(以微秒为单位)。对吗? -
是的,您必须初始化整个结构。它可以被显式初始化为零(就像你对
tv_sec成员所做的那样),或者通过在定义上初始化tv结构(如struct timeval tv = { 0, 0 };)。 -
初始化
tv_usec工作。谢谢你。您可以将其添加为答案吗?