zoukankan      html  css  js  c++  java
  • 非阻塞IO与异步IO

    一、非阻塞IO的轮询读写

    ---如果当前进程有多个输入终端和多个输出终端呢?
    while((n=read(STDIN_FILENO,buf,buf_size))>0){
       if(write(STDOUT_FILENO,buf,n)!=n)
         err_sys("write_error") }
    1、以上结构可以看出,当前进程具有一个输入终端(文件)和一个输出终端(文件)
    会很有可能会发生阻塞。降低了程序的吞吐量,可以采用非阻塞IO解决。
    2、如果当前进程有多个输入或者输出呢?
    ---可以考虑利用多个线程来解决,线程同步的复杂性,
    ---可以考虑多进程解决,同样存在父子进程之间的信号同步问题

    依然利用一个进程,利用非阻塞的文件描述符,遍历每个文件描述符号进行非阻塞IO,缺点是浪费CPU资源。

    二、异步IO

     非阻塞IO并不是异步IO,切记!!!!!
     非阻塞IO只是调用时,函数会立刻或延迟返回,当条件不满足时,不会一直阻塞。
     异步IO是指将当前进程告诉内核,我对哪个文件描述符的读/写感兴趣,请在条件满足时通过信号告诉我,
     我去利用预先定义的函数去处理。避免了轮询,节省CPU资源。
     但同样存在一些问题:
     1、设备范围有限制,可能只对网络或终端设备文件描述符号有效,针对类似设备才会有信号
     2、条件满足信号对整个进程只有一个,与进程打开的文件描述符数量相比远远不够,为了区分是哪一个描述符准备好了
       ,仍然需要将这两个描述符设置为非阻塞的,非阻塞IO尝试轮询。
    三、select/poll/pselect
     针对异步IO的问题,系统提供了IO多路转接。
     select(int maxfdcode,fd_set * readfds,fd_set * writefds,
         fd_set * exceptfds,struct timeval *tvptr)
     (一)原理
      select我们需要告诉内核:
      1、我们关心的文件描述符
      2、对每个描述符,我们关心的条件,是读条件满足还是写条件满足,还是异常条件满足
      3、我们获取条件满足的信息,愿意等待多长时间
      从select返回后,内核会告诉我们:
      1、已经准备好的描述符总数量
      2、对于读写或异常这三个条件中的每一个,哪些描述符已经准备好
     利用以上返回消息,就可以调用相应的IO函数,一般是read/write,因为确信该函数不会阻塞。

     (二)参数解释
    
    
      2、fd_set:可以理解为一个文件描述符位列表,位置索引就是文件描述符编号。
                如果对某个文件描述符感兴趣就设置相应编号索引对应的位为1。
                当条件满足时,内核会设置相应的位为0,当返回时,我们就可以判断出是哪一个描述符准备好了。
      1、maxfdcode:是我们感兴趣的描述符最大编号+1,因为是从0开始的。目的是减少内核扫描的范围。
      3、tvptr:如果为NULL,永久等待;如果为0,立即返回不等待;如果》0,就是等待指定时间后返回,无论是否有满足条件
               存在。
      4、返回值:0表示没有满足条件存在,大于0表示有满足条件存在,-1表示有错
      5、如果fd_set都设置为NULL,等加于sleep,精度更高

     (三)感兴趣文件描述符设置

      FD_ISSET(int fd,fd_set *fds):判断一个文件描述符,是否依然在描述符号条件集合中打开着或者说是条件不满足。
      FD_ZERO(fd_set *fds):清零,需要重新注册感兴趣的文件描述符。第一步就是要作的。
      FD_SET(int fd,fd_set *fds):注册感兴趣条件的文件描述符
      FD_ClR(int fd,fd_set *fds):注销感兴趣条件的文件描述符
      (四、poll)
      利用一个描述符列表,代替三个条件列表,更简单
      列表中每个元素是一个数据结构:描述符编号,兴趣事件集合,当前发生的事件


    四、再论异步IO,重点asio
       int aio_read(struct aiocb *aiocb)
       int aio_write(struct aiocb *aiocb)
       --成功返回操作被系统放入操作请求队列中
       --次(const struct aiocb *aiocb)--返回同步操作的完成状态 0-ok -1-fail EINPROGRESS-处理中
       --aio_return(const struct aiocb *aiocb)--利用上步骤判断,同步操作成功后调用一次,
                                                返回read/write正确调用的返回值(比如读取的字节数量),出错返回-1
       --aio_suspend(struct aiocb *aiocbstruct aiocb[] * aiocbs,nsize,timeout)
                                              --等待异步IO的完成。如果超时没有任何完成,那么返回-1,errno-EAGAIN
                                               -任何一个完成,都返回0
                                               -都完成直接返回
       --aio_cancel(int fd,const struct aiocb *aiocbstruct aiocb * aiocb)--调用后,利用aio_error检查,发回ECANCELEDconst struct aiocb *aiocb
                   struct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocb)

       可以后跟 aio_fsync(int op,struct aiocb *aiocb)同步或者异步同步文件到存储
       (一) 参数aiocb
       
       

       

    五、更狠的列表IO,批量操作,异步通知
       int lio_listio(mode,aiocb[] *aiocbs,nsize,struct sigevent sigevent)
        --aio控制块中的aio_lio_opcode会表明当前的动作,是读还是写,如果是读,那么就会去调用aio_read方法,写同理。
        --mode 决定是否异步,如果是NOWIAT,那么立即返回,IO请求入队
        --sigevent是在列表中所有IO完成后,才会得到通知调用,这不会妨碍各个IO请求的异步通知,适合于完成后作一些处理
    const struct aiocb *aiocb
     
    
    
  • 相关阅读:
    Java 项目运用个人看法(简写)
    windows 搭建Solr连接数据库
    总结2016年,计划2017
    如何解决,自己认为特别难的问题?(文摘)
    spring -quartz 定时任务多任务配置
    (转) java Timer 定时每天凌晨1点执行任务
    spring多数据源切换,写入报错的问题
    如何合理和有效的进行数据库设计
    Main方法定点执行线程任务
    莫辜负当下,莫悔恨过去,莫打扰错过的人
  • 原文地址:https://www.cnblogs.com/justart/p/7805548.html
Copyright © 2011-2022 走看看