深入理解计算机系统-第十二章-并发编程

Posted by Taolee on May 31, 2016

本章以一个简单的echo服务器来阐释并发编程的概念。

1.基于进程的并发编程

基本概念是在父进程中接受客户端连接请求,并创建一个子进程为每一个客户端提供服务。 基本的步骤如下:

  1. 服务器接收客户端的连接请求。
  2. 服务器派生一个子进程为客户端服务。
  3. 服务器接收下一个客户端的请求。 其中至关重要的是服务器每创建一个子进程时,子进程要释放不需要自己使用的资源。而父进程也要释放特定的资源,进而防止连接请求过多导致的服务器存储溢出。

基于进程的并发-服务器接收客户端的连接请求 基于进程的并发-服务器创建子进程和接收下一个请求 基于进程的并发-服务器再次创建子进程和接收下一个请求

基于进程的并发编程的一个迷惑的点是,使用Fork创建子进程时,子进程复制父进程中所有的信息。因此相当于子进程和父进程共享同一套代码。 也就是一套代码要完成不同的功能,那么必须在代码中判断当前自己处在子进程还是父进程中。判断的方法是: fork()函数在父进程中返回子进程的pid,而在子进程中返回0 可以这么写:

if(fork() == 0){
    //子进程中要执行的代码 
}else{
   //父进程中要执行的代码    
}

关于进程的优劣

优点是:父进程继承了子进程的文件表,但是不会继承父进程的用户地址空间。因此不会产生一个进程不小心覆盖了另一个进程的虚拟地址空间的副作用。 缺点是:1) 必须使用显式的IPC进程间通信机制 2)创建进程等的系统开销较大,所以一般会比较慢。

2. 基于IO多路复用的并发编程(有点复杂还没有搞懂)

要处理互相独立的IO事件并且不要互相阻塞的一个方法是,使用select函数,内核会挂起进程,只有在一个或多个IO事件后,系统将控制权转交给应用程序。

函数的原型如下:

#include <unistd.h>
#include <sys/types.h>
int select(int n, fd_set *fdset, NULL, NULL, NULL);

基于IO多路复用的并发事件驱动服务器

优点是:1)一个I/O多路复用的事件驱动服务器是运行在单一进程上下文的,所以每个逻辑流都 能访问该进程的全部地址空间。所以在流之间共享数据比较容易。同时单进程的优点是可以使用GDB等简单的来 调试并发服务器,就像调试顺序程序一样。同时比切换进程的效率要高。 2)但是缺点是编码复杂,而且随着并发粒度的减小,复杂性还会上升。这里的粒度是指每个逻辑流时间片 执行的指令数量。只要某个逻辑流忙于读,那么其他的逻辑流就不可能有进展。基于事件驱动的 另一个重大缺点是他们不能充分利用多核处理器。