comp.unix.programmer newsgroup FAQ 한글번역판 Part.1

comp.unix.programmer newsgroup FAQ 한글번역판 Part.1 


문서제목 : 1. Process Control
작 성 자 : 조성원
편 집 자 : 박민식(SADWIND)
작 성 일 : 2001. 05. 16
원 출 처 : http://www.efefeffang.com/unix/faq_toc.html

 

원문 출처는 위에 명시된 것과 같습니다.
1장은 프로세스 제어에 관련된 내용입니다.
원래 About This FAQ란 문서부터 시작하지만.. 일단 여기서는 뺐습니다 ㅡ.ㅡ
(SADWIND 曰, '그것두 번역하랏! ㅡ.,ㅡ)


1.1 새로운 프로세스 생성하기 : fork()
 1.1.1 What does fork() do?
 1.1.2 What's the difference between fork() and vfork() ?
 1.1.3 Why use _exit rather than exit in the child branch of fork ?
1.2 Environment Variable
 1.2.1 How can I get / set a environmet variables from a program?
 1.2.2 How can I read the whole environment ?
1.3 How can I sleep for less than a second ?
1.4 How can I get a finer-grained version of alarm() ?
1.5 How can a parent and child process communicate ?
1.6 How do I get ird of zombie process ?
 1.6.1 What is a zombie ?
 1.6.2 How do I prevent them from occurring ?
1.7 How do I get my program act like a daemon ?
1.8 How can I look at process in the system like ps ?
1.9 Given a pid , how can I tell if it's a running program ?
1.10 What's the return value of system/pclose/waitpid ?
1.11 How do I find out about a process's memory usage ?
1.12 Why do processes never decrease in size?
1.13 How do I change the name of my program?  (as seen by 'ps' )
1.14 Where do I put my configuration file then ?
1.15 Why doesn't my process get SIGHUP when parent dies ?
1.16 How can I kill all descendents of a process ?


 
1.1 새로운 프로세스 생성하기 : fork()

1.1.1 What does fork() do?
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

fork() 함수는 이미 존재하는 프로세스에서 새로운 프로세스를 만들기 위해 사용한다.
만들어지는 새로운 프로세스는 자식 프로세스라고 하며, 기존의 프로세스는 부모라고 불린다.
우리는 fork()의 반환값을 가지고 구분할 수 있다. 부모 프로세스는 생성되는 자식 프로세스의
아이디를 갖고 자식 프로세스는 0을 갖게 된다.
그러므로 다음과 같은 코딩이 가능하다.


 pid_t pid;
 switch (pid = fork() )
 {
  case 1 :
   perror("The fork failed ! \n");
   break;
  case 0 :
   exit(0);
  default:
   printf("Child's pid is %d\n",pid);
 }

혹은 다음과 같이 할 수도 있다.

 if ( -1 = ( pid = fork() ) ) 
  perror("The fork failed ! \n");
 else if( 0 == pid)
  exit(0);
 else
  printf("child's pid is %d\n",pid);

자식 프로세스는 부모 프로세스로부터 무언가를 물려 받게 된다. 그러므로 자식 프로세스가
완전히 부모 프로세스와 같은 것은 아니라고 볼 수 있겠다. 물려 받는 것은 다음과 같다.

  * real/ effective UID or GID ( Process Credential )
  * 환경변수
  * 스택
  * 메모리
  * 열린 파일기술자
  * close-on-exec flags
  * 시그널 핸들링 설정
  * nice 값
  * 스케쥴러 클래스
  * 프로세스 그룹 ID
  * 세션 ID
  * 현재 작업 디렉토리
  * 루트 디렉토리
  * 파일 모드 생성 마스크 (umask)
  * 리소스 한계값
  * 제어 터미널

자식 프로세스에게 유일하게 할당되는 것으로는 다음과 같다.

  * PID (프로세스 아이디)
  * PPID( 상이한 부모 프로세스 ID )
  * 자신의 파일 기술자 복사본, 디렉토리 스트림
  * 프로세스 시간 ( tms 구조체 )
  * 리소스 이용이 0으로 설정됨.
  * 시그널이 빈 집합으로 초기화 됨
  * timer_create로 생성된 시계(timer) 가 상속되지 않는다
  * 비동기적 입출력은 상속되지 않는다.

1.1.2 What's the difference between fork() and vfork() ?
어떤 시스템에서는 vfork()가 지원된다. 이 함수를 지원하는 이유는 fork()가 프로세스의
주소 공간을 모두 복사하기 때문에 자원관리 면에서 비효율적이다. 이를 해결하여 부담을
줄여주자는 것이다.
 하지만 vfork()가 도입된 이후, fork 함수에 대한 발전이 이루어져, 'copy-on-write' 의
 개념이 도입되면서, 부모와 자식 프로세스가 서로 물리적 주소 공간을 공유하게 되었다.
 vfork를 사용할 필요성이 줄어들면서, 과거의 시스템에서 vfork의 사용은 fork로 다시
 대체되기 시작하였다.
하지만 vfork의 잔재가 현재까지 남아 있기 때문에 호환성을 위해 vfork 시스템 콜이 존재
하며, 단지 이름뿐으로 호출 시에 fork를 대신 이용한다.
두 함수의 근본적인 차이는 vfork 의 호출에서 프로세스가 생성될 때는 자식 프로세스가
execve 등을 호출할 때까지 잠시 일시적으로 지연된다는 것이다. 그러므로 이 함수를 사용할
때에는 프로세스 주소 공간의 변수를 수정할 때 조심해야 한다. 즉, 반환값을 준다든지,
exit를 호출한다는 행동은 자제하는 것이 좋을 것이다.
이런 사실 ( exit 를 자제하고, _exit를 호출하라는 것은 fork에게도 해당되는 사항이다. )

1.1.3 Why use _exit rather than exit in the child branch of fork ?
exit와 _exit 는 약간의 차이를 보이고 있다.
근본적인 차이라고 할 수 있는 점은, 전자의 경우 사용자 공간에서 지원되는 라이브러의
제거 함수이고, 후자는 커널에서 지원하는 제거 함수라는 점이다.
fork의 자식 분기에서 exit를 사용하는 것은 표준 입출력 버퍼를 2번이나 flush 할 수도
있으며, 임시적 파일을 뜻하지 않게 지울 수도 있다. c++의 경우는 더욱 심각할 수도 있다.
static object의 제거자가 비정상적으로 행동 할 수 있기 때문이다.


1.2 Environment Variable

1.2.1 How can I get / set a environmet variables from a program?

환경 변수를 가져오는 함수는 getenv()이다.

#include <stdlib.h>
char * getenv( const char *name);

환경 변수를 지정하는 함수는 putenv() 이다.

#include <stdlib.h>
int putenv (char *string);

putenv에 넘겨지는 문자열은 메모리 해제되어서는 안된다. 왜냐하면 이를 가리키는 포인터가
putenv에 의해 유지되고 있기 때문이다. 즉, 정적 버퍼에 있거나, 힙공간 밖에 존재해야 한다.
그 문자열은 환경 변수가 또 다른 putenv에 의해 제거될 때야 비로소 메모리 해제될 수 있게
된다.
환경변수는 프로세스에서 상속되는 것이므로 , 물려 받는 프로세스는 환경변수를 수정할 수
없게 된다.
예를 들어 TERM 이란 환경변수를 얻고자 할 때는

 char * envvar;
 printf( "The value for the envirionmet variable TERM  is :  ");
 if (envvar)
 {
  printf( "%s \n",envvar );
 }
 else
 {
  printf("not set \n");
 }

그리고 새로운 환경변수를 지정하고 싶은 경우에는,

 static char envbuf[256];
 sprintf(envbuf, "MYVAR=%s","MYVAL");
 if( putenv(envbuf) )
 {
  printf("("Sorry, putenv() couldn't find the memory for %s\n",envbuf);
 }

1.2.2 How can I read the whole environment ?

만약에 당신이 환경변수를 얻고 싶은데, 이름을 모르는 경우, 환경변수에 대해 조금더 알아볼
필요가 있을 것이다. 즉, 환경변수가 어떻게 저장되어 있는가를 알아야 할 것이다.
전역변수 ,environ 는 환경변수의 문자열 포인터들의 array들의 포인터를 가지고 있다. 각각의
문자열들은 "NAME=value"와 같은 형식을 가지고 있다. NULL 포인터는 문자열들의 종료를
표시한다.
다음은 현재의 환경변수를 출력하는 간단한 프로그램이다.

 #include <stdio.h>

 extern char **environ;

 int main()
 {
  char **ep = environ;
  char *p ;

  while ( (p  = *ep ++))
   printf("%s \n",p);

  return 0;
 }

일반적으로 environ 변수는 부가적으로 main 함수의 세번째 파라미터로 넘겨 받는다. 위의
코딩을 조금 고치면,

 #include <stdio.h>

 int main (int argc, char **argv, char **envp)
 {
  char *p ;

  while (( p = *envp ++ ) )
   printf("%s \n",p);

  return 0;
 }

하지만, 대부분은 제대로 수행될 수 있지만,  POSIX 표준에는 명시되지 않은 방법이다.


1.3 How can I sleep for less than a second ?

sleep 함수는 대부분의 UNIX 시스템에서 지원되는 것으로 최소 단위가 초단위이다. 좀 더
정밀한 시간 제어를 위해서는 좀 더 찾아 보아야 한다.

  * 많은 시스템들이 usleep() 함수를 가지고 있다.
  * select 함수나 poll 함수를 이용하는 방법이다. 물론 파일 기술자는 NULL 이다.
    이에 대한 실제 예제는 comp.unix에 찾아보면 구할 수 있을 것이다.
  * 시스템이 itimers 를 가지고 있다면 (대부분 있다) 이를 이용해 usleep를 재구성하여
    사용할 수 있다.
  * POSIX  realtime을 가지고 있다면, nanosleep 도 존재한다.

BSD의 경우에는 usleep 와 nanosleep 둘 다 지원된다.
위에서 select 의 함수의 경우는 오히려 usleep 이나 itimers를 이용하는 것보다 정밀한
제어가 가능하다.
하지만 재우고 있을 때 시그널이 걸려 버리면 예상치 못한 행동을 할 수 있어서 주의가
요구된다.
위의 모든 경우는 또한, 사용하는 시스템에 의존적이다. 즉, 우리가 요구하는 값은 단지
최소값일 뿐이며, 시스템에 따라서 실제 행동은 약간씩 지연될 수도 있다.


1.4 How can I get a finer-grained version of alarm() ?

대부분의 유닉스 시스템들은 alarm을 구현할 경우에 , alarm()보다는 settimer()를 사용한다.
왜냐하면 좀 더 섬세한 조정이 가능하기 때문이다. 보통은 alarm()과 settimer(ITMER_REAL)은
기본적인 타이머로 간주하며, 양쪽을 모두 호출하는 것은 혼란을 부를 수 있다.

Itimers 은 단번 또는 주기적인 시그널을 구현할 때 사용된다.

  ITIMER_REAL
    - 실제 시간( 벽시계 시간 )을 재며, SIGALRM 시그널을 호출한다
  ITIMER_VIRTUAL
    - 프로세스 가상 시간 (CPU 시간) 을 재며, SIGVTALRM 시그널을 호출한다
  ITIMER_PROF
    - 사용자/ 시스템 CPU 시간을 잰다. SIGPROF 시그널을 호출한다. 주로 polling 방식을
      사용할 때 시간을 재주는 용도로 사용된다.

Itimers는 4.2BSD 이후에 계속 있어온 것이지만, 대부분의 시스템에 표준으로 채택된 것은
아니다.


1.5 How can a parent and child process communicate ?

부모와 자식은 IPC (Inter Process Communication)을 이용한다. ( 파이프, 소켓, 메시지 큐,
세마포어 …) 등이 있다.
가장 확실한 방법 중의 하나가 자식의 exit 상태를 가져오는 것이다.
자식 프로세스는 부모로부터 파일 기술자를 물려 받는다. 부모는 파이프의 양쪽을 모두 열
수 있으며, fork를 하고,  부모는 파이프의 한쪽을 닫고, 자식은 다른 한쪽을 닫는다.  즉,
popen() 함수로 반환 받은 파일 기술자에 쓸 수 있게 된다.  한 편 자식 프로세스는 이것을
표준 입력으로 보게 된다. 또한 반대의 경우도 가능하다.


1.6 How do I get ird of zombie process ?

1.6.1 What is a zombie ?

프로그램이 fork를 하고, 자식 프로세스가 부모 프로세스보다 먼저 죽게 될 때, 커널은 부모
프로세스가 혹시 자식 프로세스의 정보가 필요할 지 모르기 때문에 정보를 가지고 있게 된다.
예를 들어 부모 프로세스가 자식 프로세스의 exit 상태를 체크하는 경우가 그렇다. 이 정보를
얻기 위해 부모 프로세스는 wait() 함수를 호출하며, 이 때 커널은 가지고 있던 정보를 버리게
된다.
자식 프로세스가 종료될 때와 wait 함수가 호출될 때의 사이의 시간에 자식 프로세스는 좀비
프로세스라고 한다. 비록 자식 프로세스가 돌고 있지는 않지만, 프로세스 테이블의 한 구석을
차지하고 있는 상태인 것이다. 이 때 셸에서 ps 를 쳐보면 Z 로 STAT에 찍혀 있는 것을 볼 수
있다. )  실제로 좀비 프로세스가 리소스를 사용하고 있지는 않는다. 하지만 우리가 신경쓰게
되는 이유가 프로세스 테이블을 차지하는 것 때문에 발생하는 보거스 수치 때문이다.
이것이 더 진행되면 좋을 것이 없다. 왜냐하면 프로세스 테이블은 한정된 수의 엔트리를
갖고 있기 때문이다. 좀비 프로세스가 계속 늘어나게 된다면, 실제 돌려야 할 프로세스를
위한 공간을 할당 할 수 없게 된다. 그러므로 fork 가 실패할 때는 항상 프로세스 상태를
체크하는 습관이 필요하다.
부모 프로세스가 wait를 호출하지 않고 죽어버리면, 자식 프로세스는 init 프로세스에 종속
된다. 자식 프로세스를 제거해 주는 데 필요한 작업들을 대신 해주게 된다.

1.6.2 How do I prevent them from occurring ?

어떻게 하면 좀비 프로세스를 막을 수 있을까? 해결책은 자식 프로세스가 죽을 때마다
wait / wait3 / waitpid을 호출하거나 , 시스템이 응용 프로그램의 자식들이 죽는 것에
무관심하도록 만드는 방법이 있다.
또 한가지 방법은 fork() 를 2번 사용하는 것이다.  그래서 중간 단계의 자식 프로세스가
바로 종료되도록 만드는 것이다. 이 방법을 이용하면, 부모 프로세스가 먼저 죽어 버리는
상황이므로 자식은 init 프로세스가 알아서 처리하도록 만들 수 있다. 이를 구현한 것은
예제 프로그램 fork2 () 이다.
자식의 exit 상태를 무시하는 방법으로는 시그널 핸들링을 이용하는 것이다.

 struct sigaction sa;
 sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
 sa.sa_flags = SA_NOCLDWAIT;
#else
 sa.sa_flags = 0;
#endif
 sigemptyset( &sa.sa_mask );
 sigaction( SIGCHLD, &sa, NULL);

위의 코딩이 성공적이라면, wait 함수가 작동하지 않을 것이다.
만일 작동하기 시작한다면, 모든 자식 프로세스가 죽을 때까지  기다릴 것이며, 다 죽게
되는 경우 errno = ECHILD를 반환한다.
또 다른 방법은 SIGCHLD 시그널을 잡아서 waitpid 를 호출하는 방법이 있다.  이 방법이
표준적으로 많이 사용하는 방식 중 하나이다.


1.7 How do I get my program act like a daemon ?

daemon 프로세스는 터미널 세션에 속하지 않고 배경으로 돌고 있는 프로세스로 정의 될 수
있다. 많은 시스템 서비스들은 데몬으로 돌고 있다. 예를 들어 네트웍 서비스 나 프린팅
등은 데몬 프로세스로 돌게 된다.
단순히 프로그램을 백그라운드로 부르는 것으로는 장시간 돌아야 하는 것으로는 부적합하며,
터미널에서 떼어내는 것이 요구된다. 키보드의 잘못된 입력으로 해방되기 위해서이다.
대부분의 데몬 프로세스를 만드는 순서가 있는데, 다음과 같다

 1. fork() 를 호출하여 부모 프로세스가 빠져 나갈 수 있도록 한다. 이것은 명령행에게
   제어권을 넘겨주거나 셸에서 호출할 수 있도록 만들어 준다. 이 과정은 새로운 프로세스가
   작업 그룹의 리더가 되지 않도록 보장해 주는 역할을 한다. 이렇게 하는 이유는 다음 과정
   과정에서 setsid()를 호출이 가능하도록 하기 위해서이다.

 2. setsid() 를 호출하여 프로세스 그룹을 만들고 세션의 리더가 된다. 제어 터미널은
   세션과 연관되어 있기 때문에,터미널에 프로그램을 실행시킨 터미널의 제어에서 자유롭기
   위해서는 새로운 세션을 만들어 독립해야 한다.

 3. fork() 를 다시 호출한다. 그리고 다시 빠져 나간다. 이렇게 하는 이유는 완전히 터미
   널에서 독립적이기 위해서이다. 새로운 프로세스는 세션이 아닌 그룹의 리더가 되며,
   자기만의 공간을 가지고 활동을 할 수 있게 되는 것이다.

 4. chdir ("/" )를 하여, 프로그램이 특정 디렉토리를 사용하도록 만들지 않는다. 이것이
   실패하게 된다면, 관리자가 파일 시스템을 해제(unmount) 시킬 수 없게 만들 수 있다.
   왜냐하면, 그 디렉토리가 이 프로세스에 의해 사용중이기 때문이다. 한 편으로는 데몬
   에게 중요한 디렉토리로 이동하여 안전성을 도모할 수도 있겠다.

 5. umask(0) 를 하여 완벽한 제어권을 얻도록 할 수 있다. 이것은 선택적인 사항으로 이해
   하라.

 6. close() fds 0,1,2… 즉 부모로부터 상속받은 표준 입,출력,에러의 파일 기술자를 닫는다.
   우리는 이런 기술자들이 어디록 redirect될 지 모른다. 그러므로 닫아 주는 것이 좋을
  것이다.
   대부분의 시스템에서 sysconf 로 SC_OPEN_MAX를 얻을 수 있다. 즉 사용자가 열 수 있는
   파일 기술자의 개수이다. 만약의 경우 어떤 파일 기술자가 열려 있게 된다면, 동시적으로
   재사용을 할 수 없기 때문에
   최대 값까지 루프를 이용하여 닫아주는 것이 좋겠다.

 7. 이제 새로운 표준 입,출력,에러의 파일 기술자를 연다. 이 부분은 프로그래머에 따라
   취향에 맞게 바꿀 수 있는 부분이다. 데몬의 특성에 따라 표준 입력을 /dev/console ,
   /dev/null 등으로 열어 둘 수 있다.
   위와 같은 과정을 따라가는 표준적인 데몬 프로세스를 만드는 방법이다.
   하지만, inetd 에 의해 관리되는 데몬의 경우에는 이야기가 많이 달라지게 된다. inetd가
   모두 관리를 해주기 때문에, 우리가 추가해야 할 것은 단지 chidir , umask 정도 뿐이다.


1.8 How can I look at process in the system like ps ?

보통은 popen (command,"r"); 로 내용을 추출하여 파싱하는 것으로 해결할 수 있다.
프로세스가 파일로 저장되어 있는데, 시스템에 따라 위치가 틀려 질 수 있으므로 이를 고려
해야 할 것이다.


1.9 Given a pid , how can I tell if it's a running program ?

kill 을 사용할 수 있다.
이것을 사용할 때 4가지의 가능성이 있다.

 * kill 이 0를 반환할 때
   - 이것은 프로세스가 주어진 PID를 가지고 빠져 나갔다는 것을 의미한다. 시스템은 당신이
     시그널을 그것에 보낼 수 있도록 허가할 것이다.

 * kill 이 ?1 반환 , errno = ESRCH
   - PID를 가진 프로세스가 없거나, 보안 때문에 확인을 거부하는 상태이다.

 * kill 이 ?1을 반환 , errno = EPERM
   - 시스템이 특정 프로세스를 죽이지 못하게 한다. 프로세스가 이미 나갔거나, 보안이 금지
     하기 때문이다.

 * kill  -1 반환 , errno = 다른 값
   - 뭔가 문제가 있다.

대부분의 테크닉은 성공하거나, EPERM을 가진 실패는 프로세스가 존재하고, 다른 에러값이
나온 경우는 아닌 경우로 간주한다.
다른 방법도 있는데, /proc 디렉토리로 가서 해당 pid가 있는지 체크하는 것이다.


1.10 What's the return value of system/pclose/waitpid ?

man 페이지를 이용하라.
단지 waitpid의 경우는 상위 16bit가 반환되는데 신뢰할 수 없기 때문에, 대신 다음과 같은
매크로를 이용한다. <sys/wait.h>에 정의되어 있다

 WIFEXITED(stat)
 WEXITSTATUS(stat)
 WTERMSIG(stat)
 WIFSIGNALED(stat)
 WIFSTOPPED(stat)
 WSTOPSIG(stat)
 WIFCONTINUED(stat)
 WCOREDUMP(stat)


1.11 How do I find out about a process's memory usage ?

getrusage() 를 살펴보라..


1.12 Why do processes never decrease in size?

free()로 메모리를 힙으로 되돌릴 때, 프로그램의 메모리 사용을 줄이지 않는다. 메모리
해제도 프로세스의 주소 공간에 할당되어 있기 때문이다. 이는 미래에 있을지 모르는
malloc()을 충족시키기 위해서이다.
만일 시스템에 메모리를 되돌리고 싶은 경우에는 mmap()을 이용하여 개인적인 매핑을 이용
하기 바란다.
이것의 매핑을 제거하면 자동적으로 시스템에게 반환된다. GNU C 라이브러리의 경우에는
malloc() 이 이것을 사용하기 때문에 자동적으로 위의 과정이 이루어진다.
물론 ,여러분의 프로그램이 버그가 있어서 메모리 누수가 있을지도 모르겠다.


1.13 How do I change the name of my program?  (as seen by 'ps' )

BSD와 같은 시스템에서는 ps 프로그램이 실행되고 있는 프로그램의 주소 공간을 직접 들여다
보기 때문에 현재의 argv[]의 값을 찾는다. 이런 방식 때문에 argv 값을 바꾸어 주면 당신의
프로그램 이름을 바꿀 수 있다.
SysV의 경우에는 명령 이름과 파라미터의 80 바이트 정도가 u-area 에 저장된다. 그러므로
직접적인 수정을 가할 수는 없다. 어쩌면 이름을 바꾸어 주는 함수가 있을지도 모른다.
없다면, exec()를 이용해야 할지도 모르고, 커널 메모리에 직접 써야 할지도 모르지만 위험
하므로 피하는 것이 좋겠다.
Solaris와 같은 경우에는 위의 2가지 타입 모두 존재한다. 그러므로 BSD와 같은 ps를 이용
해서 고쳐주면 해결된다.
다음의 함수가 지원되는 지 우선 확인해 보라.. setproctitle() ? 이름을 바꾸어 주는 함수..


1.14 Where do I put my configuration file then ?

이 문제는 시스템 환경에 따라 다르다.
/var/opt/PACKAGE , /usr/local/lib , /usr/local/etc 등과 같이 여러가지가 있을 수 있다.
대부분의 환경 파일은 '.'으로 파일명 앞에 붙이고, $HOME 디렉토리 안에 위치하는 경우가
많다.
패키지와 같은 경우에는 ?prefix 와 같은 옵션을 가지고 위치를 결정하는 경우가 있다. 이
경우에는 적당히 환경 변수에 덧붙여 주는 방법이 있을 수 있다. 혹은 직접 config.h 파일
에서 수정하는 것도 있다.
사용자에게 한정되는 환경 설정 파일의 경우에는 '점'이 있는 하부 디렉토리를 만들어서
보관하는 경우가 일반적이다.


1.15 Why doesn't my process get SIGHUP when parent dies ?

이것은 원래 그러하기 때문이다.
SIGHUP 은 말그대로 터미널 선이 끊어졌다는 경우의 시그널이다. 이는 부모 프로세스와 전혀
무관한 개념이다. 이 시그널은 보통 tty 터미널에서 생성된다.
하지만 세션 관리 시스템의 경우에는 부모 프로세스가 죽을 때 SIGHUP을 받을 수도 있는데,

 * 죽는 프로세스가 세션의 리더인 경우이다. 터미널과 연관되어 있기 때문에, 터미널은
   SIGHUP 시그널을 터미널 그룹의 모든 프로세스에게 전달한다.
 * 죽는 프로세스가 프로세스 그룹을 고아로 만들어 버릴 경우.


1.16 How can I kill all descendents of a process ?

이에 대한 충분한 방법은 없다. ps로 확인 하는 것은 단지 그 시간의 스냅 샷이기 때문에
이를 가지고 처리하는 것은 한계가 있기 마련이다.
하지만, 하부 프로세스가 연속적으로 다시 하부 프로세스를 만드는 경우에는 , 한번에 죽는
시나리오가 가능하다. 하부 프로세스에게 새로운 그룹으로 가도록 만들고, 그룹을 죽여
버리면 간단히 해결된다.
프로세스 그룹을 만드는 경우 선호되는 방법은 setpgid() 이다. setpgrp()보다는 이것을
사용하라..
왜냐하면, 후자가 시스템마다 틀릴 수 있기 때문이다.
그룹관리에 대해서는 예제 프로그램 (Job-control)을 보기 바란다.

위로 스크롤