进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端

摘要:本文主要介绍进程的基本属性,基本属性包括:进程ID、父进程ID、进程组ID、会话和控制终端.

进程基本属性

1.进程ID(PID)

函数定义:

#include <sys/types.h>

#include <unistd.h>

pid_t getpid(void);

函数说明:

每个进程都有一个非负整型表示的唯一进程ID(PID).好比如我们的身份证一样,每个人的身份证号是唯一的.因为进程ID标示符总是唯一的,常将其用来做其他标示符的一部分以保证其唯一性,进程ID(PID)是无法在用户层修改的.

在Linux系统中,PID为0 的进程通常是调度进程,常常被称为交换进程,也是第一个系统进程.第一个用户进程是init进程,其PID为1.

在应用编程中,调用getpid()函数可以获得当前进程的PID,此函数没有参数,如果执行成功返回当前进程的PID,失败返回-1,出错原因存储于errno.

例子1:打印自己的进程ID(PID).

#include <unistd.h>
#include <stdio.h>
int main()
{
        pid_t pid; //pid_t 其实是int
        pid = getpid();
        printf("the current program's pid is %d\n",pid);
        while(1);
        return 0;
}

运行后使用“ps u”命令查看对照一下.

2.父进程ID(PPID)

函数定义:

#include <sys/types.h>

#include <unistd.h>

pid_t getppid(void);

函数说明:

任何进程(除init进程)都是由另一个进程创建,该进程称为被创建进程的父进程,被创建的进程称为子进程,父进程ID无法在用户层修改.父进程的进程ID即为子进程的父进程ID(PPID).

用户可以通过调用getppid()函数来获得当前进程的父进程ID(PPID).此函数没有参数,如果执行成功返回当前进程的父进程ID(PPID),失败返回-1,出错原因存储于errno.

例子1:打印自己的父进程PPID.

#include <unistd.h>
#include <stdio.h>
int main()
{
        pid_t ppid; //pid_t 其实是int
        ppid = getppid();
        printf("the current program's ppid is %d\n",ppid);
        while(1);
        return 0;
}

运行后使用“ps u”命令查看对照一下.

3.进程组ID(process group ID PGID)

函数定义:

#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);

pid_t getpgid(pid_t pid);

pid_t getpgrp(void);                 /* POSIX.1 version */

pid_t getpgrp(pid_t pid);            /* BSD version */

int setpgrp(void);                   /* System V version */

int setpgrp(pid_t pid, pid_t pgid);  /* BSD version */

函数说明:

在Linux系统中,每个用户都有用户ID(UID)和用户组ID(GUID).同样,进程也拥有自己的进程ID(PID)和进程组ID(PGID). 进程组是一个或多个进程的集合;他们与同一作业相关联.每个进程组都有唯一的进程组ID(PGID),进程组ID(PGID)可以在用户层修改.比如,将某个进程添加到另一个进程组,就是使用setpgid()函数修改其进程组ID.

用户可以通过调用getpgid()函数来获得当前进程的进程组ID(PGID).若此参数为0表示获取当前进程的进程组ID,如果执行成功返回当前进程的进程组ID(PGID),失败返回-1,出错原因存储于errno. 建议使用POSIX.1规定中的无参数getprgp()函数替代getpgid(pid)函数.

进程组ID(PGID)也可以通过函数getpgrp()获得.通过fork()函数产生的子进程会继承它的父进程的进程组ID(PGID).

每个进程组都可以有一个组长进程,组长进程的进程组ID等于其进程ID.但组长进程可以先退出,即只要在某个进程组中有一个进程存在,则该进程组就存在,与其组长进程是否存在无关.进程组的最后进程可以退出或转移到其他组.

可以将某个进程加入到某个进程组中,调用系统函数setpgid().其第一个参数为欲修改进程组ID(PGID)的进程ID(PID),第二参数为新的进程组ID(PGID),如果这两个参数相等,则由pid指定的进程变为该进程组组长;如果pid为0,则使用调用者的进程ID(即修改当前进程的进程组ID(PGID为指定的pgid));如果pgid是0,则由pid指定的进程ID(PID),用做进程组ID(PGID)(即:pid所指进程作为进程组的组长进程).

