进程组

进程组

(1)进程组,也称之为作业,BSD与1980年前后向UNIX中增加的一个新特性,代表一个或多个进程的集合。每个进程都属于一个进程组,在waitpid函数和kill函数的参数中都曾经使用到,操作系统设计的进程组的概念,是为了简化对多个进程的管理。

当父进程创建子进程的时候,默认子进程与父进程属于同一个进程组,进程组ID等于进程组第一个进程ID(组长进程)。所以,组长进程标识:其进程组ID等于其进程ID.
组长进程可以创建一个进程组,创建该进程组的进程,然后终止,只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。

(2)kill发送给进程组
使用 kill -n -pgid 可以将信号 n 发送到进程组 pgid 中的所有进程。例如命令 kill -9 -4115 表示杀死进程组 4115 中的所有进程。

 

进程组操作函数

1. getgrp函数:获取当前进程的进程组

pid_t getpgrp(void);

 

2. getpgid函数:获取进程的进程组ID

pid_t getpgid(pid_t pid);

分析:

  • 如果pid = 0,那么该函数作用和getpgrp一样

3.  setpgid函数作用:改变进程默认所属的进程组,通常可用来加入一个现有的进程组或新进程组。

int setpgid(pid_t pid, pid_t pgid);

分析:将参数1对应的进程,加入参数2对应的进程组中。

注意:

  • 如改变子进程为新进程组,用fork后,exec前。
  • 权级问题:非root进程只能改变自己创建的子进程,或有权限操作的进程。

ps ajx命令查看系统中的进程,参数a表示不仅列出当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j列出与作业控制相关的信息。

注意:组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。

 

 

1. 测试代码:

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

int main()
{
    pid_t pid;
    if ((pid = fork()) < 0)
    {
        perror("fork");
        exit(1);
    }
    else if (pid == 0)
    {
        printf("child PID = %d\n", getpid());
        printf("child Group ID = %d\n", getpgid(0)); //返回组id
        sleep(7);
        printf("-------Group ID of child  id change to %d\n", getpgid(0));
        exit(0);
    }
    else if (pid > 0)
    {
        sleep(1);
        setpgid(pid, pid); //让子进程自立门户,成为进程组组长,以它的pid为进程组 id

        sleep(13);
        printf("\n");
        printf("parent PID = %d\n", getpid());
        printf("parent's parent PID = %d\n", getppid());
        printf(" parent Group ID = %d\n", getpgid(0));

        sleep(5);
        setpgid(getpid(), getppid());  //改变父进程组id为父进程的父进程
        printf("\n-------Group ID of parent is change to %d\n", getpgid(0));

        while (1);
    }
    return 0;
}

 

输出结果:

 

进程组的应用

posted @ 2019-01-13 18:17  苏格拉底的落泪  阅读(344)  评论(0编辑  收藏  举报