zoukankan      html  css  js  c++  java
  • IO(四)

    Linux中有5种IO模型:

    阻塞式IO
    非阻塞式IO
    IO复用
    信号驱动式IO(SIGIO)
    异步IO(Posix的aio_系列函数)

    阻塞型IO:阻塞式IO是Linux中最基本、最常用的IO模型,指的是可能会使进程永远阻塞的函数,一般表现为:进程或线程调用某个函数,该函数需要满足特定条件才能向下执行
    如果条件不满足,则会使调用进程或线程阻塞,让出CPU控制权,并一直持续到条件满足为止,在Linux中,阻塞式IO一般作为默认属性出现,如mq_receive、sem_wait、sem_post等
    在默认情况下,所有的套接字都是阻塞的,我们以UDP套接字为例来展示阻塞式IO模型。

     进程调用recvfrom接收数据,但由于内核还未准备好,进程就会阻塞;直到内核准备好数据,recvfrom完成数据复制工作,进程才能解除阻塞状态。


    非阻塞型IO:顾名思义,非阻塞式IO不会使调用进程或线程永远阻塞,具体表现为:如果IO操作不能完成,则立即出错返回,调用进程或线程继续向下执行。对于一个给定的描述符,有两种将其指定为非阻塞式IO的方法:调用open创建打开文件时指定O_NONBLOCK标志对于一个已经打开的描述符,调用fcntl改变其属性,为其设置O_NONBLOCK标志。
    #include 
    int fcntl(int fd, int cmd, ... /* int arg */);
    

    IO多路复用(I/O multiplexing):多个进程使用同一个IO流,一旦发现进程指定的一个或者多个描述符可进行无阻塞IO访问时,它就通知该进程。

    多个Sock复用一个IO线程这个功能是在内核+驱动层实现的。

     I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。

    类似:ngnix会有很多链接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。

     select, poll, epoll 都是I/O多路复用的具体的实现,他们出现是有先后顺序的。

    select在1983年BSD UNIX里面实现的

     select流程伪代码如下:

    {
    	select(socket);
    	while(1) 
    	{
    		sockets = select();
    		for(socket in sockets) 
    		{
    			if(can_read(socket)) 
    			{
    				read(socket, buffer);
    				process(buffer);
    			}
    		}
    	}
    }

     具体的API :

    int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
    

    select 被实现以后,很快就暴露出了很多问题。

    · select 会修改传入的参数数组,这个对于一个需要调用很多次的函数,是非常不友好的。

    · select 如果任何一个sock(I/O stream)出现了数据,select 仅仅会返回,但是并不会告诉你是那个sock上有数据,于是你只能自己一个一个的找,10几个sock可能还好,要是几万的sock每次都找一遍。

    · select 只能监视1024个链接,linux 定义在头文件中的,参见FD_SETSIZE。

    · select 不是线程安全的,如果你把一个sock加入到select, 然后突然另外一个线程发现,尼玛,这个sock不用,要收回。对不起,这个select 不支持的,如果你丧心病狂的竟然关掉这个sock, select的标准行为是。。呃。。不可预测的, 这个可是写在文档中的哦.

    于是14年以后(1997年)一帮人又实现了poll, poll 修复了select的很多问题,比如

    · poll 去掉了1024个链接的限制,于是要多少链接呢, 主人你开心就好。

    · poll 从设计上来说,不再修改传入数组,不过这个要看你的平台了

    epoll 可以说是I/O 多路复用最新的一个实现,epoll 修复了poll 和select绝大部分问题, 比如:

    · epoll 现在是线程安全的。 

    · epoll 现在不仅告诉你sock组里面数据,还会告诉你具体哪个sock有数据,你不用自己去找了。

    在这种模型下,如果请求的I/O操作阻塞,且它不是真正阻塞I/O,而是让其中的一个函数等待,在此期间,I/O还能进行其他操作。


    信号驱动I/O模型:在这种模型下,进程要定义一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。这是由内核通知用户何时可以启动一个I/O操作决定的。


    异步I/O模型:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知进程I/O操作何时完成的。现在,并不是所有的系统都支持这种模型。

    smartcat.994
  • 相关阅读:
    101. Symmetric Tree(js)
    100. Same Tree(js)
    99. Recover Binary Search Tree(js)
    98. Validate Binary Search Tree(js)
    97. Interleaving String(js)
    96. Unique Binary Search Trees(js)
    95. Unique Binary Search Trees II(js)
    94. Binary Tree Inorder Traversal(js)
    93. Restore IP Addresses(js)
    92. Reverse Linked List II(js)
  • 原文地址:https://www.cnblogs.com/SmartCat994/p/14028811.html
Copyright © 2011-2022 走看看