并发服务器的实现
- 多进程服务器:通过创建多个进程提供服务
- 多路复用服务器:通过捆绑并统一管理IO对象提供服务。
- 多线程服务器:通过生成与客户端等量的线程提供服务。、
理解进程process
定义:占用内存空间的正在运行的程序。
CPU核和进程数:1个CPU 中可能包含多个运算设备( 核 )。核的个数与可同时运行的进程数相同。相反,若进程数超过核数,进程将分时使用 CPU 资源。但因为CPU 运转速度极快,我们会感到所有进程同时运行。。
进程ID:所有进程都会从操作系统分配到ID。其值为大于2的整数,1要分配给操作系统启动后的首个进程。
调用fork函数创建进程
#include<unisted.h>
pid_t fork(void);
fork函数创建调用的进程副本。
父进程fork函数返回子进程ID,子进程返回0。
进程和僵尸进程
进程完成工作后(执行完mian函数)应被销毁,但有时这些进程将编程僵尸进程,占用系统中重要资源。
产生僵尸进程的原因:1、传递参数并调用exit函数;2、mian函数中执行return语句并返回值。
向exit函数传递的参数值和main函数的retum语句返回的值都会传递给操作系统。而操作系统不会销毁子进程,直到把这些值传递给产生该子进程的父进程。处在这种状态下的进程就是僵尸进程。也就是说,将子进程变成僵尸进程的正是操作系统。
“应该向创建子进程的父进程传递子进程的exit参数值戒return语句的返回值。”
只有父进程主动发起请求(函数调用)时,操作系统才会传递这些值。换言之,如果父进程未主动要求获得子进程的结束状态值,操作系统将一直保存,并让子进程长时间处于僵尸进程状态。。
销毁僵尸进程1:wait函数
父进程应主动请求获取子进程的返回值
#include<sys/wait.h>
pid_t wait(int *statloc);
因为子进程函数参数指向单元还包含其他信息,因此要通过下列宏分离:
WIFEXITED子进程正常终止时返回真,WEXITSTATUS返回子进程返回值。即,向wait函数传递变量status的地址时,调用wait函数应编写代码:
if(WIFEXITED){
puts("Normal termination!");
print("child pass num:%d",WEIXTSTATUS(status));
}
销毁僵尸进程2:waitpid函数
#include<sys/wait.h>
pid_t waitpid(pid_t pid, int *statloc, int options);
信号处理
子进程何时终止?父进程和子进程一样繁忙,不能只调用waitpid函数等待子进程终止。
向操作系统求助子进程终止识别主体是操作系统。若操作系统能传递信息有助于构建高效的程序。引入信号处理机制。
信号与singnal函数,进程发现自己的子进程结束时,请求操作系统调用特定函数。
#include<singnal.h>
void (*signal(int signo, void(*func)(int)))(int);
待续.................................................