进程 进程组 会话的关系及作用

      Linux下的进程本身都是以init为祖先进程的一个树状进程族谱,Init进程就是这个树的根。但是为方便管理有其他层级关系进程们,又在简单的父子关系之外增加了进程组和会话的关系,从而方便进程的管理。当一个用户登录到系统时登录程序就会将登录的shell设置成一个会话首领和组长进程。简单来说是这样的一种关系 会话 > 包括进程组 > 包括进程 。而增加这样的额外关系仅仅是为了方便管理控制所有由关系的进程(作业)。在Linux中一个进程除了是属于他父进程的子进程外他还是一个进程组的成员,而同一进程组有这样一个特点-----信号会被传递到同一进程组的所有进程。

    一般情况下一个进程创建的一个子进程这个子进程就和父进程同属一个进程组,那么如果都是这样的情况那Linux中应该就只有一个进程组。所以这种情况其实是一种特殊情况。这种情况会导致不同用户的进程之间可以发送信号。所以Linux允许进程修改自己或子进程(执行exec前)的进程组和会话组,从而将进程进行又一层的分组管理。进程可以通过调用setpgid来修改自己的进程组

int setpgid(pid_t pid,pid_t pgid);

这个调用必须满足

  • 调用进程不能是当前进程组的首领进程。
  • 调用进程不能是会话首领进程。
  • pid只能是当前调用进程的pid(传入0),或者当前调用进程的子进程(未执行exec调用前),而且因为子进程和父进程的运行顺序不确定通常情况下要在子进程和父进程中同时调用此接口,确保子进程运行之初就在正确的进程组

 

一个进程还可以将自己设置为一个新的会话的新进程组成员通过调用setsid()

pid_t setsid(void);

调用的进程不能是一个进程组的或会话的首领进程,成功时返回新创建的会话的会话ID。

 

     总之会话和进程组常常用于作业控制,比如你的代码你希望他单独成为为一个组可以统一开始或结束,而不受父进程shell的的控制或者影响。反过来会话和进程组的概念也是为了方便shell管理用户的进程的,因为当进程组首领进程结束时进程组还是存在的,其他进程还是在运行的,当时当会话首领进程结束时,会话内的所有进程都会结束(ubantu14.04下测试)。

测试代码

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <error.h>
int main(char argc,char* argv)
{
    pid_t newSid;
    newsid=setsid();
    printf("The new sid is %d\n",newsid);
    while(1)
    {
        sleep(1);    
        printf("I ma Running\n");
    }
    return 0;
}

 

posted @ 2020-05-05 17:35  Little_Village  阅读(1026)  评论(0编辑  收藏  举报