IO模型

linux下主要有四种模型
阻塞 IO:
最常用、简单、效率低
read,recv,recvfrom
write,send,sendto,
accept,connect
非阻塞IO:
可防止进程则阻塞在IO操作上,需要轮询
当一个应用程序使用了非阻塞模式的套接字,它需要使用一个循环来不停的测试是否一个文件描述符有数据可读。浪费CPU资源。
fcntl函数是设置套接字的标志
int fcntl(int fd,int cmd ,long arg)
例如:
int flag;
flag = fcntl(sockfd,F_GETFL,0)
flag|=O_NONBLOCK;
fcntl(sockfd,F_SETFL,flag);

IO多路复用:
允许同时对多个IO进行控制
应用程序中同时处理多路输入输出流,若采用阻塞模式,将得不到预期的目的;若采用非阻塞方式,则对多个输入进行轮询,浪费CPU时间;
若设置多个进程,分别处理一条数据通路,将新产生进程间同步与通信的问题,比较复杂;比较好的方法是使用IO多路复用。其基本思想是:

先构造一张有关描述符的表,然后调用一个函数。当这些文件描述符中的一个或者多个已经准备好进行IO时候,函数才返回。函数返回时告诉
进程,哪个描述符已就绪,可以进行IO操作。
信号驱动IO:
异步通信模型


IO多路复用函数
int select(int n,set *read_fds,fd_set * write_fds,fd_set *except_fds,struct timeval *timeout);

函数参数:
maxfd 所有的文件描述符中最大的那个+1
read_fds 所有要读的文件描述符的集合
write_fds 所有要写的文件描述符的集合
except_fds 其他要向我们通知的文件描述符
timeout 超时设置
NULL:一直阻塞,直到有文件描述符就绪或出错
时间值为0;仅仅检测文件描述符集的状态,然后立即返回
时间值不为0;在指定时间内,如果没有事件发生,则超时返回。
在我们调用select时,进程会一直阻塞直到以下的一种情况发生。
有文件可读、有文件可写、超时设置的时间到

为了设置文件描述符我们要使用几个宏:

FD_SET 将fd加入到fdset
FD_CLR 将fd从fdset里面清除
FD_ZERO 从fdset中清除所有的文件描述符
FD_ISSET 判断fd释放在fdset集合中

宏形式:
void FD_ZERO(fd_set *fdset)
void FD_SET(int fd,fd_set * fdset)
void FD_CLR(int fd, fd_set *fdset)
int FD_ISSET(int fd ,fd_set *fdset)

例子:

fd_set rdfs;
while(1)
{
FD_ZERO(&rdfs);
FD_SET(0,&rdfs);
FD_SET(listenfd,&rdfs);
select(listenfd+1,&rdfs,NULL,NULL,NULL);

for(i = 0 ;i<=(listenfd+1);i++)
{
if(FD_ISSET(i,&rdfs))
{
if(i == STDIN_FILENO) //标准输入文件描述符
{
fgets(buf,N,stdin);
printf("%s\n",buf);
}
else if (i == listenfd)
{
connfd = accept(listenfd,NULL,NULL);
printf("new connect connfd=%d is coming",connfd);
}
}
}
}

 

 

 

 

 

 

 

 

你可能感兴趣的:(IO)