zoukankan      html  css  js  c++  java
  • 第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
    */
  • 相关阅读:
    Android开发 ViewConfiguration View的配置信息类
    Android 开发 倒计时功能 转载
    Android 开发 关于7.0 FileUriExposedException异常 详解
    Android 开发 实现文本搜索功能
    Android 开发 Activity里获取View的宽度和高度 转载
    Android 开发 存储目录的详解
    Android 开发 Fresco框架点击小图显示全屏大图实现 ZoomableDraweeView
    Android 开发 将window变暗
    Android 开发 DisplayMetrics获取Android设备的屏幕高宽与其他信息
    Android 开发 DP、PX、SP转换详解
  • 原文地址:https://www.cnblogs.com/5iedu/p/6358482.html
Copyright © 2011-2022 走看看