Sto*_*row 5 linux process process-groups
我正在学习 Linux 中进程、进程组(和会话)之间的关系。
我编译了以下程序...
#include <iostream>
#include <ctime>
#include <unistd.h>
int main( int argc, char* argv[] )
{
char buf[128];
time_t now;
struct tm* tm_now;
while ( true )
{
time( &now );
tm_now = localtime( &now );
strftime( buf, sizeof(buf), "%a, %d %b %Y %T %z", tm_now );
std::cout << buf << std::endl;
sleep(5);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...a.out
作为后台进程运行它,就像这样......
a.out &
Run Code Online (Sandbox Code Playgroud)
这个网站说以下...
每个进程都是唯一进程组的成员,由其进程组 ID 标识。(创建进程时,它成为其父进程组的成员。)按照惯例,进程组的进程组 ID 等于进程组的第一个成员的进程 ID,称为进程组组长。
根据我的阅读,第一句与括号内的内容冲突:进程是唯一进程组的成员,还是其父进程组的成员?
我试图调查ps
...
ps xao pid,ppid,pgid,sid,command | grep "PGID\|a.out"
PID PPID PGID SID COMMAND
24714 23890 24714 23890 ./a.out
Run Code Online (Sandbox Code Playgroud)
这告诉我我的a.out
进程是 pid 24714
,从父 pid23890
和程序组的一部分产生24714
。首先,我不明白为什么这个 pgid 与 pid 匹配。
接下来,我试图调查父进程......
ps xao pid,ppid,pgid,sid,command | grep "PGID\|23890"
PID PPID PGID SID COMMAND
23890 11892 23890 23890 bash
24714 23890 24714 23890 ./a.out
Run Code Online (Sandbox Code Playgroud)
我的父进程a.out
是bash
. 起初我认为“ bash 的 pid 与其 pgid 匹配 - 那一定是因为它是进程组的领导者。也许这是有道理的,因为 bash 是运行我的进程的“第一件事”。 “但是那个推理没有意义,因为a.out
的 pgid 也匹配它自己的 pid。
为什么a.out
pgid 不等于bash
pgid?根据我对报价的理解,这就是我所期望的。
有人可以澄清pids和pgids之间的关系吗?
Bash 将您的程序放在其自己的进程组中,作为其作业控制处理的一部分。例如,来自 bash 联机帮助页:
为了便于作业控制的用户界面的实现,操作系统维护了当前终端进程组 ID 的概念。此进程组的成员(进程组 ID 等于当前终端进程组 ID 的进程)接收键盘生成的信号,例如 SIG? 情报局。据说这些进程在前台。后台进程是那些进程组 ID 与终端不同的进程;此类进程不受键盘生成信号的影响。只允许前台进程读取,或者,如果用户使用 stty tostop 指定,则写入终端。
还有关于set -m
:
监控模式。作业控制已启用。对于支持它的系统上的交互式 shell,默认情况下启用此选项(请参阅上面的 JOB CONTROL)。所有进程都在一个单独的进程组中运行。当后台作业完成时,shell 会打印一行包含其退出状态的行。
所以,如果你想要你期望的行为,你可以:
fork
在您的代码中使用,在没有 bash 的情况下创建一个进程。set +m
关闭 bash 中的监控模式。不过,这会破坏诸如 之类的东西fg
。没有冲突;默认情况下,一个进程将位于一个唯一的进程组中,该进程组是其父进程组:
$ cat pg.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
fork();
printf("pid=%d pgid=%d\n", getpid(), getpgrp());
}
$ make pg
cc pg.c -o pg
$ ./pg
pid=12495 pgid=12495
pid=12496 pgid=12495
$
Run Code Online (Sandbox Code Playgroud)
在fork
分裂我们的工艺为母公司(12495
)和孩子(12496
),和孩子属于父的独特的工艺组(12495
)。bash
与此不同,因为它发出额外的系统调用:
$ echo $$
12366
$
Run Code Online (Sandbox Code Playgroud)
然后在另一个终端中我们运行:
$ strace -f -o blah -p 12366
Run Code Online (Sandbox Code Playgroud)
然后回到第一个终端:
$ ./pg
pid=12676 pgid=12676
pid=12677 pgid=12676
$
Run Code Online (Sandbox Code Playgroud)
然后我们control+c的strace
,并检查系统调用:
$ egrep 'exec|pgid' blah
12366 setpgid(12676, 12676) = 0
12676 setpgid(12676, 12676 <unfinished ...>
12676 <... setpgid resumed> ) = 0
12676 execve("./pg", ["./pg"], [/* 23 vars */]) = 0
12676 write(1, "pid=12676 pgid=12676\n", 21 <unfinished ...>
12677 write(1, "pid=12677 pgid=12676\n", 21 <unfinished ...>
Run Code Online (Sandbox Code Playgroud)
bash
已经使用setpgid
调用来设置进程组,从而将我们的pg
进程放入与shell无关的进程组中。(setsid(2)
如果您正在寻找系统调用,这将是调整进程组的另一种方法。)
归档时间: |
|
查看次数: |
1422 次 |
最近记录: |