UNP读书笔记

最近阅读了UNP一书中关于select函数的相关部分,虽然队C语言不是那么的熟悉,但是也能从中汲取一些有用的思想

LinuxIO模型

阻塞式I/O

非阻塞式I/O;

I/O复用(select和poll)

信号驱动式I/O(SIGIO) ;

异步I/O(POSIX的aio_系列函数)

select属于I/O复用的模型,select会阻塞与应用程序或者内核上,而不是阻塞与IO,select会接受多个socket,等待这些连接为可读,可写,或者异常时返回,下图为io复用的示意图


IO复用

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,const struct timeval *timeout); 

select的定义如上,maxfdp1参数指定待测试的描述符个数,三个参数readset、 writeset和exceptset指定我们要让内核测试读、 写和异常条件的描述符,timeout, 它告知内核等待所指定描述符中的任何一个就绪可花多长时间,当前几个参数为空指针时,我们就得到了一个精度为10MS的定时器,在tornado中,使用gen.sleep()没有阻塞程序,而time.sleep()会阻塞程序正是因为这个原因,对于文件描述符是否可读可写以及异常,有以下标准


select返回某个套接字就绪的条件小结

#include "unp.h"

void  str_cli(FILE *fp, int sockfd)

{

int maxfdp1;

fd_set rset;

char sendline[MAXLINE], recvline[MAXLINE];

FD_ZERO(&rset);

for ( ; ; ) {

        FD_SET(fileno(fp), &rset);

        FD_SET(sockfd, &rset);

        maxfdp1 = max(fileno(fp), sockfd) + 1;

        Select(maxfdp1, &rset, NULL, NULL, NULL);

        if (FD_ISSET(sockfd, &rset)) { 

                if (Readline(sockfd, recvline, MAXLINE) == 0)

                        err_quit("str_cli: server terminated prematurely");

                Fputs(recvline, stdout);

        }

if (FD_ISSET(fileno(fp), &rset)) { 

        if (Fgets(sendline, MAXLINE, fp) == NULL)

                return; /* all done */

        Writen(sockfd, sendline, strlen(sendline));

                }

        }

}

代码的基本含义是建立一个tcp连接,然后调用socket,如果soket在返回时socket是可读的,那就读取文本,然后再使用fputs输出,如果socket输入可读,那先用fgets读入一行文本,再用writen写入套接字中

若服务有单个监听描述符,那么描述符fd0,fd1,fd2分别为标准输入,输出,错误,监听套接字的fd3,当不断的有客户端连接时,服务器上的文件描述符数组会变长,本服务器能接受的最大客户端数目为select的连接限制(一般为256)与内核允许进程打开的文件描述符的最小值.

你可能感兴趣的:(UNP读书笔记)