Linux系统网络I/O模型
Linux系统网络I/O模型
几个概念:
从程序的自身角度来看,I/O分为阻塞和非阻塞:
- 阻塞I/O:在进行I/O操作(比如调用read、write、recv、send等系统调用API时)的时候,内核的缓存区里的数据拷贝到用户态的缓存区,若此时内核缓存区里没有数据,则会等待内核把数据准备好,在这个过程中,应用进程/线程处于一种挂起状态,我们看到在程序调用这些API的地方是阻塞的情形,所以称为阻塞I/O。
- 非阻塞I/O:在进行I/O操作(比如调用read、write、recv、send等系统调用API时)的时候,内核的缓存区里的数据拷贝到用户态的缓存区,若此时内核缓存区里没有数据,
也会直接返回
。我们看到进程/线程并没有任何的等待,所以称为非阻塞I/O。
从通信双方响应的方式角度来看,I/O分为同步和异步:
注意:谈论同步和异步,要上升到整个系统(即通信双方)的角度来讨论。
- 同步I/O:请求方发出I/O请求后,一直等待对方处理,等到结果返回,
- 异步I/O:请求方发出I/O请求后,在对方处理结果的时候不需要等待,发出请求后直接返回;等对方处理好了对方会通知请求方。
很明显,同步方式的逻辑和代码都很容易实现,而异步较难实现。举例:你去派出所办身份证,你可以有两种方式:第一种、你告诉派出所的工作人员要办身份证(发出请求),然后等派出所工作人员办理,你在派出所一直等,等了好多天,办好了给你(返回处理结果)。第二种、你告诉派出所的工作人员要身份证(发出请求),并且留了手机号给工作人员
,让办好了给你打电话,然后你去取,这时候你就可以回去了(不需要在等待)。过了好多天给你打电话说办好了,你去取回身份证(返回结果)。
办身份第一种方式就是同步,第二种就是异步。同步很简单,你不用考虑太多,反正就是一直等。但是你就不能离开,因为你离开了,再也找不到你了,因为你没登记任何信息。而异步通过电话号就能找到你,但是多了电话号登记,给你打电话,还有你总共去派出所要跑两趟等这些过程。不管是同步还是异步都能实现,就看你自己选择哪种,哪种适合你,你如果连手机都没有,那你只能选择同步。
阻塞、非阻塞,同步、异步经常放在一起讨论,很容易把人弄晕,但是如果从不同的角度看,很容易就懂了。阻塞、非阻塞从程序自身,进程/线程会不会"堵
"在系统I/O的地方;而同步、异步从整个系统设计,通信双方的角度来看。
异步I/O的方式在编程的时候通常通过向系统注册一个回调函数
,等对方有结果的时候,系统会通过调用这个回调函数的方式通知我们。