【linux下的IO模型】

阻塞IO

  1. 最常用,最简单,效率最低的IO模式<br /> **读:**recv(),read(),recvfrom(),fgets()<br /> **写:**write(),send()<br /> d当缓冲区大小小于实际写入的数据大小,会阻塞<br /> **其他:**accept(),connect()

非阻塞IO

  1. 在数据读写时不会阻塞在IO位置,需要轮询确定,<br /> 这种方式用的不多,CPU资源消耗大<br /> recv()<br />**注意:**对于文件描述符,默认都是阻塞属性

fcntl()

int fcntl(int fd,int cmd,….)

功能:

设置文件描述符属性

参数:

fd:要设置的描述符
cmd:要对描述符做什么设置
…:当使用fcntl函数做一些特殊操作时需要第三个参数

设置文件描述符非阻塞

cmd:
  1. **F_GETFL:**得到文件描述符的状态<br /> **F_SETFL:**将状态重新设置写回<br />**设置非阻塞状态的参数:**O_NONBLOCK

步骤:

1.获取状态
  1. int flag = fcntl(0,F_GETFL);

2.修改状态为非阻塞
  1. flag |= O_NONBLOCK;

3.把修改后的状态写回
  1. fcntl(0,F_SETFL,flag);

IO多路复用

信号驱动IO:和底层相关

【IO多路复用】

基本概念:

IO多路复用一旦发现进程指定的一个或者多个IO条件准备就绪,就通知进程进行读写操作

基本思想

1.构建一张表用于存放事件对应的描述符
2.将要检测的事件对应的文件描述符添加到表里
3.检测有没有事件发生
4.根据发生的事件写逻辑

使用场景

1.处理多个文件描述符
2.用于TCP

select

include

  1. /* 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

参数:

  1. **nfds:**监测的最大文件描述符的最大值+1<br /> **readfds:**读事件集合<br /> **writefds:**写事件集合<br /> **exceptfds:**异常事件集合<br /> **timeout:**这个参数如果有,则可以设置超时检测,不设置填NULL

返回值:

设置超时检测:
  1. **>0:**发生的事件个数<br /> **==0:**超时<br /> **<0:**错误

不设置超时检测:
  1. **错误时:**返回<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);