데몬 프로세스는 터미널과 완전히 분리되어, 백그라운드에서 동작하는 프로세스를 의미한다.
데몬 프로세스는 다음과 같은 특징을 갖고 있다.
void MakeDaemon(const char* name, int facility)
{
int i;
pid_t pid;
pid = fork(); // 자식 프로세스 생성
if (pid != 0)
exit(0); // parent terminates
setsid(); // 프로세스를 제어 터미널에서 독립
signal(SIGHUP, SIG_IGN); // SIGHUP 신호 무시
// child process를 fork()하고 exit(0)
// process group leader를 제거하여 controlling terminal를 다시는 얻을 수 없도록 한다.
pid = fork();
if (pid != 0)
exit(0); // 1st child terminates
// 마스크를 0으로 설정해 파일 생성 시 모든 권한을 허용
umask(0);
// 모든 파일 디스크럽터를 닫아 어떠한 표준 입출력도 터미널과 연결되지 않도록 함
for (i=0; i<DAEMON_MAXFD; i++)
close(i);
}
MakeDaemon()
함수는 실행중인 프로그램을 데몬 프로세스로 만드는 함수의 예제이다.
코드를 해석하면 다음과 같다.
pid = fork(); // 자식 프로세스 생성
if (pid != 0)
exit(0); // parent terminates
첫 번째 자식 프로세스를 생성한다.
그리고 if (pid != 0) exit(0);
구문에 의해 부모 프로세스를 종료한다. (자식 프로세스의 경우 0을 반환)
setsid(); // 프로세스를 제어 터미널에서 독립
signal(SIGHUP, SIG_IGN); // SIGHUP 신호 무시
setsid()
함수는 세션(새로운 세션 리더)을 생성한다. 이를 통해 프로세스는 기존 세션에서 독립된다. 또한 새로운 프로세스 그룹 리더가 되어 컨트롤 터미널에서 완전히 독립된다.
그리고 SIG_IGN
옵션을 통해 SIGHUP
신호를 무시한다. 이 신호는 터미널 세션이 끊겼을 때 보내지는 신호로, 데몬 프로세스가 터미널에 종속되지 않도록 방지한다.
pid = fork();
if (pid != 0)
exit(0); // 1st child terminates
두 번째 자식 프로세스를 생성하고, 첫 번재 자식 프로세스를 종료한다.
두 번의 fork()
를 거쳐 두 번의 자식 프로세스를 생성하는 것은 process group leader를 제거하여 controlling terminal를 다시는 얻을 수 없도록 함으로써, 데몬 프로세스가 터미널과 완전히 독립되도록 하는 일반적인 방법 중 하나라고 한다.
umask(0);
// 모든 파일 디스크럽터를 닫아 어떠한 표준 입출력도 터미널과 연결되지 않도록 함
for (i=0; i<DAEMON_MAXFD; i++)
close(i);
umask를 0으로 설정하여, 두 번째 자식 프로세스에서 파일 생성 시 모든 권한을 허용한다.
for()
문은 모든 파일 디스크립터를 닫는 부분으로, close(i)
를 통해 0부터 DAEMON_MAXFD까지의 모든 파일 디스크럽터를 닫는다.
특히 0은 표준 입력(STDIN), 1은 표준 출력(STDOUT), 2는 표준 에러(STDERR)를 나타내며, DAEMON_MAXFD의 값은 시스템의 최대 파일 디스크립터 수에 따라 달라진다.
이렇게 함으로써 프로세스와 터미널과의 연결이 완전히 끊어지고 어떠한 표준 입출력도 터미널과 연결되지 않게 된다.
최대 파일 디스크립터의 수는 ulimit -n
명령어를 통해 확인할 수 있다.
ulimit -n
1024