求教有关linux API eventfd的问题

不秃头的程序猿Gabriel
嵌入式领域新星创作者
2020-03-22 10:55:55
下面这段代码,secelt监控了两个fd,一个是标准输入,另一个是event的fd,当先触发eventfd的时候,select会返回,但是先触发标准输入的时候,再触发eventfd,eventfd不会让select返回。现象就是,运行程序,直接ctrl C (触发eventfd)程序会退出。但是运行程序,先输入几个字母回车,再ctrl c(触发eventfd),程序不会直接退出。如果把接收到efd的那里的 break注释掉,然后试试,现象就是,先触发stdin,efd没反应,先触发efd,stdin没反应。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/select.h>
#include <pthread.h>
#include <stdlib.h>

//eventfd
#include <sys/eventfd.h>
#include <stdint.h>

fd_set allset;
char buf[256] = {0};

int efd = -1;
char isRunning = 1;

void signalstop(int signal)
{
printf("catch signal!\n");
isRunning = 0;

uint64_t u = 10;
ssize_t s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
perror("write");
}

int thread_loop()
{
printf("into thread_loop!\n");
int max_fd = efd > STDIN_FILENO ? efd : STDIN_FILENO;
while (isRunning)
{
printf("wait ......\n");
int nready = select(max_fd+1, &allset, NULL, NULL, NULL);
if (nready <= 0)
{
perror("select error:");
break;
}
printf("nready = %d\n", nready);

if (FD_ISSET(STDIN_FILENO, &allset))
{
printf("STDI.........\n");
read(STDIN_FILENO, buf, 256);
printf("buf is %s\n", buf);
}

if (FD_ISSET(efd, &allset))
{
printf("efd.........\n");
uint64_t u = 0;
ssize_t s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
perror("read");
printf("Parent read %llu from efd\n",(unsigned long long)u);
break;
}
}
printf("thread_loop exit!\n");
return 0;
}

int main(void)
{
signal(SIGINT, signalstop);

efd = eventfd(0, 0); //返回通用事件通道的文件描述符
if (efd == -1)
perror("efd init\n");

printf("efd = %d\n", efd);
FD_ZERO(&allset);
FD_SET(STDIN_FILENO, &allset);
FD_SET(efd, &allset);

pthread_t thread1;

int ret_thrd1 = pthread_create(&thread1, NULL, (void *)&thread_loop, NULL);
if (ret_thrd1 != 0)
{
printf("creat thread failed!\n");
return 0;
}

while (isRunning)
{
sleep(1);
}

pthread_join(thread1, NULL);
close(efd);
printf("main exit!\n");

return 0;
}
...全文
960 1 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
tobybo 2020-04-23
  • 打赏
  • 举报
回复
if (FD_ISSET(efd, &allset)); 这句代码的意思是 检查 你的 allset 描述符集合里存不存在 efd这个描述符; 第一个事件触发后,再次select的时候,allset 里面已经没有另一个描述符了,当然就等不到对应事件通知了; while (isRunning) { printf("wait ......\n"); int nready = select(max_fd+1, &allset, NULL, NULL, NULL); poll与select一个很大的不同就是: select修改其参数以指示哪一个描述符已准备好了。

4,465

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