• 函数模型Linux系统文件I/O编程(三)I/O多路复用


    文章结束给大家来个程序员笑话:[M]

        多路复用

        函数说明

        我们都晓得fcntl()函数处理了文件共享的问题,如果不晓得请看:http://blog.csdn.net/mybelief321/article/details/8993138。接下来该处置I/O复用的情况了。那么,什么是I/O复用呢?这个咱得先弄清楚,所谓的I/O复用无非就是多个进程共同应用一个I/O输入输出流。

       在经典的《Unix网络编程第1卷》Chapter 6中作者详细介绍了五种I/O模型,分离为:
       ① blocking I/O
       ② nonblocking I/O
       ③ I/O multiplexing (select and poll)
       ④ signal driven I/O (SIGIO)
       ⑤ asynchronous I/O (the POSIX aio_functions)

       我英语水平一般,还是换成中文的来说吧。I/O处置的模型有5种:

       ① 阻塞I/O型:在这种模式下,若所调用的I/O函数没有实现相干的功能,则会使进程挂起,直到相干数据达到才会返回。如常见对管道设备、终端设备和网络设备进行读写时经常会涌现这种情况。

       ② 非阻塞I/O型:在这种模式下,当请求的I/O操纵不能实现时,则不让进程睡眠,而且立即返回。非阻塞I/O应用户可以调用不会阻塞的I/O操纵,如open()、write()和read()。如果该操纵不能实现,则会立即返回犯错(如打不开文件)或者返回0(比如在缓冲区中没有数据可以读取或者没有空间可以写入数据)。

       ③ I/O多路转接模型:在这种模式下,如果请求的I/O操纵阻塞,且它不是真正的阻塞I/O,而是让其中的一个函数等待,在此期间,I/O还能进行其他操纵。咱们接下来要说的select()函数和poll()函数,就是属于这种类型。

       ④ 信号驱动I/O模型:在这种模式下,进程要定义一个信号处置程序,系统可以自动捕获特定信号的到来,从而启动I/O。这是由内核通知用户何时可以启动一个I/O操纵决定的。这种模型是非阻塞的,当有就绪的数据时,内核就向该进程发送SIGIO信号。无论我们如何处置SIGIO信号,这种模型的利益就是当等待数据达到时,可以不阻塞。主程序继承执行,只有收到SIGIO信号时,才去处置数据即可。

       ⑤ 异步I/O模型:在这种模型下,进程先让内核启动I/O操纵,并在整个操纵实现后通知该进程。这种模型与信号驱动模型的主要区分在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操纵,而异步I/O模型是由内核通知进程I/O操纵何时实现的。当初并非全部的系统都支撑这种模型。

        相比较而言,select()和poll()的I/O多路转换模型是处置I/O复用的一个高效的方法。它可以详细设置程序中每一个所关心的文件描述符的条件、希望等待的时光等,从select()函数和poll()函数返回时,内核会通知用户已准备好的文件描述符的数量、已准备好的条件(或事件)等。通过应用select()和poll()函数的返回结果(多是检测到某个文件描述符的注册事件或是超时,或是调用犯错),就可以调用相应的I/O处置函数了。

        函数格式

       下图为select()函数的介绍

       函数和模型

        可以看到,select函数根据希望进行的文件操纵对文件描述符进行了分类,这里对文件描述符的处置主要涉及4个宏函数,如下表2所示

        函数和模型

         另外,select()函数中的 timeou 是一个 struct timeval类型的指针,该结构体如下所示:

         函数和模型

        可以看到,这个时光结构体的精确度可以设置到微秒级,这对于大多数的应用而言已足够了。

        每日一道理
    冰心说道:“爱在左,同情在右,走在生命的两旁,随时撒种,随时开花,将这一径长途,点缀得香花弥漫,使穿枝拂叶的行人,踏着荆棘,不觉得痛苦,有泪可落,却不是悲凉。”

        应用select()函数的进程可归纳综合为:先调用FD_ZERO() 将指定的fd_set清零,然后调用宏FD_SET()将需要测试的fd加入fd_set,接着调用函数select测试fd_set中的全部fd,最后用用宏FD_ISSET()检查某个fd在函数select调用后,相应位是不是仍然为1。在执行完对相干文件描述符的操纵后,应用FD_CLR来描述符集。

        下表为 poll()函数的介绍:

        函数和模型

        基础实验

        实验原理

          本实验主要实现通过调用poll()函数来监听三个终端的输入(分离重定向到两个管道文件的虚拟终端及主程序所运行的虚拟终端)并分离进行相应的处置。在这里我们建立了一个poll()函数监听的读文件描述符集,其中包含三个文件描述符,分离为标准输入文件描述符和两个管道文件描述符。通过监视主程序的虚拟终端标准输入来实现程序的控制(如程序结束);以两个管道作为数据输入,主程序将从两个管道读取的输入字符串写入到标准输出文件(屏幕)。

         为了充分表示poll()函数的功能,在运行主程序时,需要打开3个虚拟终端:首先用mknod命令创建两个管道 in1 和 in2。接下来,在两个虚拟终端上分离运行 cat > in1和cat > in2.同时在第三个虚拟终端上运行主程序。

       在程序运行后,如果在两个管道终端上输入字符串,则可以观察到同样的内容将在主程序的虚拟终端上逐行显示。

       如果想结束主程序,只要在主程序的虚拟终端下输入以“q”或“Q”字符开头的字符串即可。如果三个文件一直在无输入状态张,则主程序一直处于阻塞状态。为了防止无限期的阻塞,在程序中设置超时值(本实验汇总设置为60s),当无输入状态延续到超时值时,主程序自动结束运行并退出。

       程序的流程图如下:

      函数和模型

       实验步调:本次实验只需要一个c文件,即multiplex_poll.c,我上传到了网站,请自行下载:点此下载

       在第一个终端中,应用命令:gcc multiplex.c -o multiplex编译文件,如下

       函数和模型

       应用命令建立两个管道文件:mknod  in1  p

                                                      mknod  in2  p,如下图,mknod命令不懂得的请点此

        函数和模型 

        在终端1执行命令:./multiplex_select

        再打开两个终端,在终端2中执行命令: cat > in1 ,不懂得cat命令的请点此,在终端3中执行命令:cat > in2,如下图所示,分离在终端2和3中输入字符,终端1中就会显示,在终端1中输入q或Q,则立刻结束程序运行。

        函数和模型

        函数和模型函数和模型

       函数和模型

       下图为程序的超时结果:

      函数和模型

      

        

    文章结束给大家分享下程序员的一些笑话语录: 乔布斯:怎么样还是咱安全吧!黑客:你的浏览器支持国内网银吗?苹果可以玩国内的网游吗乔布斯:......不可以黑客:那我研究你的漏洞干嘛,我也需要买奶粉!

    --------------------------------- 原创文章 By
    函数和模型
    ---------------------------------

  • 相关阅读:
    BZOJ3997:[TJOI2015]组合数学(DP,Dilworth定理)
    BZOJ4807:車(组合数学,高精度)
    BZOJ4008:[HNOI2015]亚瑟王(DP,概率期望)
    BZOJ1499:[NOI2005]瑰丽华尔兹(DP,单调队列)
    洛谷1514 引水入城
    洛谷 1018 乘积最大
    八数码难题
    CODEVS 1069关押罪犯
    CODEVS 1067 机器翻译
    洛谷 P1417 烹调方案
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3111304.html
Copyright © 2020-2023  润新知