通讯架构学习-nginx-(七) 进程基础

fork函数:用来创建进程:
    进程的概念:一个可执行程序(多个进程可以共享一个可执行程序)
    进程:定义为一个可执行程序的实例
在一个进程中,可以用fork创建一个子进程,当该子进程创建时,它从fork指令的下一条开始执行与父进程相同的代码
    说白了:fork函数产生了一个和当前进程完全一样的新进程, 并和当前进程一样从fork中返回
    原来一条执行通路, 变成了两条通路
    之后的代码谁执行不一定
fork函数简单范例:
        
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>

void sig_usr(int signo)
{
    printf("收到了SIGUSR1信号, 进程id为%d\n",getpid());
}


int main()
{
    
    pid_t pid;
    if(signal(SIGUSR1, sig_usr) == SIG_ERR)
    {
        printf("无法捕捉");
        exit(1);
    }
    pid =fork();
    if(pid< 0)
    {
        printf("子进程创建失败\n");
        exit(1);
    }
    for(;;)
    {
        sleep(1);
        printf("休息一秒, 进程id=%d!\n", getpid());
    }
    printf("再见了!\n");
    return 0;
}


在这个代码中,使用strace -e trace=signal -p 父进程pid,跟踪父进程  kill掉子进程,父进程会收到SIGCHILD,
子进程变成了僵尸进程。状态为Z

僵尸进程的产生, 解决, SIGCHILD
僵尸进程的产生:在Unix系统中,一个子进程结束了但是它的父进程还活着
            但是它的父进程没有调用wait/waitpid函数进行额外的处理,那么这个子进程就会变成僵尸进程
僵尸进程:以及被终止,但没有被内核丢掉,因为内核认为父进程可能需要子进程信息。Z+
作为开发者, 坚决不允许僵尸进程。
解决僵尸进程:
    a) kill 掉父进程
    b)重启电脑
    SIGCHILD信号:一个进程被终止或者停止时,这个信号被发送给父进程;
    所以,对源码中有fork行为的进程,我们应该拦截SIGCHILD信号
解决范例:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>

void sig_usr(int signo)
{
    int status;
    switch(signo)
    {
        case SIGUSR1:
            printf("收到了SIGUSR1信号, 进程为%d\n", getpid());
            break;
        case SIGCHLD:
        // waitpid 为了获取子进程的终止状态
        //第一个参数为-1 表示等待任何子进程
        //第二个参数 保存子进程的状态信息
        //第三个参数 提供额外选项, WNOHANG表示不要阻塞, 立即返回
            printf("收到了SIGCHILD信号, 进程id=%d\n", getpid());
            pid_t pid = waitpid(-1, &status, WNOHANG);
            if(pid==0)
            return;
            if(pid==-1)
            return;
            return;
            break;
    }
}

int main()
{
    
    pid_t pid;
    if(signal(SIGUSR1, sig_usr) == SIG_ERR)
    {
        printf("无法捕捉");
        exit(1);
    }
    pid =fork();
    if(pid< 0)
    {
        printf("子进程创建失败\n");
        exit(1);
    }
    for(;;)
    {
        sleep(1);
        printf("休息一秒, 进程id=%d!\n", getpid());
    }
    printf("再见了!\n");
    return 0;
}

fork函数进一步认识:
    fork()产生新进程的速度非常快, fork()产生的新进程并不复制原进程的内存空间,而是和
    原进程(父进程)一起共享一个内存空间,但这个内存空间的特性是“写时复制”也就是说:
    原来的进程和fork() 出来的子进程可以同时,自由的读取内存, 但如果子进程(父进程)对内存
    进行修改的话,那么这个内存就会复制一份给改进程单独使用,以免影响到共享这个内存空间的其他进程

fork代码:
    fork返回两次, 父进程返回一次, 子进程返回一次, 子进程pid==0,
    父进程返回值>0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值