저는 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;
}
... a.out
다음과 같이 백그라운드 프로세스로 실행합니다.
a.out &
이 웹사이트다음과 같이 말해보세요...
각 프로세스는 프로세스 그룹 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
이는 내 a.out
프로세스가 pid 24714
이고 상위 pid에서 생성되었으며 23890
프로그램 그룹의 일부임을 알려줍니다 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
내 부모 프로세스 a.out
는 나에게 의미가 있습니다 bash
. 처음에는 "라고 생각했어요.bash의 pid는 pgid와 일치합니다. 이는 프로세스 그룹 리더이기 때문입니다. 아마도 bash가 실행되는 "첫 번째 작업"이고 내가 bash에서 프로세스를 실행하기 때문에 이것이 의미가 있을 수 있습니다.a.out
"그러나 pgid도 자신의 pid와 일치하기 때문에 이러한 추론은 의미가 없습니다 .
a.out
왜 '의 pgid가 '의 pgid와 같지 않습니까 bash
? 이 문장에 대한 나의 이해를 바탕으로 이것이 내가 기대했던 것입니다.
누군가 pid와 pgid 사이의 관계를 명확히 할 수 있습니까?
답변1
충돌은 없습니다. 기본적으로 프로세스는 상위인 유일한 프로세스 그룹에 속합니다.
$ 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
$
fork
프로세스를 상위 프로세스( 12495
)와 하위 프로세스( )로 나누고 , 하위 프로세스는 12496
상위 프로세스( ) 12495
의 고유 프로세스 그룹 에 속합니다. bash
추가 시스템 호출을 실행하기 때문에 이와는 다릅니다.
$ echo $$
12366
$
그런 다음 다른 터미널에서 실행하십시오.
$ strace -f -o blah -p 12366
그런 다음 첫 번째 터미널로 돌아갑니다.
$ ./pg
pid=12676 pgid=12676
pid=12677 pgid=12676
$
그런 다음 시스템 호출을 확인합니다 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 ...>
bash
이 setpgid
호출을 사용하여 프로세스 그룹을 설정함으로써 pg
프로세스를 쉘 독립적인 프로세스 그룹에 배치합니다. ( setsid(2)
시스템 호출을 찾고 있다면 프로세스 그룹을 조정하는 또 다른 방법이 될 것입니다.)
답변2
Bash는 작업 제어 처리의 일부로 프로그램을 자체 프로세스 그룹에 넣습니다. 예를 들어, bash 맨페이지에서:
작업 제어 사용자 인터페이스의 구현을 용이하게 하기 위해 운영 체제는 현재 터미널 프로세스 그룹 ID의 개념을 유지합니다. 이 프로세스 그룹의 멤버(현재 터미널의 프로세스 그룹 ID와 동일한 프로세스 그룹 ID를 가진 프로세스)는 SIGINT와 같은 키보드 생성 신호를 수신합니다. 이러한 프로세스를 포그라운드에 있다고 합니다. 백그라운드 프로세스는 프로세스 그룹 ID가 터미널 프로세스 그룹 ID와 다른 프로세스입니다. 이러한 프로세스는 키보드에서 생성된 신호의 영향을 받지 않습니다. 포그라운드 프로세스만 터미널을 읽거나 쓸 수 있습니다(사용자가 stty tostop을 사용하여 지정한 경우). 커널의 터미널 드라이버는 터미널에서 읽기를 시도하는(그리고 stty tostop이 적용될 때 쓰기를 시도하는) 백그라운드 프로세스에 SIGTTIN(SIGTTOU) 신호를 보내고 프로세스는 잡히지 않는 한 정지됩니다.
또한 set -m
:
모니터 모드. 작업 제어가 활성화되었습니다. 이 옵션은 이를 지원하는 시스템의 대화형 셸에 대해 기본적으로 활성화되어 있습니다(위의 작업 제어 참조). 모든 프로세스는 별도의 프로세스 그룹에서 실행됩니다. 백그라운드 작업이 완료되면 셸은 종료 상태를 포함하는 줄을 인쇄합니다.
따라서 기대하는 동작을 원하면 다음을 수행할 수 있습니다.
fork
Bash 없이 프로세스를 생성하기 위해 코드에서 사용됩니다.set +m
Bash에서 감시 모드를 끄는 데 사용됩니다 .fg
하지만 이것은 그런 것들을 깨뜨릴 것입니다.