setpgid
POSIX C 프로세스 그룹 최소 예
기본 API의 실행 가능한 최소 예제로 이해하는 것이 더 쉬울 수 있습니다.
자식이로 프로세스 그룹을 변경하지 않은 경우 신호가 자식에게 전송되는 방식을 보여줍니다 setpgid
.
main.c
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
volatile sig_atomic_t is_child = 0;
void signal_handler(int sig) {
char parent_str[] = "sigint parent\n";
char child_str[] = "sigint child\n";
signal(sig, signal_handler);
if (sig == SIGINT) {
if (is_child) {
write(STDOUT_FILENO, child_str, sizeof(child_str) - 1);
} else {
write(STDOUT_FILENO, parent_str, sizeof(parent_str) - 1);
}
}
}
int main(int argc, char **argv) {
pid_t pid, pgid;
(void)argv;
signal(SIGINT, signal_handler);
signal(SIGUSR1, signal_handler);
pid = fork();
assert(pid != -1);
if (pid == 0) {
is_child = 1;
if (argc > 1) {
/* Change the pgid.
* The new one is guaranteed to be different than the previous, which was equal to the parent's,
* because `man setpgid` says:
* > the child has its own unique process ID, and this PID does not match
* > the ID of any existing process group (setpgid(2)) or session.
*/
setpgid(0, 0);
}
printf("child pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)getpgid(0));
assert(kill(getppid(), SIGUSR1) == 0);
while (1);
exit(EXIT_SUCCESS);
}
/* Wait until the child sends a SIGUSR1. */
pause();
pgid = getpgid(0);
printf("parent pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)pgid);
/* man kill explains that negative first argument means to send a signal to a process group. */
kill(-pgid, SIGINT);
while (1);
}
GitHub의 업스트림 .
다음과 같이 컴파일하십시오.
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -Wpedantic -o setpgid setpgid.c
없이 실행 setpgid
CLI 인수 setpgid
가 없으면 수행되지 않습니다.
./setpgid
가능한 결과 :
child pid, pgid = 28250, 28249
parent pid, pgid = 28249, 28249
sigint parent
sigint child
프로그램이 중단됩니다.
보시다시피, 두 프로세스의 pgid는에 걸쳐 상속됨에 따라 동일 fork
합니다.
그런 다음 때릴 때마다 :
Ctrl + C
다시 출력합니다.
sigint parent
sigint child
이것은 방법을 보여줍니다 :
- 신호를 전체 프로세스 그룹에 전송
kill(-pgid, SIGINT)
- 터미널의 Ctrl + C는 기본적으로 전체 프로세스 그룹에 종료를 보냅니다.
SIGQUIT with를 사용하여 두 신호에 다른 신호를 보내 프로그램을 종료하십시오 Ctrl + \
.
로 실행 setpgid
인수로 실행하면 다음과 같습니다.
./setpgid 1
그런 다음 자식은 pgid를 변경하고 이제는 부모로부터 매번 단일 sigint 만 인쇄됩니다.
child pid, pgid = 16470, 16470
parent pid, pgid = 16469, 16469
sigint parent
그리고 지금, 당신이 칠 때마다 :
Ctrl + C
부모 만이 신호를 수신합니다.
sigint parent
여전히 SIGQUIT를 사용하여 이전과 같이 부모를 죽일 수 있습니다.
Ctrl + \
그러나 아이는 이제 다른 PGID를 가지고 있으며 그 신호를받지 않습니다! 이것은 다음에서 볼 수 있습니다.
ps aux | grep setpgid
다음을 사용하여 명시 적으로 종료해야합니다.
kill -9 16470
이를 통해 신호 그룹이 존재하는 이유를 알 수 있습니다. 그렇지 않으면 항상 수동으로 정리할 프로세스가 많이 남아 있습니다.
우분투 18.04에서 테스트되었습니다.