一个进程只能为自己或子进程设置进程组ID(PGID),如果在它的子进程中调用了exec()等系列函数,就不再能改变该子进程的进程组ID(PGID).

#include <unistd.h>
#include <stdio.h>
int main()
{
        int i;
        printf("\t pid \tppid \t pgid\n");
        printf("parent:\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0));
        for(i=0; i<2; i++)
        {
                if(fork()==0)
                {
                        printf("child:\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0));
                }
        }
        sleep(500);
        return 0;

}

输出:

4.会话(session)

函数定义:

#include <unistd.h>

pid_t getsid(pid_t pid);

pid_t setsid(void);

函数说明:

会话是一个或多个进程组的集合.系统调用函数getsid()用来获取某个进程的会话ID(SID).

如果pid是0,返回调用进程的会话SID,一般说来,改制等于进程组ID(PGID).如果pid并不属于调用者所在的会话,则调用者就无法获取SID.

某个进程的会话ID也是可以修改的,调用函数setsid()用来创建一个新的会话.

如果调用进程已经是一个进程组的组长,则此函数返回错误.如果不是,则返回一个新的会话.

(1)该进程变成新会话首进程,会话首进程是创建该会话的进程,此时,该进程是新会话唯一的进程.

(2)该进程成为一个新的进程组的组长进程.新的进程组ID(PGID)是该调用进程的PID.

(3)该进程没有控制终端.如果在调用setsid()之前该进程就有一个控制终端,那么这种联系也会中断.

图1 进程组合会话的进程安排

5.控制终端(controlling terminal)

函数定义:

#include <unistd.h>

pid_t tcgetpgrp(int fd);

int tcsetpgrp(int fd, pid_t pgrp);

函数说明:

会话和进程组的关系:

(1)一个会话可以有一个控制终端,建立于控制终端相连接的会话首进程被称为控制进程.

(2)一个会话中的几个进程组可被分为一个前台进程组和几个后台进程组,如果一个会话有一个控制终端,则他有一个前台进程组.

(3)无论何时键入终端的中断键,都会将中断信ID发送给前台进程组的所有会话;无论何时键入终端的退出键,都会将退出信ID发送给前台进程组的所有会话.

如果终端监测到调制解调器(或网络)已经断开连接,则将挂断信ID发送给控制进程(会话首进程).

调用函数tcgetgrpt()获取与打开的终端相关联的前台进程组的进程组ID.

调用函数tcsetgrpt()设置某个进程组是前台进程还是后台进程组.

如果进程有一个控制终端,则将前台进程组ID设置为pgrp,pgrp的值应该在同一会话中的一个进程组的ID,fd为控制终端的文件描述符.

如果调用tcsetpgrp()函数的是会话中的后台进程组的进程,则该进程不会阻塞,或者忽略SIGTTOU信号.信号SIGTTOU将会发送给该进程组的所有进程.

当fd是指向进程的控制终端,函数tcgetpgrp()返回终端的前台进程组的进程组ID,该ID值是一个大于1且没有使用的值.如果fd指向的不是进程的终端,则函数返回-1,并设置errno指示出错.

图2 显示控制终端的进程组和会话

笔者:个人能力有限,只是学习参考...读者若发现文中错误,敬请提出.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙筑高台,静下心来,慢慢地沉淀---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

时间: 2024-12-30 18:08:15

进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端的相关文章

(转)进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端

不同的shell对使用管道线时创建子进程的顺序不同,本文以bash为例,它是支持作业控制的shell的典型代表. 僵尸进程与孤儿进程 僵尸进程:先于父进程终止,但是父进程没有对其进行善后处理(获取终止子进程有关信息,释放它仍占有的资源).消灭僵尸进程的唯一方法是终止其父进程.孤儿进程:该进程的父进程先于自身终止.其特点是PPID=1(init进程的ID).一个孤儿进程可以自成孤儿进程组. 文中用到的缩写 PID = 进程ID (由内核根据延迟重用算法生成)PPID = 父进程ID(只能由内核修改

进程组ID操作

 进程关系 调用格式 #include <unistd.h> int setpgid(pid_t pid, pid_t pgid); pid_t getpgid(pid_t pid); pid_t getpgrp(void);                /* POSIX.1 version */ pid_t getpgrp(psid_t pid);          /* BSD version */ int setpgrp(void);                  /* Sys

2进程之间的关系:进程组,会话,守护进程

 1进程组 一个或过个进程的集合,进程组ID是一个正整数.用来获得当前进程组ID的函数. pid_t getpgid(pid_t pid) pid_t getpgrp(void) 获得父子进程进程组 运行结果: 组长进程标识:其进程组ID=其进程ID 组长进程可以创建一个进程组,创建该进程组中的进程,然后终止,只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关. 进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组) 一个进程可以为自己或子进程设置进程组ID i

Linux-进程、进程组、作业、会话、控制终端详解

一.进程 传统上,Unix操作系统下运行的应用程序. 服务器以及其他程序都被称为进程,而Linux也继承了来自unix进程的概念.必须要理解下,程序是指的存储在存储设备上(如磁盘)包含了可执行机器指 令(二进制代码)和数据的静态实体:而进程可以认为是已经被OS从磁盘加载到内存上的.动态的.可运行的指令与数据的集合,是在运行的动态实体.这里指的 指令和数据的集合可以理解为Linux上ELF文件格式中的.text .data数据段. 二.进程组 每个进程除了有一个进程ID之外,还属于一个进程组,那什

进程组与会话 Linux Process Groups and Sessions

在类Unix系统中,用户通常会跟各种相关的进程打交道.虽然在登录的时候只有一个终端进程(用户对应的登录shell ,通过这个shell启动各种程序和服务),但通常不久以后就会产生许多相关的进程,例如进行如下动作: 在后台运行无交互的程序(例如bash命令中末位的"&") 通过shell的 job control在各种交互进程之间切换 通过管道启动一组程序 在图形环境下(例如X window system)启用多个终端窗口 为了管理这些进程,内核便对这些进程进行了分组,称其为进程

设置用户ID和设置组ID

与一个进程关联的ID有6个或更多,如下图所示: 与每个进程相关联的用户ID和组ID 实际用户ID 实际组ID 我们实际是谁 有效用户ID 有效组ID 附加组ID 用于文件访问权限检索 保存的设置用户ID 保存的设置组ID 由exec函数保存 实际用户ID和实际组ID标识我们究竟是谁,这两个字段在登录时取自口令文件中的登录项.通常,在一个登录会话间这些值并不改变,但是超级用户进程有方法改变它们. 有效用户ID,有效组ID以及附加组ID决定了我们的文件访问权限. 保存的设置的用户ID和保存的设置组I

【转】linux 设置用户id 设置组id

[转]转自 linux 设置用户id 设置组id 最近看apue,简单记录对设置用户id理解(设置组id同理). 1. 相关的id好像很多,共有哪些? 文件2个id 2个位: 拥有者id             拥有者组id 设置用户id位         设置组id位 进程6个或更多的id(如果有附加组id): 实际用户id             实际组id       (仅仅标志我们是谁,不参与文件访问权限检测) 有效用户id             有效组id        (用于文件访

linux -- 进程的查看、进程id的获取、进程的杀死

进程查看 ps ax : 显示当前系统进程的列表 ps aux : 显示当前系统进程详细列表以及进程用户 ps ax|less : 如果输出过长,可能添加管道命令 less查看具体进程, 如:ps ax|grep XXX(XXX为进程名称) 获取进程id shell获取进程ID的方法: ps -A |grep "cmdname"| awk '{print $1}' pidof "cmdname" pgrep "cmdname" 这三种在bash和

linux下进程的实际用户ID(有效组)和有效用户ID(有效组ID)

实际用户ID(实际组ID):标识当前用户(所属组)是谁,当用户登陆时取自口令文件. 有效用户ID(有效组ID):用来决定我们(当前进程)对文件的访问权(即实际该进程的是以那个用户运行的). 一般情况下,进程的有效用户ID等于进程的实际用户ID,进程的有效用户组ID等于进程的实际用户组ID. 但是当可执行程序文件的文件模式(st_mode)中设置了“设置-用户-ID(set_user_id)位”时,进程的有效用户ID等于该可执行文件的拥有者ID. 同样的如果可执行文件的文件模式(st_mode)中