下面这段代码,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;
}
