通过系统的进程树来查看某个进程的父进程;
在显示的输出中,第三列就是该进程的父进程PID,然后可以再使用ps命令来查看父进程的名称
man ps says:
This version of ps accepts several kinds of options:
1 UNIX options, which may be grouped and must be preceded by a
dash.
2 BSD options, which may be grouped and must not be used with a
dash.
3 GNU long options, which are preceded by two dashes.
So, ef uses the BSD e and f options, and -ef uses the Unix -e and -f options. These are different (sections SIMPLE PROCESS SELECTION, OUTPUT FORMAT CONTROL and OUTPUT MODIFIERS respectively):
-e Select all processes. Identical to -A.
-f Do full-format listing. This option can be combined with many
other UNIX-style options to add additional columns. It also
causes the command arguments to be printed. When used with
-L, the NLWP (number of threads) and LWP (thread ID) columns
will be added. See the c option, the format keyword args, and
the format keyword comm.
e Show the environment after the command.
f ASCII art process hierarchy (forest).
Clearly, you’re not selecting all processes using the ef options, but are using the default listing of processes, plus some additional formatting:
By default, ps selects all processes with the same effective user ID
(euid=EUID) as the current user and associated with the same terminal
as the invoker. It displays the process ID (pid=PID), the terminal
associated with the process (tname=TTY), the cumulated CPU time in
[DD-]hh:mm:ss format (time=TIME), and the executable name (ucmd=CMD).
Output is unsorted by default.
The use of BSD-style options will add process state (stat=STAT) to
the default display and show the command args (args=COMMAND) instead
of the executable name. You can override this with the PS_FORMAT
environment variable. The use of BSD-style options will also change
the process selection to include processes on other terminals (TTYs)
that are owned by you; alternately, this may be described as setting
the selection to be the set of all processes filtered to exclude
processes owned by other users or not on a terminal.
Which should you use? What do you want to do with the output?
Also, see the EXAMPLES section (which does list -ef rather prominently, and doesn’t use the BSD e option at all):
EXAMPLES
To see every process on the system using standard syntax:
ps -e
ps -ef
ps -eF
ps -ely
To see every process on the system using BSD syntax:
ps ax
ps axu
To print a process tree:
ps -ejH
ps axjf
This version of ps accepts several kinds of options:
1 UNIX options, which may be grouped and must be preceded by a dash.
2 BSD options, which may be grouped and must not be used with a dash.
3 GNU long options, which are preceded by two dashes.
So the 1st method (ps ef) is BSD style and the manual page goes on with
The use of BSD-style options will add process state (stat=STAT) to the default display and show the command args (args=COMMAND) instead of the executable name. You can override this with the PS_FORMAT environment variable. The use of BSD-style options will also change the process selection to include processes on other terminals (TTYs) that are owned by you; alternately, this may be described as setting the selection to be the set of all processes filtered to exclude processes owned by other users or not on a terminal. These effects are not considered when options are described as being “identical” below, so -M will be considered identical to Z and so on.
https://askubuntu.com/questions/942529/which-to-use-of-ps-ef-or-ps-ef
Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux。这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同。现在的大部分Linux系统都是可以同时使用这两种方式的。
ps -ef 是用标准的格式显示进程的、其格式如下
其中各列的内容意思如下
UID //用户ID、但输出的是用户名
PID //进程的ID
PPID //父进程ID
C //进程占用CPU的百分比
STIME //进程启动到现在的时间
TTY //该进程在那个终端上运行,若与终端无关,则显示? 若为pts/0等,则表示由网络连接主机进程。
CMD //命令的名称和参数
ps aux 是用BSD的格式来显示、其格式如下
同ps -ef 不同的有列有
USER //用户名
%CPU //进程占用的CPU百分比
%MEM //占用内存的百分比
VSZ //该进程使用的虚拟內存量(KB)
RSS //该进程占用的固定內存量(KB)(驻留中页的数量)
STAT //进程的状态
START //该进程被触发启动时间
TIME //该进程实际使用CPU运行的时间
其中STAT状态位常见的状态字符有
D //无法中断的休眠状态(通常 IO 的进程);
R //正在运行可中在队列中可过行的;
S //处于休眠状态;
T //停止或被追踪;
W //进入内存交换 (从内核2.6开始无效);
X //死掉的进程 (基本很少见);
Z //僵尸进程;
< //优先级高的进程
N //优先级较低的进程
L //有些页被锁进内存;
s //进程的领导者(在它之下有子进程);
l //多线程,克隆线程(使用 CLONE_THREAD, 类似 NPTL pthreads);
问题描述:当SSH远程连接到服务器上,然后运行一个服务 ./catalina.sh start,然后把终端开闭(切断SSH连接)之后,发现该服务中断,导致网页无法访问。
解决方法:使用nohup命令让程序在关闭窗口(切换SSH连接)的时候程序还能继续在后台运行。
Unix/Linux下一般比如想让某个程序在后台运行,很多都是使用& 在程序结尾来让程序自动运行。比如我们要运行mysql在后台:
/usr/local/mysql/bin/mysqld_safe –user=mysql &
但是加入我们很多程序并不象mysqld一样做成守护进程,可能我们的程序只是普通程序而已,一般这种程序使用& 结尾,但是如果终端关闭,那么程序也会被关闭。但是为了能够后台运行,那么我们就可以使用nohup这个命令,比如我们有个test.php需要在后台运行,并且希望在后台能够定期运行,那么就使用nohup:
nohup /root/test.php &
提示:
[~]$ appending output to nohup.out
嗯,证明运行成功,同时把程序运行的输出信息放到当前目录的nohup.out 文件中去。
nohup命令说明:
用途:不挂断地运行命令。
语法:nohup Command [ Arg … ] [ & ]
描述:nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 & ( 表示“and”的符号)到命令的尾部。
无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符。
退出状态:该命令返回下列出口值:
126 可以查找但不能调用 Command 参数指定的命令。
127 nohup 命令发生错误或不能查找由 Command 参数指定的命令。
否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。
nohup命令及其输出文件
nohup命令:如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令。该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup就是不挂起的意思( n ohang up)。
该命令的一般形式为:nohup command &
使用nohup命令提交作业
如果使用nohup命令提交作业,那么在缺省情况下该作业的所有输出都被重定向到一个名为nohup.out的文件中,除非另外指定了输出文件:(也就是说自定义输出的文件名)
nohup command > myout.file 2>&1 &
在上面的例子中,输出被重定向到myout.file文件中。
使用 jobs 查看任务。
使用 fg %n 关闭。
另外有两个常用的ftp工具ncftpget和ncftpput,可以实现后台的ftp上传和下载,这样我就可以利用这些命令在后台上传和下载文件了。
思考:问题1为什么ssh一关闭,程序就不再运行了?
元凶:SIGHUP 信号
让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。
在Linux/Unix中,有这样几个概念:
进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。
根据POSIX.1定义:
挂断信号(SIGHUP)默认的动作是终止程序。
当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
如果会话期首进程终止,则该信号发送到该会话期前台进程组。
一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。(关于孤儿进程参照:http://blog.csdn.net/hmsiwtv/article/details/7901711 )
结论:因此当网络断开或终端窗口关闭后,也就是SSH断开以后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。
简而言之:就是ssh 打开以后,bash等都是他的子程序,一旦ssh关闭,系统将所有相关进程杀掉!! 导致一旦ssh关闭,执行中的任务就取消了
例子:
我们来看一个例子。打开两个SSH终端窗口,在其中一个运行top命令。
[root@tivf09 root]# top
在另一个终端窗口,找到top的进程ID为5180,其父进程ID为5128,即登录shell。
[root@tivf09 root]# ps -ef|grep top
root 5180 5128 0 01:03 pts/0 00:00:02 top
root 5857 3672 0 01:12 pts/2 00:00:00 grep top
使用pstree命令可以更清楚地看到这个关系:
[root@tivf09 root]# pstree -H 5180|grep top
|-sshd-+-sshd—bash—top
使用ps-xj命令可以看到,登录shell(PID 5128)和top在同一个会话期,shell为会话期首进程,所在进程组PGID为5128,top所在进程组PGID为5180,为前台进程组。
[root@tivf09 root]# ps -xj|grep 5128
5126 5128 5128 5128 pts/0 5180 S 0 0:00 -bash
5128 5180 5180 5128 pts/0 5180 S 0 0:50 top
3672 18095 18094 3672 pts/2 18094 S 0 0:00 grep 5128
关闭第一个SSH窗口,在另一个窗口中可以看到top也被杀掉了。
[root@tivf09 root]# ps -ef|grep 5128
root 18699 3672 0 04:35 pts/2 00:00:00 grep 5128
问题2 为什么守护程序就算ssh 打开的,就算关闭ssh也不会影响其运行?
因为他们的程序特殊,比如httpd –k start运行这个以后,他不属于sshd这个进程组 而是单独的进程组,所以就算关闭了ssh,和他也没有任何关系!
[root@CentOS5-4 ~]# pstree |grep http
|-httpd
[root@CentOS5-4 ~]# pstree |grep top
|-sshd-+-sshd—bash—top
结论:守护进程的启动命令本身就是特殊的,和一般命令不同的,比如mysqld_safe 这样的命令 一旦使用了 就是守护进程运行。所以想把一般程序改造为守护程序是不可能,
问题3 使用后台运行命令& 能否将程序摆脱ssh进程组控制呢 也就是ssh关闭,后台程序继续运行?
我们做一个试验: find / -name ‘http’&
利用ctrl+d 注销以后 再进入系统 会不会看见这个命令再运行?
答案是 :命令被中止了!!
因为他依然属于这个ssh进程组 就算加了&也无法摆脱!!
[root@CentOS5-4 ~]# pstree |grep find
|-sshd-+-sshd—bash—find
结论就是:只要是ssh 打开执行的一般命令,不是守护程序,无论加不加&,一旦关闭ssh,系统就会用SIGHUP终止
问题4 nohup能解决的问题
但是为了能够再注销以后 依然能后台运行,那么我们就可以使用nohup这个命令,我们现在开始查找find / -name ‘http’&
,并且希望在后台运行,
那么就使用nohup:nohup find / -name “httpd”
此时默认地程序运行的输出信息放到当前文件夹的nohup.out 文件中去
加不加&并不会影响这个命令 只是让程序 前台或者后台运行而已
延伸:Linux命令nohup+screen命令
如果想在关闭ssh连接后刚才启动的程序继续运行怎么办,可以使用nohup。但是如果要求第二天来的时候,一开ssh,还能查看到昨天运行的程序的状态,然后继续工作,这时nohup是不行了,需要使用screen来达到这个目的。
虽然nohup很容易使用,但还是比较“简陋”的,对于简单的命令能够应付过来,对于复杂的需要人机交互的任务就麻烦了。
其实我们可以使用一个更为强大的实用程序screen。流行的Linux发行版(例如Red Hat Enterprise Linux 4)通常会自带screen实用程序,如果没有的话,可以从GNU screen的官方网站下载。
1)使用
执行screen , 按任意键进入子界面;
我用ping命令开始执行,如果下班了,但是想关闭ssh以后ping继续运行,那么按ctrl+a 再按d 这样暂停了子界面,会显示[detached]的字样,这时候 我回到了父界面;
用screen –ls查看目前子界面的状态screen -ls
There is a screen on: 22292.pts-3.free (Detached)
1 Socket in /tmp/screens/S-root,这里的22292其实是子界面的pid号;
如果回到子界面 用screen –r 22292,一下子弹到了ping 的子界面;
2)更多帮助
可以通过C-a(ctrl+a)?来查看所有的键绑定,常用的键绑定有:
C-a ?
显示所有键绑定信息
C-a w
显示所有窗口列表
C-a C-a
切换到之前显示的窗口
C-a c
创建一个新的运行shell的窗口并切换到该窗口
C-a n
切换到下一个窗口
C-a p
切换到前一个窗口(与C-a n相对)
C-a 0..9
切换到窗口0..9
C-a a
发送C-a到当前窗口
C-a d
暂时断开screen会话
C-a k
杀掉当前窗口
C-a [
进入拷贝/回滚模式
其他常用选项:
-c file
使用配置文件file,而不使用默认的$HOME/.screenrc
-d|-D [pid.tty.host]
不开启新的screen会话,而是断开其他正在运行的screen会话
-h num
指定历史回滚缓冲区大小为num行
-list|-ls
列出现有screen会话,格式为pid.tty.host
-d -m
启动一个开始就处于断开模式的会话
-r sessionowner/ [pid.tty.host]
重新连接一个断开的会话。多用户模式下连接到其他用户screen会话需要指定sessionowner,需要setuid-root权限
-S sessionname
创建screen会话时为会话指定一个名字
-v
显示screen版本信息
-wipe [match]
同-list,但删掉那些无法连接的会话
不同的shell对使用管道线时创建子进程的顺序不同,本文以bash为例,它是支持作业控制的shell的典型代表。
僵尸进程与孤儿进程
僵尸进程:先于父进程终止,但是父进程没有对其进行善后处理(获取终止子进程有关信息,释放它仍占有的资源)。消灭僵尸进程的唯一方法是终止其父进程。
孤儿进程:该进程的父进程先于自身终止。其特点是PPID=1(init进程的ID)。一个孤儿进程可以自成孤儿进程组。
文中用到的缩写
PID = 进程ID (由内核根据延迟重用算法生成)
PPID = 父进程ID(只能由内核修改)
PGID = 进程组ID(子进程、父进程都能修改)
SID = 会话ID(进程自身可以修改,但有限制,详见下文)
TPGID= 控制终端进程组ID(由控制终端修改,用于指示当前前台进程组)
进程、进程组、会话之间的关系
总体关系
进程属于一个进程组,进程组属于一个会话,会话可能有也可能没有控制终端
会话
会话首进程:
新建会话时,会话中的唯一进程,其PID=SID。它通常是一个登陆shell,也可以在成为孤儿进程后调用setsid()成为一个新会话。
会话:
一个或多个进程组的集合。一个登陆shell发起的会话,一般由一个会话首进程、一个前台进程组、一个后台进程组组成。
进程组
一个或多个进程的集合,进程组属于一个会话。fork()并不改变进程组ID。
进程组组长:
PID与PGID相等的进程。组长可以改变子进程的进程组ID,使其转移到另一进程组。
例如一个shell进程(下文均以bash为例),当使用管道线时,如echo “hello” | cat,bash以第一个命令的进程ID为该管道线内所有进程设置进程组ID。此时echo和cat的进程组ID都设置成echo的进程ID。
前台进程组
该进程组中的进程能够向终端设备进行读、写操作的进程组。
登陆shell(例如bash)通过调用tcsetpgrp()函数设置前台进程组,该函数将终端设备的fd(文件描述符)与指定进程组关联。成为前台进程组的进程其TPGID=PGID,常常可以通过比较他们来判断前后台进程组。
后台进程组
一个会话中,除前台进程组、会话首进程以外的所有进程组。该进程组中的进程能够向终端设备写,但是当试图读终端设备时,将会收到SIGTTIN信号,并停止。登录shell可以根据设置在终端上发出一条消息[1]通知用户有进程欲求读终端。
前台进程组ID只能有一个,而后台进程组同时可存在多个。后台进程组的PGID≠TPGID。
孤儿进程组
定义1
该组中的每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员
定义2
不是孤儿进程组的条件是,该组中有一个进程,其父进程属于同一会话的另一个组中。
也就是说,将该父进程终止就能使该进程组成为僵尸进程孤儿进程(感谢网友”hello”的指正)。这个父进程通常是这个进程组的组长进程,因为只有它的父进程在这个进程组外,而其他进程(组长的子进程)的父进程都是组长进程的ID。
解析:产生一个孤儿进程(组)并读终端
由组长fork()产生的子进程其进程组ID不变(因为fork()不改变进程组ID)
若组长是bash,则将子进程的进程组ID设置成第一个命令的PID,即由第一个命令当组长,并成为一个新的进程组
由bash产生的新进程组中,至少要有一个进程的PPID指向该bash,否则该进程组成为孤儿进程组,无法将进程状态的改变通知bash
bash通过wait函数族检测子进程(新的进程组)的状态,从而决定如何设置前台进程组ID(给指定的终端设备)
后台进程(组)试图读控制终端设备时,终端驱动程序向其发送SIGTTIN信号,此时应当由bash唤醒该进程(组),使之进入前台
对于孤儿进程(组),bash无法知晓其状态,因为bash不知道其PID,而唯一知道其PID的进程已经终止,也就无法知晓其组ID,从而不能将其组ID放入前台。如果孤儿进程(组)试图读取终端,read()调用将失败,并将errno置为EIO。
注释
[1] 可以通过使用stty tostop命令禁止后台进程组向终端进行写操作,当发出写请求时,将会收到SIGTTOU信号。
一、产生原因
1、僵尸进程
子进程退出,父进程运行,父进程没有调用 wait 或者 waitpid 函数,那么子进程就处于僵尸状态(Z)。
2、孤儿进程
子进程运行,父进程退出,孤儿进程由 init 进程收养,此时子进程就变成了孤儿进程。
3、系统为什么需要僵尸进程这种进程状态
由于父进程创建子进程是异步的,双方不知道各自的运行状态,而父进程有的时候需要知道子进程退出时的一些信息,所以 linux 提供了一种机制,通过让子进程退出时向父进程发送 SIGCHRD 信号来告知父进程,子进程已经退出了。同时,父进程通过调用 wait 和 waitpid 来获取子进程的退出信息。
二、有什么危害
1、僵尸进程
有很大危害。因为僵尸进程已经挺尸了,对系统没有什么作用,但是依然在进程表占了位置,如果 os 有大量的僵尸进程,那么进程号就会被大量无故占用,严重的话再次 fork 进程可能失败。
2、孤儿进程
没什么危害。因为该进程只是父进程换成了 init ,依然可以正常运行。
三、如何预防(解决方案)
1、kill 父进程
kill 父进程之后,僵尸进程会变成孤儿僵尸进程,由 init 收养,通过 init 是循环 wait ,从而让子进程彻底退出。
2、注册 SIGCHRD 信号的信号处理函数,在函数中调用 wait 或者 waitpid 。
3、fork 两次,创建子进程,子进程在创建孙进程,最后 kill 子进程,那么孙进程就由 init 收养。
父进程创建的进程为该父进程的子进程
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
孤儿进程和僵尸进程产生的原因:
归根结底还是Unix操作系统提供了一种这样的机制:让父进程可以知道子进程结束时的状态信息。
如果没有这种机制,一个子进程结束,就把他的所有资源和信息全部释放掉,那父进程就无法获得子进程结束时的状态信息了,对吧?所以子进程结束的时候会留下一个数据结构,用这个数据结构存储子进程结束时的信息,直到父进程调用wait或者waitpid的时候才释放。
那就有下面的情况发生:
一、如果父进程一直比较忙,或者因为其他原因没有去wait/waitpid子进程结束时候留下的状态信息,那这些已经结束的线程遗留的数据结构就无从清理,也就产生了所谓的僵尸进程,因为数据结构里包含pid等信息,操作系统的pid是有限的,因此僵尸进程是有害的。
二、如果父进程先于子进程结束,那子进程无父进程了,如果之后子进程也结束,谁去释放他遗留下来的数据结构呢?这个无父进程的子进程就叫孤儿进程,他将会被init进程(pid=1)托管,之后此子进程结束的话,他的遗留数据结构将会被init进程去wait/waitpid释放
为什么ssh一关闭,程序就不再运行了?
元凶:SIGHUP 信号
让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。
在Linux/Unix中,有这样几个概念:
进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。
根据POSIX.1定义:
挂断信号(SIGHUP)默认的动作是终止程序。
当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
如果会话期首进程终止,则该信号发送到该会话期前台进程组。
一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。(关于孤儿进程参照:http://blog.csdn.net/hmsiwtv/article/details/7901711 )
结论:因此当网络断开或终端窗口关闭后,也就是SSH断开以后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。
简而言之:就是ssh 打开以后,bash等都是他的子程序,一旦ssh关闭,系统将所有相关进程杀掉!! 导致一旦ssh关闭,执行中的任务就取消了
在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)
函数说明:
会话是一个或多个进程组的集合.系统调用函数getsid()用来获取某个进程的会话ID(SID).
假设pid是0。返回调用进程的会话SID,一般说来。改制等于进程组ID(PGID).假设pid并不属于调用者所在的会话。则调用者就无法获取SID.
某个进程的会话ID也是能够改动的。调用函数setsid()用来创建一个新的会话.
假设调用进程已经是一个进程组的组长,则此函数返回错误.假设不是,则返回一个新的会话. (1)该进程变成新会话首进程。会话首进程是创建该会话的进程。此时,该进程是新会话唯一的进程. (2)该进程成为一个新的进程组的组长进程.新的进程组ID(PGID)是该调用进程的PID. (3)该进程没有控制终端.假设在调用setsid()之前该进程就有一个控制终端,那么这样的联系也会中断.