• 第7章 进程关系(3)_进程组和组长进程


    3. 进程组和组长进程

    (1)进程组

      ①一个或多个进程的集合;

      ②可以接受同一终端的各种信号,同一个信号发送进程组就等于发送给组中的所有进程

      ③每个进程组有唯一的进程组ID

      ④进程组的消亡要等到组中所有的进程结束

      ⑤kill发送信号组进程组:kill -9 -进程组号注意进程组号前的“-”

    (2)组长进程

      ①每个进程组可以有个组长进程,组长进程的ID就是进程组的ID

      ②组长进程可以创建进程组及该组中的进程。

      ③进程组的创建从第一个进程(组长进程)加入开始

      ④进程组的组号取第一个加入组的进程(组长进程)的编号

    (3)获取或设置进程组ID

    头文件

    #include <unistd.h>

    函数

    pid_t getpgrp(void);  //返回调用进程的进程组ID

    pid_t getpgid(pid_t pid); //进程pid所在进程组的ID,出错返回-1

    int setpgid(pid_t pid, pid_t pgid); //将进程加入到指定的进程组中,其中pid为进程号,pgid为进程组号。成功返回0,出错返回-1。

    功能

    获取或设置进程组ID

    备注

    ①getpgid(0)与getpgid(getpid())等价,都是获得当前进程的进程组ID

    ②第1次调用setpgid,则创建一个进程组,而调用进程成为组长进程。如

    setpgid(getpid(), getpid());//第2个参数为进程组ID,也是组长进程。

    ③②用fork创建一个新进程后子进程默认是和父进程在一个进程组内

    【编程实验】1.进程扇与分组

    //process_swing_group.c

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char* argv[])
    {
        pid_t pid;
        int i = 0;
    
        //创建进程组,组长进程为父进程
        setpgid(getpid(), getpid());
        pid_t group1 = getpgid(getpid()); //获取进程组ID
        pid_t group2;
    
        //构建进程扇
        for(i = 0; i<3; i++) {
            pid = fork();
            if(pid < 0 ){
                perror("fork error");
                exit(1);
            }else if(pid > 0) { //parent process
                //父进程中执行和子进程相同的操作,因为父、子进程
                //谁先被调用未知,所以设置进程组ID时,需要父子进程同时设置
                //以确保不管谁先运行,都能正确将他们分组
                if(i == 0){
                    //将第一个子进程加入到group1中
                    setpgid(pid, group1);
                }
                if(i == 1){
                    //创建进程组,第二个子进程为组长进程
                    setpgid(pid, pid);
                    group2 = getpgid(pid);
                }
                if(i == 2){
                    //第3个子进程加入到group2中
                    setpgid(pid, group2);
                }
                continue; //父进程继续运行,创建新的子进程
            }else{
                if(i == 0){
                    //将第一个子进程加入到group1中
                    setpgid(getpid(), group1);
                }
                if(i == 1){
                    //创建进程组,第二个子进程为组长进程
                    setpgid(getpid(), getpid());
                    group2 = getpgid(getpid());
                }
                if(i == 2){
                    //第3个子进程加入到group2中
                    setpgid(getpid(), group2);
                }
                
                 break; //要构建进扇,子进程须退出。
            }
        }
    
        printf("pid = %d, ppid = %d, pgid = %d
    ", 
                        getpid(), getppid(), getpgid(0));
        
        for(i=0; i<3; i++)
            wait(0);   
    }
    /*输出结果:
    pid = 3196, ppid = 2447, pgid = 3196
    pid = 3198, ppid = 3196, pgid = 3198
    pid = 3197, ppid = 3196, pgid = 3196
    pid = 3199, ppid = 3196, pgid = 3198
    */

    【编程实验】2.进程链与分组

    //process_link_group.c

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char* argv[])
    {
        setpgid(getpid(), getpid());
        pid_t group1 = getpgid(getpid());
    
        pid_t pid;
        int i = 0;
        //构建进程链
        for(i = 0; i<2; i++) {
            pid = fork();
            if(pid < 0 ){
                perror("fork error");
                exit(1);
            }else if(pid > 0) { //parent process
                if(i == 0){
                    //创建进程组2,第1个子进程作为组长进程
                    setpgid(pid, pid);
                }
                if(i == 1){
                    //将第2个子进程加入到group1
                    setpgid(pid, group1);
                }
    
                break;//在进程链,父进程操作完退出循环
            }else{ //child process
                if(i == 0){
                    //创建进程组2,第1个子进程作为组长进程
                    setpgid(getpid(), getpid());
                }
                if(i == 1){
                    //将第2个子进程加入到group1
                    setpgid(getpid(), group1);
                }
    
                continue; //子进程继续创建新的子进程
            }
        }
    
        printf("pid = %d, ppid = %d, pgid = %d
    ",
                      getpid(), getppid(), getpgid(0));
        
        wait(0);
    }
    /*
     pid = 3216, ppid = 2447, pgid = 3216
     pid = 3217, ppid = 3216, pgid = 3217
     pid = 3218, ppid = 3217, pgid = 3216
     */

    【编程实验】3. 操作进程组

    //process_group3.c

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    /*父子进程加入同一进程组*/
    
    //说明:
    //(1)默认即使以下代码中不加入setpgid的操作,fork出来的子进程与父进程仍会默认地属一进程组
    //(2)kill -9 -进程组ID,则父子进程均会收到退出进程的信号
    //(3)如果先kill父进程,则子进程成为孤儿进程,会被1号进程领养
    //(4)如果先kill子进程,则子进程成为僵尸进程。如果再kill父进程,则回收僵尸进程。
    int main(void)
    {
        //创建进程组,父进程作为组长进程
        pid_t pid = fork();
        if(pid < 0){
            perror("fork error");
            exit(1);
        }else if(pid > 0){ //parent process
            //将子进程加入到父进程所在的组
            setpgid(pid, getpgid(getpid()));
        }else{ //child process
            //将子进程加入到父进程所在的组
            setpgid(getpid(), getpgid(getppid()));
        }
    
        printf("pid = %d, ppid = %d, pgid = %d
    ",
                       getpid(), getppid(), getpgid(0));
        pause();//暂停。父子进程都会执行到这里。
    
        return 0;
    }
    /*输出结果:
    pid = 3301, ppid = 2447, pgid = 3301
    pid = 3302, ppid = 3301, pgid = 3301
    */
  • 相关阅读:
    关于面试总结8-http协议相关面试题
    关于面试总结7-linux篇
    关于面试总结6-SQL经典面试题
    关于面试总结5-python笔试题(递归)
    关于面试总结4-python笔试题
    关于面试总结3-SQL查询
    关于面试总结2-SQL学生表
    关于面试总结1-SQL学生表
    浅谈多变量线性回归中的数据规范化
    浅谈KL散度
  • 原文地址:https://www.cnblogs.com/5iedu/p/6358482.html
Copyright © 2020-2023  润新知