LINUX I/O复用

标准流功能

  1. stdin 0 标准输入
  2. stdout 1 标准输出
  3. stderr 2 标准错误

write()

在linux中所有的 输入输出 都可以由write 来实现,硬盘读取,网络读取,文件读取都可以

write(目的,源,lemgth)

  1. write(stdout,buf,sizeof(buf)); //和printf效果一样在屏幕输出

文件流指针

fopen() 只可以打开普通的文件
  • int setvbuf(FILE stream, char buf, int type, unsigned size); 设置流缓冲区
  • stream为文件流指针
  • buf为缓冲区首地址
  • type为缓冲区类型
  • _IOFBF (满缓冲):当缓冲区为空时,从流读入数据。或当缓冲区满时,向流写入数据。
  • _IOLBF (行缓冲):每次从流中读入一行数据或向流中写入—行数据。
  • _IONBF (无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区
  • size为缓冲区内字节的数量
  • 返回值 成功为0 失败非0
  1. setvbuf(fp,NULL,_IONBF,0);
  • FILE 结构体

    • _IO_buf_base 读取到的位置
    • _IO_read_ptr 源文件缓冲区启示位置
    • _IO_buf_end 源文件缓冲区结束位置

缓冲区

  • 全缓冲区 BUFSIZE 默认开启

    • 缓冲区刷新函数:fflush(stdout);
  • 行缓冲区
    预见换行符才进行刷新

    • scanf() 行缓冲区 以 \n 判断是否结束
    • gets() 行缓冲区 以 \n 判断是否结束
  • 无缓冲区

    • write(0,buf); 无缓冲区
    • read(0,buf,size) 以EOF 判断是否结束
    • puts(0); 在输出内容后面自动加 \0
    • strerr()
  1. fputs("enter any charcter",stdout);//标准输出打印内容
  • 指定缓冲区
    void setbuf(FILE_ stream,char_buf)
  • buf 参数必须指向一个长度为BUFSIZE的缓冲区 如果为空 就为空缓冲区
  1. void setbuffer(FILE_ stream,char_buf,size_t size)
  • size : 指定缓冲区长度

void setlinebuf(FILE* stream)

  • 系统自动指定 缓存长度

文件读写函数

  • 都以\n为结尾

    • fgetc

    • getc

    • gets

    • puts

  • read

  • write

文件流定位

  • int fseek(FILE *stream, long offset, int fromwhere); 修改当前文件流指针

  • fromwhere: 起始点

    • SEEK_SET 0 文件开头
    • SEEK_CUR 1 文件当前位置
    • SEEK_END 2 文件末尾
  • ftell(FILE *srteam) 返回当前文件指针位置

  • rewind(FILE *srteam) 把文件指针移回开头

SOCKET 的IO模型

  • 非阻塞IO处理
  • 阻塞IO处理
  • IO复用
  • 信号驱动
  • 异步IO

非阻塞IO处理

  • 缺点:轮询次数高,不知数据拷贝的量

IO复用

  • 监听一个文件夹中的多个文件夹
  • 当文件夹中有任何一个文件可以返回就会返回,或者 超时
  • 内核层:

fcntl() 设置socket为非阻塞IO

int fcntl(int fd, int cmd, long arg);

  • 头文件 #include

  • fd:文件描述符

  • cmd: 操作命令

  • arg: 供命令使用的参数

  • 返回值 失败 -1

cmd:
  1. 一. F_DUPFD :复制文件描述词
  2. 二. FD_CLOEXEC :设置close-on-exec标志。如果FD_CLOEXEC位是0,执行execve的过程中,文件保持打开。反之则关闭。
  3. 三. F_GETFD :读取文件描述词标志。
  4. 四. F_GETFL :读取文件状态标志。
  5. 五. F_SETFL :设置文件状态标志
  • F_SETFL

    • O_NONBLOCK 非阻塞I/O
    • O_APPEND 强制每次写(write)操作都添加在文件大的末尾
    • O_ASYNC 当I/O可用的时候,允许SIGIO信号发送到进程组
  1. 知识连接:
  2. https://www.cnblogs.com/xuyh/p/3273082.html
  3. https://blog.csdn.net/bailyzheng/article/details/7463775

设置非阻塞IO

  1. int sock = socket(AF_INET,SOCK_STREAM,0);
  2. fcntl(sock,F_SETFL,O_NONBLOCK);
  3. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. // 设置此次 recv为非阻塞
  5. recv(sock,buf,bufsize,MSG_DONTWAIT);

select IO复用手段

fd_set 文件集合结构体

1.分配 select

定义 fd_set 结构体

2. 设置

初始化: FD_ZERO(&rfds);

加入句柄:FD_SET(fd,&rfds);

移除句柄:FD_CLR(fd,fd_set* set)

3. 使用

int select(int nfds, fd_set _readfds, fd_set _writefds,
fd_set _exceptfds, struct timeval _timeout);

  • 头文件 #include
  • nfds :文件集合中最大fd+1
  • readfds:可以使用单个,读写错误要对应,没有写NULL
  • timeout:超时时间
  • 返回值:错误 -1 超时0 成功 可连接数

struct timeval 结构体
  1. struct timeval
  2. {
  3. long tv_sec; //秒
  4. long tv_usec; //微秒
  5. };

FD_ISSET() 判断由哪一个fd引发的返回

int FD_ISSET(int fd, fd_set *set);