您的位置:首页 > 其它

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

2016-04-09 19:24 375 查看
摘要:本文主要介绍进程的基本属性,基本属性包括:进程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;

}


pid ppid pgid

parent: 4924 3633 4924

child: 4926 4924 4924

child: 4925 4924 4924

child: 4927 4925 4924

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()之前该进程就有一个控制终端,那么这种联系也会中断
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: