[C++ 网络协议] 多进程服务器端

本文详细介绍了多进程服务器的工作原理,包括进程的概念、创建进程(如fork函数)、进程销毁、进程间的通信(如管道)以及信号处理。特别讨论了在C++中实现简单多进程服务器的代码示例,指出了多进程服务器端的优缺点,并提到了通过分割TCP I/O来提升性能的策略。
摘要由CSDN通过智能技术生成

具有代表性的并发服务器端实现模型和方法:

多进程服务器:通过创建多个进程提供服务。✔

多路复用服务器:通过捆绑并统一管理I/O对象提供服务。

多线程服务器:通过生成与客户端等量的线程提供服务。

目录

1. 进程的概念及应用

1.1 什么是进程?

1.2 创建进程

1.2.1 进程ID

1.2.2 fork函数(创建进程)

1.2.3 僵尸进程(为什么要进行进程销毁)

1.2.4 wait函数(销毁进程,阻塞)

1.2.5 waitpid函数(销毁进程,无阻塞)

1.3 进程间的通信

1.3.1 通过管道(PIPE)实现进程间的通信

2. 信号处理

2.1 signal函数(旧版本,只适用于旧版本UNIX系统)

2.2 sigaction函数(新版本,所有UNIX操作系统都一样,更稳定)

3. 实现简单的多进程服务端

3.1 代码

3.2 fork函数复制文件操作符

3.3 多进程可服务器端的缺点

4. 分割TCP的I/O程序(实现多进程客户端的一种模型)


1. 进程的概念及应用

1.1 什么是进程?

进程:占用内存空间的正在运行的程序

从操作系统的角度看,进程是程序流的基本单位。若创建多个进程,则操作系统将同时运行。有时一个程序运行过程中也会产生多个进程,多进程服务器端就是其中的代表。

CPU核的个数与进程数:

         拥有2个运算设备的CPU称作双核CPU,拥有4个运算器的称作四核CPU。也就是说,1个CPU可能包含有多个运算设备(核),核的个数与可同时运行的进程数相同。如果进程数超过了核,那么进程将分时使用CPU资源,但因为CPU运算很快,所以我们会觉得所有进程都同时在运行。

1.2 创建进程

1.2.1 进程ID

每个进程都会从操作系统中分配到一个ID,这个ID就是“进程ID”,进程ID的值为大于2的整数,因为1要分配给操作系统启动后的首个进程(协助操作系统的进程),因此用户无法得到ID为1的进程。

Linux中查看所有进程的命令: ps au

1.2.2 fork函数(创建进程)

#include<unistd.h>

pid_t fork();
成功返回进程ID,失败返回-1

fork函数: 将创建基于当前运行的,调用fork函数的进程的副本(内存空间内容完全相同且互相独立)。此进程为父进程,其副本为子进程。两个进程都将执行fork函数调用后的语句(准确来说,就是从这个fork函数的返回值开始),之后的程序流中,通过fork函数的返回值来区分,当前执行的是子进程还是父进程fork函数只会复制属于进程的资源,而非操作系统的资源。

父进程:fork函数返回子进程ID

子进程:fork函数返回0

如图:

从复制发生点开始,父进程的所有变量的值,在复制发生点处时,是什么值,子进程也就会是什么值,之后两个进程之间的变量值互不影响,如图所示,最终结果:

父进程:gval=11,lval=26

子进程:gval=12,lval=25

1.2.3 僵尸进程(为什么要进行进程销毁)

如果在子进程创建和执行了销毁后父进程没有主动要求获取子进程的结束状态值,那么子进程就会成为僵尸进程,此时的进程只是一个空壳只保留了一些pid,退出状态,运行时间等数据,而其内存空间已经在return和exit的时候释放了,这就是僵尸进程。

僵尸进程产生的原因:

        子进程通过两种方式来终止,一是传递参数并调用exit函数,二是main函数找那个执行return语句并返回值。这两种方式返回的值都会传递给操作系统,但操作系统不会销毁子进程,而是直到把这些值传递给产生该子进程的父进程之后,才会进行销毁。在销毁之前,这期间状态下的进程,就是僵尸进程。所以也可得知,如果要终止子进程,那么就必须向父进程传递exit参数值或return语句的返回值。

那么子进程如何向父进程传递exit参数值或return语句的返回值,来终止自己?

答:通过父进程主动发起请求来调用。如果父进程没有主动要求获取子进程的结束状态值,那么操作系统将一直保存子进程。

为什么要销毁僵尸进程?

答:僵尸进程虽然不占用内存空间,但因其信息还在,会占用进程号,而系统所能拥有的进程号是有限的,所以如果有大量僵尸进程出现的话,则会因为进程号不够用,而导致不能创建新的进程。

1.2.4 wait函数(销毁进程,阻塞)

#include<sys/wait.h>

pid_t wait(int* statloc);    //statloc指向的内存空间,存放有子进程的exit参数值或return语句的返回值等其它信息
成功返回终止的子进程ID,失败返回-1

statloc指向的内存空间,不仅仅存放有子进程的exit参数值或return语句的返回值,还有其它信息,需要通过如下宏进行分离:

WIFEXITED(int statue);
子进程正常终止返回1(真)。
WEXITSTATUS(int statue);
返回子进程的返回值。

所以,使用wait函数的标准流程:

int status;

wait(&status);

if(WIFEXITED(status))    //如果正常终止
{
    std::cout<<"子进程正常终止!"<<std::endl;
    std::cout<<"子进程返回值:"<<WEXITSTATUS(status)<<std::endl;
}

注意:调用wait函数时,如果没有子进程要终止,那么程序将阻塞住,直到有任意一个子进程终止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值