linux的文件多路复用的操作

.关于多路转接模型

 

selectpoll函数,他们可以设定程序中所关心的文件描述符,希望等待的时间等。从函数返回的时候,内核会通知用户准备好的文件描述符的数量,已经准备好的条件或者事件等。通过selectpoll的返回结果,对应检测到某个文件描述符的注册事件或者是超时,或者是调用出错。

 

.select函数说明

 

1.所需头文件

 

 

 

 

2.函数原型

 

int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exeptfds,struct timeval *timeout);

 

3.参数说明

 

1numfds:为需要监视的文件描述符的最大值加1

 

2readfds:由select函数监视的读文件描述符集合

 

3writefds:由select函数监视的写文件描述符集合

 

4exeptfds:由select函数监视的异常处理文件描述符集合

 

5timeout

 

----NULL:永远等待

 

----》具体值:具体的超时值

 

----0:从不等待,测试所有指定的文件描述符立即返回

 

4.返回值

 

成功:准备好的文件描述符

 

失败:-1

 

超时:0

 

5.select涉及到的文件描述符处理宏定义函数

 

1FD_ZERO(fd_set *set):清除一个文件描述符集合

 

2FD_SET(int fd,fd_set *set):将一个文件描述符加入到set集合

 

3FD_CLR(int fd,fd_set *set):将一个文件描述符从set集合删除

 

4FD_ISSET(int fd,fd_set *set):测试fd是否属于set。可以用于调用select以后检测集合中的哪个文件描述符是否有变化

 

5FD_SETSIZE表示fd_set结构能够容纳的文件描述符的最大数目

 

6.注意事项

 

1)使用select函数之前一般要用FD_ZEROFD_SET初始化文件描述符集合

 

2)在重复调用select函数的时候,先把一次初始化好的文件描述符集合备份下来,每次读取他即可

 

3)在select返回以后,可循环使用FD_ISSET来测试描述符集合

 

4)在执行完对相关文件描述符的操作以后,用FD_CLR清除该文件描述符

 

.poll函数说明

 

1.头文件

 

 

 

2.函数原型

 

int poll(struct pollfd *fds,int numfds,int timeout);

 

3.参数说明

 

1fds:用于描述需要对哪些文件的哪种类型的操作进行监控

 

2numfds:需要监听的文件个数,即第一个参数所指向的数组中的元素数目

 

3timeout:阻塞的超时时间,精确到毫秒级别,如果小于0,表示无限等待

 

4.返回值:

 

成功:大于0,表示事件发生的pollfd结构的个数

 

失败:-1

 

超时:0

 

.使用实例

 

1.select的弊端

 

1)内核必须检查多余的文件描述符

 

2)每次调用select以后都要重置被监听的文件描述符集合

 

3)可监听的文件描述符个数受限制

 

2.mknod命令创建两个管道in1,in2,然后在两个虚拟终端分别运行cat>in1cat>in2,同时在第三个终端运行主程序。

 

3.如果三个文件一直处于无输入状态,则主程序一直处于阻塞状态,为了防止无限期等待,在主程序中设置超时值。

 

4.实际代码

 

#include

#include

#include

#include

#include

#include

#include

#include

 

#define MAX_BUFSIZE  1024

#define IN_FILES 3

#define TIME_OUT 60000

#define MAX(a,b)    ((a > b) ? (a): (b))

 

int main(void)

{

 

    struct pollfd fds[IN_FILES];

    

    char buf[MAX_BUFSIZE];

 

    int i,res,real_read,maxfd;

 

    /*open two source files with some permission*/

 

    fds[0].fd = 0;

 

    if((fds[1].fd = open("in1",O_RDONLY|O_NONBLOCK)) < 0)

    {

        printf("open in1 error!\n");

        return 1;

    }

 

    if((fds[2].fd = open("in2",O_RDONLY|O_NONBLOCK)) < 0)

    {

        printf("open in2 error!\n");

        return 1;

    }

 

    /*achieve the bigger one from two filedescriptions*/

    for(i = 0; i < IN_FILES;i++)

    {

 

        fds[i].events = POLLIN;

    }

 

    while(fds[0].events || fds[1].events || fds[2].events)

    {

 

        if(poll(fds,IN_FILES,0) < 0)

        {

            printf("Poll error or time out\n");

            return 1;

        }

        for(i = 0;i < IN_FILES;i++)

        {

            if(fds[i].events)

            {

                memset(buf,0,MAX_BUFSIZE);

                real_read = read(fds[i].fd,buf,MAX_BUFSIZE);

                if(real_read < 0)

                {

 

                    if(errno != EAGAIN)

                    {

 

                        return 1;

                    }

                }

                else if(!real_read)

                {

                    close(fds[i].fd);

                    fds[i].events = 0;                        

                }

                else{

 

                    if(i == 0)

                    {

 

                        if((buf[0] == 'q') || (buf[0] == 'Q'))

                        {

                            return 1;

        

                        }

                    }

                    else{

 

                        buf[real_read] = '\0';

                        printf("%s",buf);

                    }

                }

 

            }

        }

 

    }

 

    exit(0);    

}

 

 

你可能感兴趣的:(linuxC,文件,多路复用)