IO多路复用与select函数原理
同时监听标准输入和管道,避免陷入读、写、报错的阻塞态。select函数参数里面有传入读集合、写集合以及error集合,会将对应的文件描述符存入对应的集合中(fd_set数据类型)。
fd是文件描述符,对应内核态文件索引数组的下标。
#include <homeworkhead.h>
int main(int argc,char* argv[]){
// ./chat1 1.pipe 2.pipe
ARGS_CHECK(argc,3);
int fdr = open(argv[1],O_RDONLY);//只读管道1
ERROR_CHECK(fdr,-1,"open fdr");
int fdw = open(argv[2],O_WRONLY);//只写管道2
ERROR_CHECK(fdw,-1,"open fdw");
puts("pipe established!");
char buf[2048]={0};
fd_set rdset;//监听读集合
struct timeval timeout;
struct stat timrrecord;//记录文件状态
while (1)//开始死循环通信直到一方主动读EOF
{
FD_ZERO(&rdset);//读集合清零
FD_SET(fdr,&rdset);//将读管道加入监听
FD_SET(STDIN_FILENO,&rdset);//将标准输入加入监听
timeout.tv_sec=60;//1分钟不通信主动断开聊天
timeout.tv_usec=0;
//肯定fdr最大,因为标准输入是0
int sret = select(fdr+1,&rdset,NULL,NULL,&timeout);
if(sret==0){
printf("timeout!\n");
break;
}
time_t now ;
struct tm *tm_now ;
time(&now) ;
tm_now = localtime(&now) ;//get time
//轮询
if(FD_ISSET(fdr,&rdset)){
memset(buf,0,sizeof(buf));
read(fdr,buf,sizeof(buf));
printf("%d:%d:%d ",tm_now->tm_hour,
tm_now->tm_min,tm_now->tm_sec);
puts(buf);
}
if(FD_ISSET(STDIN_FILENO,&rdset)){
memset(buf,0,sizeof(buf));
read(STDIN_FILENO,buf,sizeof(buf));
write(fdw,buf,strlen(buf)-1);
}
}
return 0;
}