学习笔记(linux高级编程)16

IO多路复用

   定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力

   作用:

   应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标的输入、中断信号等等事件,再比如web服务器如nginx,需要同时处理来来自N个客户端的事件。

   逻辑控制流在时间上的重叠叫做 并发

   而CPU单核在同一时刻只能做一件事情,一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片,不同事件流的时间片交替进行)。在计算机系统中,我们用线程或者进程来表示一条执行流,通过不同的线程或进程在操作系统内部的调度,来做到对CPU处理的时分复用。这样多个事件流就可以并发进行,不需要一个等待另一个太久,在用户看起来他们似乎就是并行在做一样。

   使用并发处理的成本:

   线程/进程创建成本

   CPU切换不同线程/进程成本 Context Switch

   多线程的资源竞争

   有没有一种可以在单线程/进程中处理多个事件流的方法呢?一种答案就是IO多路复用。

   因此IO多路复用解决的本质问题是在用更少的资源完成更多的事。

IO模型

   1、阻塞IO 

   2、非阻塞IO  EAGAIN  忙等待 errno

   3、信号驱动IO  SIGIO 用的相对少(了解)

   4、并行模型 进程,线程

   5, IO多路复用  select、poll、epoll

   1、阻塞IO ===》最常用 默认设置

   2、非阻塞IO ===》在阻塞IO的基础上调整其为不再阻塞等待。

    在程序执行阶段调整文件的执行方式为非阻塞:

            ===》fcntl() ===>动态调整文件的阻塞属性

   #include <unistd.h>

   #include <fcntl.h>

   int fcntl(int fd, int cmd, ... /* arg */ );

   功能:修改指定文件的属性信息。

   参数:fd 要调整的文件描述符

         cmd 要调整的文件属性宏名称

         ... 可变长的属性值参数。

   返回值:成功  不一定,看cmd

            失败  -1;

eg:修改文件的非阻塞属性:

       int flag ;

       flag  = fcntl(fd,F_GETFL,0);  ///获取fd文件的默认属性到flag变量中。

       flag  = flag | O_NONBLOCK;    ///将变量的值调整并添加非阻塞属性

       fcntl(fd,F_SETFL,flag);       ///将新属性flag设置到fd对应的文件生效。

       以上代码执行后的阻塞IO将变成非阻塞方式。

3.信号驱动io

   文件描述符需要追加 O_ASYNC 标志。

   设备有io事件可以执行时,内核发送SIGIO信号。

       1.追加标志

       int flag ;

       flag  = fcntl(fd,F_GETFL,0);

       fcntl(fd,F_SETFL,flag | O_ASYNC);   

       2.设置信号接收者

       fcntl(fd,F_SETOWN,getpid());//常用设置

       3.对信号进行捕获

       signal(SIGIO,myhandle);

4.并发

       1.进程

       2.线程

 IO 多路复用 ===》并发服务器 ===》TCP协议

       3、select循环服务器 ===> 用select函数来动态检测有数据流动的文件描述符

   #include <sys/select.h>

   #include <sys/time.h>

   #include <sys/types.h>

   #include <unistd.h>

   int select(int nfds, fd_set *readfds, fd_set *writefds,

                fd_set *exceptfds,

                struct timeval *timeout);

   功能:完成指定描述符集合中有效描述符的动态检测。

         该函数具有阻塞等待功能,在函数执行完毕后

         目标测试集合中将只保留最后有数据的描述符。

   参数:nfds 描述符的上限值,一般是链接后描述符的最大值+1;

         readfds 只读描述符集

         writefds 只写描述符集

         exceptfds 异常描述符集

         以上三个参数都是 fd_set * 的描述符集合类型

         timeout  检测超时 如果是NULL表示一直检测不超时 。

   返回值:超时 0

            失败  -1

            成功 >0

       为了配合select函数执行,有如下宏函数:

       void FD_CLR(int fd, fd_set *set);

       功能:将指定的set集合中编号为fd的描述符号删除。

       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集合中所有描述符删除。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值