【linux下的IO模型】
阻塞IO
最常用,最简单,效率最低的IO模式<br /> **读:**recv(),read(),recvfrom(),fgets()<br /> **写:**write(),send()<br /> d当缓冲区大小小于实际写入的数据大小,会阻塞<br /> **其他:**accept(),connect()
非阻塞IO
在数据读写时不会阻塞在IO位置,需要轮询确定,<br /> 这种方式用的不多,CPU资源消耗大<br /> recv()<br />**注意:**对于文件描述符,默认都是阻塞属性
fcntl()
int fcntl(int fd,int cmd,….)
功能:
参数:
fd:要设置的描述符
cmd:要对描述符做什么设置
…:当使用fcntl函数做一些特殊操作时需要第三个参数
设置文件描述符非阻塞
cmd:
**F_GETFL:**得到文件描述符的状态<br /> **F_SETFL:**将状态重新设置写回<br />**设置非阻塞状态的参数:**O_NONBLOCK
步骤:
1.获取状态
int flag = fcntl(0,F_GETFL);
2.修改状态为非阻塞
flag |= O_NONBLOCK;
3.把修改后的状态写回
fcntl(0,F_SETFL,flag);
IO多路复用
信号驱动IO:和底层相关
【IO多路复用】
基本概念:
IO多路复用一旦发现进程指定的一个或者多个IO条件准备就绪,就通知进程进行读写操作
基本思想
1.构建一张表用于存放事件对应的描述符
2.将要检测的事件对应的文件描述符添加到表里
3.检测有没有事件发生
4.根据发生的事件写逻辑
使用场景
select
include
/* According to earlier standards */<br /> #include <sys/time.h><br /> #include <sys/types.h><br /> #include <unistd.h>
int select(int nfds, fd_set readfds, fd_set writefds,fd_set exceptfds, struct timeval timeout);
功能:
阻塞等待事件发生,一旦有事件准备就绪,会把事件对应的文件描述符置位,没发生的事件清0
参数:
**nfds:**监测的最大文件描述符的最大值+1<br /> **readfds:**读事件集合<br /> **writefds:**写事件集合<br /> **exceptfds:**异常事件集合<br /> **timeout:**这个参数如果有,则可以设置超时检测,不设置填NULL
返回值:
设置超时检测:
**>0:**发生的事件个数<br /> **==0:**超时<br /> **<0:**错误
不设置超时检测:
**错误时:**返回<0
注意:
select函数最大能监测1024个事件是否发生
0 1 2 3 4 5
void FD_CLR(int fd, fd_set set):
将fd对应的事件从集合set里清除
int FD_ISSET(int fd, fd_set set);
判断fd是否在set对应的集合内
void FD_SET(int fd, fd_set set);
将FD添加到集合set里
void FD_ZERO(fd_set set);
清空set集合
超时检测结构体:
struct timeval{
long tv_sec;//秒级别
long tv_usec;//微秒级别
};
注意:select函数每一次事件发生后就会把没有发生事件的描述符清0
案例:判断鼠标事件和键盘事件是否发生
0:键盘输入
int mouse_fd = open(“/dev/input/mouse0”,O_RDONLY);
