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

    转自:https://www.zhihu.com/question/19732473

    https://blog.csdn.net/mianhuantang848989/article/details/83961337

    1.阻塞与非阻塞

    https://blog.csdn.net/lengxiao1993/article/details/78154467

    1.1 进程间通信

    分别对于进程、对于IO系统调用来说:

    对进程阻塞挺好理解,就是发出一个调用,就由running转换为waiting状态,直到结果返回才执行下一行代码。

    进程间的通信时通过 send()receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计。
    消息的传递有可能是**阻塞的**或**非阻塞的** -- 也被称为**同步**或**异步**的

      • 阻塞式发送(blocking send). 发送方进程会被一直阻塞, 直到消息被接受方进程收到。
      • 非阻塞式发送(nonblocking send)。 发送方进程调用 send() 后, 立即就可以其他操作。
      • 阻塞式接收(blocking receive) 接收方调用 receive() 后一直阻塞, 直到消息到达可用。
      • 非阻塞式接受(nonblocking receive) 接收方调用 receive() 函数后, 要么得到一个有效的结果, 要么得到一个空值, 即不会被阻塞。

    进程通信层面, 阻塞/非阻塞, 同步/异步基本是同义词, 但是需要注意区分讨论的对象是发送方还是接收方。

    • 发送方阻塞/非阻塞(同步/异步)和接收方的阻塞/非阻塞(同步/异步) 是互不影响的。

    //但是非阻塞的意思是,调用了,立马返回了一个结果,然后继续执行?我不太懂,直接返回返回什么?如果后续要用到读取到的数据那岂不是会出错误?非阻塞的话是当前进程/线程继续执行,还是说切换了呢?

    1.2 IO系统调用

     进程发出系统调用后:

    • 可以阻塞式地等待IO 设备的返回结果,阻塞式的调用,使得应用级代码的编写更容易(代码的执!行顺序和编写顺序是一致的)。
    • 也会提供非阻塞I/O 系统调用接口,一个非阻塞调用不会挂起调用程序, 而是会立即返回一个值, 表示有多少bytes 的数据被成功读取(或写入)。

    和非阻塞IO系统调用同等的是异步IO系统调用,但两者并不相等,返回结果不一样。与非阻塞 I/O 系统调用类似,asychronous system call 也是会立即返回, 不会等待 I/O 操作的完成, 应用程序可以继续执行其他的操作, 等到 I/O 操作完成了以后,操作系统会通知调用进程(设置一个用户空间特殊的变量值 或者 触发一个 signal 或者 产生一个软中断 或者 调用应用程序的回调函数)。

    非阻塞IO系统调用和异步IO系统调用的区别:

    • 一个非阻塞I/O 系统调用 read() 操作立即返回的是任何可以立即拿到的数据, 可以是完整的结果, 也可以是不完整的结果, 还可以是一个空值
    • 而异步I/O系统调用 read()结果必须是完整的, 但是这个操作完成的通知可以延迟到将来的一个时间点。

    2.同步与异步

    在进程同步的上下文中,表示send与receive方是否阻塞;

    在IO系统调用中,即进程在发出系统调用后所处的状态,同步的话会阻塞(IO系统调用一般不说同步吧,同步意思就是阻塞?得要等到读取结果之后才进行下一步),异步的话就会继续执行下面的代码。

    3.IO函数

    https://blog.csdn.net/kwinway/article/details/80708878

    3.1 send:

    阻塞与非阻塞send返回值没有区分,都是 <0:出错=0:连接关闭,>0发送数据大小,
    特别:非阻塞模式下返回值 <0时并且 (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的, 继续发送。

    只是阻塞模式下send会阻塞着发送数据,非阻塞模式下如果暂时无法发送数据会返回,不会阻塞着 send,因此需要循环发送。

    3.1.1 errno的解释:

    https://blog.csdn.net/wm_1991/article/details/51858997

    • EINTR:指操作被中断唤醒,需要重新读/写
    • EWOULDBLOCK:用于非阻塞模式,不需要重新读或者写
    • EAGAIN:比较常见的一个错误(比如用在非阻塞操作中),提示再试一次。比如连续做read操作而没有数据可读,此时程序不会阻塞起来等待数据准备就绪返回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。

    3.2 recv:

    返回同上。

    只是阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要 循环读取

    3.3 write/read

    只是阻塞模式下write会阻塞着发送数据;非阻塞模式下如果暂时无法发送数据会返回,不会阻塞着 write,因此需要循环发送。

    只是阻塞模式下read会阻塞着接收数据;非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要 循环读取。

    3.3.1 例子

    https://blog.csdn.net/wm_1991/article/details/51858997

    读数据:

    ssize_t   readn ( int fd, void *vptr, size_t n )
     {
         size_t     nleft;
         ssize_t   nread;
         char       *ptr;
     
        ptr=vptr;
         nleft=n;
     
        while ( nleft>0 )//循环读取
         {
            if ( ( nread = read ( fd,ptr,nleft ) ) < 0 )//读取到fd中
            {
               if ( errno == EINTR )//未读取到,读中断
                  nread = 0;
               else
                  return ( -1 );
            }
            
           nleft-=nread;
            ptr+=nread;
         }
          
        return ( n-nleft );
     }

    写数据:

    ssize_t   writen (  int fd,   const void *ptr,    size_t n  )
     {
         size_t   nleft;
         ssize_t   nwritten;
         const char *ptr;
     
        ptr=vptr;
         nleft=n;
     
        while ( nleft>0 )//循环写数据
         {
            if( ( nwritten=write( fd, ptr, nleft ) )<=0 )
            {
               if( nwritten<0 && errno == EINTR )//写中断,可能是写满了
                  nwritten = 0;
               else
                  return (-1);//其他错误,比如说网络错误
            }
               
              nleft-=nwritten;//写成功
               ptr+=nwritten;
         }
     
        return (n);
     }
  • 相关阅读:
    Linux常用技巧
    Python2 Python3 urllib方法对应
    Python常用技巧
    aix7安装was7、打补丁、更改访问端口、手动启动was、配置was7、部署项目
    微服务解释
    Java集合框架介绍。Java Collection Frameworks = JCF
    从今日起,坚持记录博客。
    java web 监控cpu、内存等。hyperic-sigar
    java线程中如何使用spring依赖注入
    java 下载文件 内容为空。
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/14268956.html
Copyright © 2011-2022 走看看