多进程服务器

进程的概念及应用

进程:占用内存空间正在运行的程序
CPU核:CPU核的个数与运行的进程数相同,若进程超过核数,进程将分时使用CPU资源.(cpu运算速度极快,所以平时感觉所有进程好像是在同时运行)
查看进程:ps au

并发服务器的实现方法
  • 多进程服务器:通过创建多个进程提供服务
  • 多路复用服务器:通过捆绑并统一管理I/O对象提供服务
  • 多线程服务器:通过生成与客户端等量的线程提供服务
创建进程

使用fork()函数创建进程,它将会创建调用的进程副本,会复制正在运行的父进程为一个全新的子进程,2个进程都将执行fork函数调用后的语句

父进程:fork函数返回子进程ID(原进程)
子进程:fork函数返回0

#include <stdio.h>
#include <unistd.h>

int gval = 10;
int main(int argc, char *argv[])
{
        pid_t pid;
        int lval = 20;
        gval++, lval += 5;

        pid = fork();
        if(pid == 0)    //这是子进程
        {
                gval += 2, lval += 2;
        } else {
                gval -= 2, lval -= 2;
        }

        if(0 == pid) {
                printf("Child Proc: [%d, %d]\n", gval, lval);
        } else {
                printf("Parent Proc: [%d, %d]\n", gval, lval);
        }
        return 0;
}

以上例程编译运行结果:

Parent Proc: [9, 23]
Child Proc: [13, 27]

可以看出运行fork创建进程后,父子进程拥有完全独立的内存结构。

僵尸进程

进程工作完成后(main函数中的程序执行完成后)应该被销毁,但有时这些程序变成僵尸进程,占用系统中的重要资源,这种状态下的进程称为僵尸进程。

产生僵尸进程的原因:
向exit函数传递的值和main函数的return语句传递的值都会传递给操作系统,而操作系统不会销毁子进程,直到把这些值传递给产生子进程的父进程,处在这种状态下的进程就是僵尸进程,也就是说正是操作系统将子进程变成了僵尸进程。如何销毁:"应该向创建子进程的父进程传递子进程的return语句返回值或者exit语句的参数 "
如果父进程未主要要求获取子进程的状态值,操作系统则一直保存,让子进程一直处于僵尸进程,也就是说谁创造的孩子,谁负责带走。

//vim zombie.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
        pid_t pid = fork();

        if(pid == 0){   //子进程
                puts("我是子进程");
        } else {
                printf("我是父进程\n我的进程ID为%d", pid);
                sleep(10);
        }

        if(pid == 0)
                puts("结束子进程\n");
        else
                puts("结束父进程\n");
        return 0;
}


[root@11_centos C]# gcc zombie.c -o zombie
[root@11_centos C]# ./zombie
我是父进程  
我是子进程  
结束子进程  

我的进程ID为32010
结束父进程

//在父进程sleep的过程中通过ps au可以查看到子进程并未结束,而是等父进程全部完成后,子进程才真正销毁。
通过wait销毁僵尸进程
//vim wait.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
        int status;
        pid_t pid = fork();

        if(pid==0) {
                return 3;
        } else {
                printf("子进程的进程ID:%d\n", pid);
                pid=fork();
                if(pid == 0)
                {
                        exit(7);
                } else {
                        printf("子进程的进程ID:%d\n", pid);
                        wait(&status);
                        if(WIFEXITED(status)) {
                                printf("子进程1终止:%d\n", WEXITSTATUS(status));
                        }

                        wait(&status);
                        if(WIFEXITED(status)) {
                                printf("子进程2终止:%d\n", WEXITSTATUS(status));
                        }
                        sleep(20);
                }
        }
        return 0;
}

[root@0_11_centos C]# ./wait 
子进程的进程ID:1973
子进程的进程ID:1974
子进程1终止:7
子进程2终止:3

//这就是wait函数消灭僵尸进程的方法,调用wait函数时,如果没有已终止的子进程,,那么程序将会阻塞直到有子进程终止,所以要慎重使用。

WIFEXITED   子进程正常终止时返回 true   
WEXITSTATUS     返回子进程终止时返回的值
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值