-
2020-12-24 19:48:52更多相关内容
-
浅谈阻塞和非阻塞语句的本质区别
2020-10-22 14:19:52Verilog HDL适合算法级,寄存器级,逻辑级,门级和版图级等各个层次的设计和描述。Verilog HDL进行设计最大的优点是其工艺无关性。这使得工程师在功能设计,逻辑验证阶段可以不必过多考虑门级及工艺实现的具体细节,... -
java 中同步、异步、阻塞和非阻塞区别详解
2020-08-30 19:20:00主要介绍了java 中同步、异步、阻塞和非阻塞区别详解的相关资料,需要的朋友可以参考下 -
简述JAVA同步、异步、阻塞和非阻塞之间的区别
2020-08-18 17:13:48主要介绍了JAVA同步、异步、阻塞和非阻塞之间的区别,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下 -
java 同步、异步、阻塞和非阻塞分析
2020-08-31 11:15:38主要介绍了java 同步、异步、阻塞和非阻塞分析的相关资料,需要的朋友可以参考下 -
Linux设备驱动中的阻塞和非阻塞I/O
2021-01-20 14:56:05写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说是对I/O操作的两种不同的方式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式。 一、基本概念: 阻塞操作:是指在执行设备... -
verilog HDL 的阻塞和非阻塞语句分析
2020-08-14 05:23:57阻塞和非阻塞语句作为verilog HDL语言的最大难点之一,一直困扰着FPGA设计者,即使是一个颇富经验的设计工程师,也很容易在这个点上犯下一些不必要的错误。阻塞和非阻塞可以说是血脉相连,但是又有着本质的差别。... -
Linux下的Socket编程实例(阻塞和非阻塞)
2015-06-05 14:48:27Linux下基于C/C++的Socket的阻塞和异步编程实例 -
跟着我从零开始入门FPGA之(阻塞和非阻塞)
2020-08-21 14:41:25述阻塞和非阻塞 -
windows的阻塞和非阻塞Socket编程
2019-03-19 01:46:09NULL 博文链接:https://daojin.iteye.com/blog/720402 -
阻塞和非阻塞
2018-07-02 23:10:16在介绍阻塞和非阻塞之前,我们先来了解一下多线程间一个重要的概念——临界区。临界区——一种公有的资源或者共享数据,它可以被多个线程使用。临界区资源一次只能被一个线程使用,其它线程必须等待上一个线程执行...在介绍阻塞和非阻塞之前,我们先来了解一下多线程间一个重要的概念——临界区。
临界区——一种公有的资源或者共享数据,它可以被多个线程使用。临界区资源一次只能被一个线程使用,其它线程必须等待上一个线程执行完成之后,才能使用。临界区资源是多线程之间重要保护对象,当临界区资源同时被多个线程访问时,容易出现错误。代码示例:/** * @author php * @date 2018/7/2 */ public class CriticalRegion { //定义1000元 public static Integer money = 1000; public static void main(String[] args) throws InterruptedException { //定义公共资源 CriticalRegion criticalRegion = new CriticalRegion(); //定义10个线程来购物 ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(() -> { criticalRegion.shop(); }); } Thread.sleep(1000); System.out.println("最终还有:" + CriticalRegion.money); executorService.shutdown(); } //我们每次购物使用100块钱 public void shop() { money = money - 100; System.out.println("使用了100元,我还有:" + CriticalRegion.money); } }
执行结果:从中可以看出,多个线程,同时操作临界区资源时,容易导致操作资源错误。在大部分情况下,这是一个很严重的问题。大家可以多执行几次,看看结果有什么不同。
现在,我们修改一下shop()方法,在方法上加上sychronized。执行结果:sychronized可以让临界区资源,一次只能被一个线程访问,从而结果正确。
临界区资源,在使用多线程时,要格外的注意,以免结果千奇百怪。
在我们了解临界区之后,再来了解阻塞和非阻塞的概念。
阻塞和非阻塞通常被用来形容多线程间的相互影响。当一个线程占用了临界区资源,那么其它需要使用这个资源的线程都必须在这个临界区上等待。等待会导致线程挂起,这样就形成了阻塞。如果占用资源的线程一直没有释放资源,那么其它的线程在这个临界区上都不能继续工作。
相反,非阻塞表明多个线程之间的执行是不会相互影响的。
通常,我们使用synchronized关键字,ReentrantLock(重入锁)时,我们得到的线程就是阻塞线程。阻塞线程在执行代码前,都会尝试得到临界区资源的锁,如果得不到,线程就会一直挂起,直到临界区资源释放。 -
深入浅出:Linux设备驱动中的阻塞和非阻塞I/O
2021-01-09 17:16:36写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说是对I/O操作的两种不同的方式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式。 一、基本概念: 阻塞操作 : 是指在执行设备... -
verilog中的阻塞和非阻塞区别
2011-06-01 17:28:09帮助初学者很好认识阻塞和非阻塞的问题,对养成好的编程习惯非常有益 -
详解socket阻塞与非阻塞,同步与异步、I/O模型
2020-08-31 21:41:58主要介绍了详解socket阻塞与非阻塞,同步与异步、I/O模型,socket网络编程中的同步,异步,阻塞式,非阻塞式,有何联系与区别,本文将详细讲诉。 -
浅谈socket同步和异步、阻塞和非阻塞、I/O模型
2021-01-21 15:58:12在进行网络编程时,常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式 同步/异步主要针对C端: 同步:c端发出一个功能调用时,在没有得到结果之前,c端死等结果 例如:普通B/S模式(同步)... -
处理java异步事件的阻塞和非阻塞方法分析
2020-08-25 22:27:55主要介绍了处理java异步事件的阻塞和非阻塞方法分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,阻塞与非阻塞关注的是交互双方是否可以弹性工作。,需要的朋友可以参考下 -
科学知识:同步、异步、阻塞和非阻塞区别
2020-10-24 05:20:04主要介绍了科学知识:同步、异步、阻塞和非阻塞区别,本文分别讲解了这些概念,需要的朋友可以参考下 -
基于VS2010的 TCP协议连接的例子,包括阻塞和非阻塞方式
2019-03-25 14:05:43基于VS2010 使用TCP协议进行网口连接的例子,包括阻塞和非阻塞方式,以及超时设置,使用非阻塞方式进行连接,使用阻塞方式进行收发 -
操作系统阻塞和非阻塞区别.doc
2020-10-16 03:43:10第 PAGE 页码 页码 页 / 总页数 NUMPAGES 总页数 总页数 页 操作系统阻塞和非阻塞区别 学习操作系统的朋友们肯定有学到阻塞和同步具体知识是怎么应用呢下面由我为大家整理了操作系统的同步的相关知识希望对大家有... -
socket阻塞和非阻塞有哪些影响
2018-09-27 20:45:22socket阻塞和非阻塞有哪些不同文章目录
一、阻塞非阻塞概念
- 阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
- 非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者。
- 同步,就是我调用一个功能,该功能没有结束前,我死等结果。
- 异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)。
阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回
同步IO和异步IO的区别就在于: 数据拷贝的时候进程是否阻塞二、socket阻塞和非阻塞有哪些影响
1.建立连接 connect
阻塞方式下,connect首先发送SYN请求到服务器,当客户端收到服务器返回的SYN的确认时,则connect返回,否则的话一直阻塞。
非阻塞方式,connect将启用TCP协议的三次握手,但是connect函数并不等待连接建立好才返回,而是立即返回,返回的错误码为EINPROGRESS,表示正在进行某种过程。
2.接收连接 accept
阻塞模式下调用accept()函数,没有新连接时,进程会进入睡眠状态,直到有可用的连接,才返回。
非阻塞模式下调用accept()函数立即返回,有连接返回客户端套接字描述符。没有新连接时,将返回EWOULDBLOCK错误码,表示本来应该阻塞。
3.读操作 recv/read
阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小。
阻塞模式下调用read(),recv()等读套接字函数会一直阻塞住,直到有数据到来才返回。
当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲区中的数据大于期望读取的字节数时,读取期望读取的字节数,返回实际读取的长度。
非阻塞模式下,不管接收缓冲区中有没有数据,函数调用都离开返回。
- 接收缓冲区中有数据时,与阻塞socket有数据的情况是一样。
- 接收缓冲区中没有数据,则返回-1,errno被置为EWOULDBLOCK,表示该操作本来应该阻塞的,但是由于本socket为非阻塞的socket,因此立刻返回。
非阻塞模式下返回值 < 0 时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,因此需要循环读取数据。
因此,非阻塞的read调用一般这样写:
if ((nread = read(sock_fd, buffer, len)) < 0) { if (errno == EWOULDBLOCK) { return 0; //表示没有读到数据 } else return -1; //表示读取失败 } else return nread; //读到数据长度
读取指定字节数据可封装readn()函数为:
ssize_t readn(int fd, void *vptr, size_t n) { int32 nleft = 0; int32 nread = 0; int8 *pread_buf = NULL; pread_buf = (int8 *)vptr; nleft = n; while (nleft > 0) { nread = recv(fd, (char *)pread_buf, nleft, 0); if (nread < 0) { if (EINTR == errno || EWOULDBLOCK == errno || EAGAIN == errno) { nread = 0; } else { return -1; } } else if (nread == 0) { break; } else { nleft -= nread; pread_buf += nread; } } return (ssize_t)(n - nleft); }
4.写操作 write/send
阻塞与非阻塞write/sned返回值没有区分,都是 <0:出错,=0:连接关闭,>0发送数据大小。
阻塞模式,如果发送缓冲区没有空间或者空间不足的话,write操作会直接阻塞住,如果有足够空间,则拷贝所有数据到发送缓冲区,然后返回。
非阻塞模式下,不管发送缓冲区中有没有空间,函数调用都离开返回。
- 发送缓冲区中有足够空间或者是不足以拷贝所有待发送数据的空间的话,则拷贝前面N个能够容纳的数据,返回实际拷贝的字节数。
- 发送缓冲区没有空间时直接返回-1,errno被置为EWOULDBLOCK表示没有空间可写数据,如果错误号是别的值,则表明发送失败。
非阻塞模式下返回值 < 0时并且 (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的, 因此需要循环发送。
非阻塞的write操作一般写法是:
ssize_t writen(int connfd, const void *pbuf, size_t nums) { int32 nleft = 0; int32 nwritten = 0; char *pwrite_buf = NULL; if ((connfd <= 0) || (NULL == pbuf) || (nums < 0)) { return -1; } pwrite_buf = (char *)pbuf; nleft = nums; while(nleft>0) { if (-1 == (nwritten = send(connfd, pwrite_buf, nleft, MSG_NOSIGNAL))) { if (EINTR == errno || EWOULDBLOCK == errno || EAGAIN == errno) { nwritten = 0; } else { errorf("%s,%d, Send() -1, 0x%x\n", __FILE__, __LINE__, errno); return -1; } } nleft -= nwritten; pwrite_buf += nwritten; } return(nums); }
5.简单小结
阻塞socket容易存在的问题:
- connect/accept/write导致线程阻塞。(服务关闭/重启线程无法退出)
- recv读数据长度不确定。(不能保证读取完整数据,导致无法解析)
非阻塞的socket
- 在建立连接时要兼容处理返回EINPROGRESS情况
- 在接收连接、读操作、写操作时要兼容处理返回EWOULDBLOCK错误码的情况
以上情况并非连接异常,而是网络延时或者套接字缓冲区满造成的,一般不宜做异常处理(如返回异常关闭套接字)
使用建议:
- 使用阻塞socket,通过select等IO复用模型可实现socket阻塞的非阻塞调用。(解决线程阻塞问题)
- 读写接口:套用封装好的readn/writen函数。(指定时间读不到数据/读不到指定数据算作异常)
三、设置套接字阻塞或非阻塞
1.生成socket时设置
socket函数创建socket默认是阻塞的,也可以增加选项将socket设置为非阻塞的:int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
2.使用fcntl设置
//设置套接字非阻塞 if (fcntl(sock_v4, F_SETFL, fcntl(sock_v4, F_GETFL) | O_NONBLOCK) == -1) { printf( "set sockfd nonblock -1, errno=%d\n", errno); //fcntl返回-1表示失败 }
2.使用ioctl设置
int b_on = 1; ioctl (fd, FIONBIO, &b_on);
针对fcntl函数可做如下封装:
/** @fn set_nonblock(int32 sock_fd, bool b_set) * @brief 设置socket fd为阻塞模式或者非阻塞模式 * @param[in] sock_fd 已经连接成功的连接fd。范围:大于0 * @param[in] b_set 是否设置为非阻塞模式。0-否,非0-是; * @param[out] 无 * @return 成功返回0;失败返回-1 */ int set_nonblock(int32 sock_fd, bool b_set) { int32 flags = 0; flags = fcntl(sock_fd, F_GETFL, 0); if (-1 == flags) { printf("get sockfd flag -1, errno=%d\n", errno); return -1; } if (b_set) { if (fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK) == -1) { printf("set sockfd nonblock -1, errno=%d\n", errno); return -1; } } else { if (fcntl(sock_fd, F_SETFL, flags & (~O_NONBLOCK)) == -1) { printf("set sockfd nonblock -1, errno=%d\n", errno); return -1; } } return 0; }
四、Linux fcntl函数介绍
功能描述:根据文件描述词来操作文件的特性。
fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性。头文件:
#include <unistd.h> #include <fcntl.h>
函数原型:
int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock);
参数:
fd:文件描述词。 cmd:操作命令。 arg:供命令使用的参数。 lock:同上。
描述:
fcntl()针对(文件)描述符提供控制。参数fd是被参数cmd操作(如下面的描述)的描述符。针对cmd的值,fcntl能够接受第三个参数arg。返回值: 与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。
下列三个命令有特定返回值:F_DUPFD,F_GETFD,F_GETFL以及F_GETOWN。
F_DUPFD 返回新的文件描述符
F_GETFD 返回相应标志
F_GETFL , F_GETOWN 返回一个正的进程ID或负的进程组IDfcntl函数有5种功能:
- 复制一个现有的描述符(cmd=F_DUPFD).
- 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).
- 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).
- 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).
- 获得/设置记录锁(cmd=F_GETLK , F_SETLK或F_SETLKW).
cmd 选项:
F_DUPFD:返回一个如下描述的(文件)描述符:
(1)最小的大于或等于arg的一个可用的描述符
(2)与原始操作符一样的某对象的引用
(3)如果对象是文件(file)的话,返回一个新的描述符,这个描述符与arg共享相同的偏移量(offset)
(4)相同的访问模式(读,写或读/写)
(5)相同的文件状态标志(如:两个文件描述符共享相同的状态标志)
(6)与新的文件描述符结合在一起的close-on-exec标志被设置成交叉式访问execve(2)的系统调用
F_GETFD:取得与文件描述符fd联合close-on-exec标志,类似FD_CLOEXEC.如果返回值和FD_CLOEXEC进行与运算结果是0的话,文件保持交叉式访问exec(), 否则如果通过exec运行的话,文件将被关闭(arg被忽略)
F_SETFD:设置close-on-exec旗标。该旗标以参数arg的FD_CLOEXEC位决定。
F_GETFL:取得fd的文件状态标志,如同下面的描述一样(arg被忽略)
F_SETFL:设置给arg描述符状态标志,可以更改的几个标志是:O_APPEND, O_NONBLOCK,O_SYNC和O_ASYNC。
F_GETOWN:取得当前正在接收SIGIO或者SIGURG信号的进程id或进程组id,进程组id返回成负值(arg被忽略)
F_SETOWN:设置将接收SIGIO和SIGURG信号的进程id或进程组id,进程组id通过提供负值的arg来说明,否则,arg将被认为是进程idF_GETFL和F_SETFL的标志如下面的描述:
O_NONBLOCK:非阻塞I/O;如果read(2)调用没有可读取的数据,或者如果write(2)操作将阻塞,read或write调用返回-1和EAGAIN错误 O_APPEND :强制每次写(write)操作都添加在文件大的末尾,相当于open(2)的O_APPEND标志
O_DIRECT :最小化或去掉reading和writing的缓存影响.系统将企图避免缓存你的读或写的数据.
如果不能够避免缓存,那么它将最小化已经被缓存了的数 据造成的影响.如果这个标志用的不够好,将大大的降低性能
O_ASYNC :当I/O可用的时候,允许SIGIO信号发送到进程组,例如:当有数据可以读的时候注意: 在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现在的标志值,然后按照希望修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。
五、参考资料
关于socket阻塞与非阻塞情况下的recv、send、read、write返回值
https://www.cnblogs.com/longingforlife/p/3289976.html -
Linux UDP socket 设置为的非阻塞模式与阻塞模式区别
2020-09-15 11:25:33主要介绍了Linux UDP socket 设置为的非阻塞模式与阻塞模式区别的相关资料,需要的朋友可以参考下 -
tornado-couchdb:一个 Python 模块,提供阻塞和非阻塞(异步)客户端以使用 Tornado 的 httpclient 访问 ...
2021-06-01 15:44:17使用 Tornado 的 httpclient 的 CouchDB 的阻塞和非阻塞(异步)客户端 这个 Python 模块包装了 CouchDB HTTP REST API 并定义了一个通用接口,用于在 CouchDB 上进行阻塞和非阻塞操作。 安装 使用pip安装: pip ... -
PHP阻塞锁和非阻塞锁机制
2019-08-07 18:48:46PHP阻塞锁和非阻塞锁机制,内置解决并发锁重复执行的方案。目前支持文件、Redis、Memcache、Memcached。 -
串口通信非阻塞
2018-08-24 16:51:15串口通信非阻塞方式,发送数据,接收数据并保存到文件(当间隔n毫秒没有再收到数据表示一次接收完毕,将数据保存到文件) -
java 同步、异步、阻塞和非阻塞分析.docx
2022-01-13 11:02:34java 同步、异步、阻塞和非阻塞分析.docx -
FPGA阻塞和非阻塞赋值的不同
2017-12-04 12:52:24FPGA阻塞和非阻塞赋值的不同,详细的介绍了阻塞和非阻塞赋值的差异,内附例子,包懂。 -
阻塞和非阻塞的区别(干货!!!)
2021-03-22 11:24:35阻塞和非阻塞阻塞非阻塞区别 阻塞 为了完成一个功能,发起一个调用,如果不具备条件的话则一直等待,直到具备条件则完成 非阻塞 为了完成一个功能,发起一个调用,具备条件直接输出,不具备条件直接报错返回 区别 其实就... -
网络编程 read 阻塞和非阻塞下的区别
2019-04-20 23:21:062,read 阻塞和非阻塞下的区别: 阻塞下 原则是在不超过指定的长度下,有多少读多少,没有数据则一直等待,有可能会被信号中断。 比如,对端write写了10字节,本端read 读20字节,则此时read 直接返回,... -
select函数的阻塞和非阻塞态理解(实践总结)
2020-06-15 16:34:58int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,...select函数的阻塞和非阻塞主要看最后一个参数 timeout超时时间的值,timeout的取值决定了select的三种状态: 1、timeout传........