Linux学习笔记8 select

多路复用select

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

  • select函数参数解析:
    maxfd: 最大的文件描述符(最大描述符值 + 1,并不是文件描述符个数)
    readset: 内核读操作的描述符字集合
    writeset:内核写操作的描述符字集合
    exceptfds:内核异常操作的描述符字集合
    timeout:等待描述符就绪需要多少时间。NULL 代表永远等下去,固定值代表等待固定时间,0 代表根本不等待,检查描述字之后立即返回。
    select返回值:失败返回-1,成功返回就绪文件描述符的数值。
    fd_set是一个数组,以下为用法:
fd_set rdset;//定义一个rdset的集合
FD_ZERO(&rdset);//清空数组
FD_SET(0,&rdset);//监控0(标准输入文件描述符)
FD_SET(fdr,&rdset);//监控fdr描述符
FD_ISSET(fdr,&rdset);//判断fdr是否有设置
FD_CLR(fdr,&rdset);//删除fdr这个文件描述符
//注意,定义的rdset是一个传入传出参数
  • select的退出机制
    一般情况下:写端(write)如果没有往缓冲区写数据,读端会等待。
    写端如果断开(ctrl+c),read端会接收到0
    select 的退出机制:
    当管道写端先关闭时,读端使用read时会返回0(相当于发送了一个EOF)
    即select发现写端关闭,告知我们读端一直可读(一直打印)
    读端可读代码:

用户Mark2

#include "func.h"

int main(int argc,char *argv[])
{
    ARGS_CHECK(argc,3);
    int fdr=open(argv[1],O_RDONLY);//open 1st mkfifo in the way of reading
    ERROR_CHECK(fdr,-1,"open");
    int fdw=open(argv[2],O_WRONLY);//open 2nd mkfifo in the way of writing                                                                                                                 
    ERROR_CHECK(fdw,-1,"open");
    printf("I am mark2,girl\n");
    char buf[128]={0};
    int ret;
    fd_set rdset;//定义一个文件描述符集合
    while(1)
    {
        FD_ZERO(&rdset);
        FD_SET(0,&rdset);//监视STDIN_FILENO
        FD_SET(fdr,&rdset);//监视 fdr
        ret=select(fdr+1,&rdset,NULL,NULL,NULL);
        if(FD_ISSET(0,&rdset))//有数据从键盘传输过来,需要写
        {
            memset(buf,0,sizeof(buf));
            ret=read(STDIN_FILENO,buf,sizeof(buf));
            //if(ret==0)//ctrl+d
            //{
            //    printf("user has log out 2\n");
            //    break;
            //}
            ret=write(fdw,buf,strlen(buf)-1);

        }
        if(FD_ISSET(fdr,&rdset))//有数据从对端传输过来,需要读
        {
            memset(buf,0,sizeof(buf));
            ret=read(fdr,buf,sizeof(buf));
            ERROR_CHECK(ret,-1,"read");
            //if(0==ret)//ctrl+c
            //{
            //    printf("user has log out 2\n");
            //    break;
            //}
            ret=write(fdw,buf,strlen(buf)-1);
   
        }
        if(FD_ISSET(fdr,&rdset))//有数据从对端传输过来,需要读
        {
            memset(buf,0,sizeof(buf));
            ret=read(fdr,buf,sizeof(buf));
            ERROR_CHECK(ret,-1,"read");
            //if(0==ret)//ctrl+c
            //{
            //    printf("user has log out\n");
            //    break;
            //}
            printf("%s\n",buf);
        }

    }
    return 0;
}

用户Mark1

#include "func.h"

int main(int argc,char *argv[])
{
    ARGS_CHECK(argc,3);
    int fdw=open(argv[1],O_WRONLY);
    if(-1==fdw)
    {   
        perror("open");
        return -1; 
    }   
    int fdr=open(argv[2],O_RDONLY);//以只读的方式打开第二条管道
    ERROR_CHECK(fdr,-1,"open");
    printf("I am mark1\n");//测试死锁
    char buf[128]={0};
    int ret;
    fd_set rdset;
    while(1)
    {   
        FD_ZERO(&rdset);
        FD_SET(0,&rdset);
        FD_SET(fdr,&rdset);                                                                                   
        ret=select(fdr+1,&rdset,NULL,NULL,NULL);
        if(FD_ISSET(0,&rdset))
        {   
            memset(buf,0,sizeof(buf));
            ret=read(STDIN_FILENO,buf,sizeof(buf)-1);
            //if(ret==0)//ctrl+d
            //{ 
            //    printf("user has log out 2\n");
            //    break;
            //} 
            ret=write(fdw,buf,strlen(buf)-1);

        }
        if(FD_ISSET(fdr,&rdset))
        {
            memset(buf,0,sizeof(buf));
            ret=read(fdr,buf,sizeof(buf));
            ERROR_CHECK(ret,-1,"read");
            //if(0==ret)//ctrl+c
            //{
            //    printf("user has log out\n");
            //    break;
            //}
            printf("%s\n",buf);
        }
    }
    return 0;
}

注:read==0可代表读到文件末尾(可以man 2 read查看返回值)
将注释去除即为select的使用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值