内核(操作系统)一旦发现进程指定的一个或者多个IO条件准备读或者准备写的时候,就会给该进程发一个通知。当服务端要处理多个套接字文件描述符的时候,这个时候可以采用IO复用,操作系统发现哪些套接字文件描述符可读或可写的时候,就会通知相应的进程才去执行对应的read(保证文件描述符对应的地址有可用的数据返回,而不是由于试探性的返回无用的值)或write操作。
可以举个例子:
例如:现在李老师收取刚刚布置给学生要默写在纸上的古诗的作业。
第一种情况:李老师按照学号的顺序来收取,并且会等待将要收取作业的同学同意提交作业,直到该同学提交作业,才会去下一个学号的同学那里去询问是否提交作业。(循环处理每个socket,不支持高并发,效率低)
第二种情况:李老师向其他老师请求帮助,拉来了很多老师帮忙收作业,每个老师处理一小部分学生的古诗词作业的提交任务。(相当与创建多个进程或者线程处理socket)
第三种情况:李老师站在讲台上,根据同学们的反应来做出相应的动作(如果谁的要提交作业,该同学就举手),某些同学举手后,李就会去收取这些同学的作业。(IO复用)
系统调用函数实现IO复用将多个文件描述符集中到一起统一监视。比如对多个套接字进行统一管理与调度 。
1.select函数函数会做的事情包括:
检测是否存在套接字接受数据
检测是否存在套接字无阻塞的传输数据
哪些套接字发生了异常
该函数的调用时的顺序
1. 设置文件描述符
将需要监视的文件描述符集中到一起(fd_set),集中的时候要按照监视项来区分(包括接收,传输,异常)。fd_set结构体如下:
/* The fd_set member is required to be an array of longs. */ typedef long int __fd_mask; /* Number of descriptors that can fit in an `fd_set'. */ #define __FD_SETSIZE 1024 /* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ #define __NFDBITS (8 * (int) sizeof (__fd_mask)) /* fd_set for select and pselect. */ typedef struct { __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; } fd_set;