zoukankan      html  css  js  c++  java
  • linux C孤儿进程以及进程回收

    • 上机环境linux mint下 Qt5.11
    • 一例孤儿进程代码的演示
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<fcntl.h>
    int main()
    {
        pid_t pid;
        pid =fork();
        if(pid==0)
        {
            while(1)
            {
                printf("i'm child=%d, parent=%d
    ",getpid(),getppid());
                sleep(1);
            }
        }
        else if(pid==-1)
        {
            perror("process failed!");
            exit(1);
        }
        else
        {
            printf("i'm the master process %d
    ",getpid());
            sleep(10);
            printf("master process %d died
    ",getpid());
        }
        return 0;
    }

    输出结果:

    由此可见,进程13345的父进程结束后,变为孤儿进程,其父进程转为1365

    • 给僵尸进程下的定义
    子进程结束时,父进程会受到SIGCHILD信号。如果没有收到,也没有执行wait()子进程,那么子进程虽然终止,但还是会在内核中占有表项(PCB依然存在),此时子进程就被称作僵尸进程
    • 避免僵尸进程的方法
    父进程要处理SIGCHILD信号忽略(忽略也是种处理哦)或者捕捉它,或者等待子进程结束。
    如果父进程先于子进程结束,那么子进程的终止将转交给init进程处理
    • waitpid((int)子进程号,(int)状态码,阻塞模式)
    #include <stdio.h>
    #include<sys/wait.h>
    #include<stdlib.h>
    #include<signal.h>
    #include<unistd.h>
    
    int main()
    {
        pid_t pid;
        int status;
        int retval;
        pid=fork();
        if(pid==-1)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        else if(pid==0)
        {
            puts("child process launched
    ");
            sleep(3000);
            exit(EXIT_SUCCESS);
        }
        else{
            if(waitpid(pid,&status,WNOHANG)==0)//exit process without block
            {
                retval=kill(pid,SIGKILL);//跟信号有关的系统调用,一如kill
                if(retval)
                {
                    puts("kill failed");
                    perror("failed");
                }
                else
                {
                    printf("%d has been killed
    ",pid);
                }
            }
        }
    }
    • waitpid函数第一个参数取值范围详解
    关键词:等待回收
    pid<-1 如果子进程的组进程号是pid的绝对值,那么这些子进程都会被父进程等待回收
    pid=-1等待任何子进程相当于wait()
    pid=0进程组码与目前进程相同的子进程
    pid>0识别码为pid的子进程
    • sigaction
       struct sigaction
          {
              void (*sa_handler)(int);//信号处理函数1
              void(*sa_sigaction)(int,siginfo_t *,void*);//信号处理函数2
              sigset_t sa_mask;//信号处理函数执行期间需要屏蔽的信号,确保该信号不会再发生,例如正在处理信号A,如果又收到信号A,那么视同就是当前处理的这个新号A,这时,新到的信号A放入进程的信号掩码sa_mask
              int sa_flags;//指定信号处理行为,当包含SA_SIGINFO时,使用该系处理函数,否则使用SA_HANDLER系列处理函数
              void (*sa_restorer)(void);//已废弃不再使用,仅仅用作占位
          }
    • sa_flags  是下列信号处理行为的“按位或”组合
    SA_START 被信号打断的系统调用重新发起
    SA_NOCLDSTOP父进程在他的子进程暂停或继续运行时不会收到SIGCHILD信号
    SA_NOCLDWAIT使父进程在子进程退出时不会收到SIGCHILD信号,这种情况下子进程不会成为僵尸进程
    SA_NODEFER对信号的屏蔽无效,在信号处理期间仍能发出这个新号
    SA_SIGINFO使用sa_sigaction而不是sa_handler作为信号处理函数
    • 用例:sigaction函数,使用SA_HANDLER方法---这意味着,我们使用自定义的函数来处理信号
    • 自定义信号处理函数sig_usr
    static void sig_usr(int signum)
    {
        if(signum==SIGUSR1)
        {
            puts("sigusr1 received
    ");
        }
        else if(signum==SIGUSR2)
        {
            puts("sigusr2 received
    ");
        }
        else
        {
            puts("bad luck!
    ");
        }
    }
    • 主函数调用
    int main()
    {
        int n;//n用于返回read()调用后的返回值
        struct sigaction sa_method;
        char buf[512];//栈上声明个字符数组变量,用于存放输入的命令
        sa_method.sa_flags=0;
        sa_method.sa_handler=sig_usr;//表示使用自定义的信号处理函数
        //SIGUSR1 SIGUSR2是系统预留给程序员玩的两个信号
        sigaction(SIGUSR1,&sa_method,NULL);
        sigaction(SIGUSR2,&sa_method,NULL);
        printf("当前进程号是:%d
    ",getpid());
        while(1)
        {
            //读取文件描述符STDIN_FILENO
         //耐人寻味的read用法,参数一是要读取的文件描述符,参数二是要读取的数据类型大小,代码中的buf是字符数组的首元素大小,511是指一次最多可以读取511个首元素大小的量
            if((n=read(STDIN_FILENO,buf,511))==-1)//n如果大于0,是返回读取的字节数,-1代表读取失败,0代表没有读取到任何东西
            {
                if(errno==EINTR)
                {
                    printf("读取出现问题,被信号中断 
    ");
                }
            }
            else
            {
                buf[n]='';
                printf("%d bytes read: %s
    ",n,buf);
            }
        }
         return 0;
    
    }

    运行过程

     使用SIGUSR1对进程进行扰断

     结果

     运行过程2

     使用SIGUSR2扰断

    结果

  • 相关阅读:
    mysql中bigint、int、mediumint、smallint 和 tinyint的取值范围
    centos6.5下安装samba服务器与配置
    centos 6.5 安装图形界面【转】
    Linux 下添加用户,修改权限
    Linux下自动调整时间和时区与Internet时间同步
    C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
    Unity脚步之NetworkBehaviour下前进、后退、左右转向的简单移动
    Token 在 Ajax 请求头中,服务端过滤器跨域问题
    【游戏】【暗黑2】重置属性点和技能点
    ASCII
  • 原文地址:https://www.cnblogs.com/saintdingspage/p/12182503.html
Copyright © 2011-2022 走看看