노무현 대통령 배너


2006. 6. 2. 14:36

[본문스크랩] 데몬(daemon) 프로그램의 이해

데몬(daemon) 프로그램의 이해

Daemon 프로그램은 보통 telnet, httpd, mysql과 같은 각종 서버를 background 상태에서 돌아가는 프로그램을 말한다. 그러나 background 프로그램과 Daemon 프로그램은 엄연한 차이가 있다.

일반적인 background 프로그램은 터미널을 가지지만, Daemon 프로그램은 터미널을 가지지 않는다.
왜냐하면 보통 데몬프로그램은 특별한 일이 없는한 사용자와 상호대화할 필요 없이 아무도 모르게 실행되어야 하기 때문이다.
또한 모든 데몬 프로그램은 PPID 즉 부모 프로세스가 1번으로 세팅되며, 이는 데몬 프로그램의 관리프로세스는 1번 pid 를 가지는 init 가 담당함을 의미한다.

$ ./my_server&
$ ps -efjc
UID PID PPIDPGID SID CLS PRI STIME TTY TIME CMD
yundream 4314 4219 4314 4175- 3015:36 ttyp0 00:00:00 ./my_server&

$ ./my_server
-D
$ ps -efjc
UID PID PPIDPGID SID CLS PRI STIME TTY TIME CMD
yundream 43191 4319 4319 - 30 15:37 ? 00:00:00 ./my_server


위의 화면은 my_server란 프로그램을 백그라운드 모드로 실행시켰을 경우와 -D 옵션을 줘서 데몬모드로 실행시켰을때의 ps 정보를 보여준다.
데몬 프로세스의 경우를 보면 알겠지만, PPID가 1로 세팅되어 있으며 TTY 즉 터미널을 가지지 않음을 알수 있다. 그리고 SID 역시 자신의 PID와 같다는것을 알수 있다.

그럼 이제 실질적으로 데몬 프로그램을 만들도록 해보자, 데몬 프로그램을 만드는 핵심은 바로 위에서 설명한대로 터미널을 가지지 않으며 PPID가 1인 프로세스를 만드는 것으로 아래와 같은 코딩 규칙을 이용해서 작성가능하다.
1. 우선 fork를 호출해서 자식프로세스를 생성시킨 다음 부모프로세스를 종료시킨다.
2. setsid를 이용하여 새로운 세션을 만들고, 현재프로세스(자식)의 PID가 세션의 제어권을 가지도록 한다.
3. chdir을 이용하여 프로세스가 루트디렉토리에서 작업을 수행하도록 변경시켜준다.

1번을 이해하려면 fork에 대한 이해가 필요한데, 기본적으로 부모프로세스가 자식프로세스를 fork 했을경우 해당 자식프로세스의 PPID는 부모프로세스의 ID가 된다. 그런데 자식이 죽기전에 부모프로세스가 죽어버리면 자식프로세스의 PPID는(다시말해서 자식프로세스의 소유 프로세스) 누가될까? 부모 프로세스는 이미 죽었으므로 PPID가 될수 없을 것이다. 이럴 경우 자동적으로 자식프로세스의 관리 프로세스는 PID 1번인 init가 담당하게 된다.

2번의 setsid 는 새로운 새션을 생성하기 위해서 사용한다. 보통 세션은 자신의 세션을 위한 tty를 가져야 되는데, 새로운 세션을 생성하면 여기에 tty를 부여해 주어야 한다. 그렇지 않게 될경우 터미널을 가지지 않은 세션이 생성되게 된다. 세션(Session)에 대한 논의는 다른 문서를 참고하기 바라고, 간단히 생각해서 세션이란 프로그램 그룹의 모음이라고 일단은 생각해주길 바란다. 어쨋든 이렇게 해서 프로세스는 자신만의 독자적인 길을 걷게 된다.

3번은 선택사항이다. 굳이 해주지 않아도 되지만, 데몬 프로그램에서 여러가지 파일을 읽고 쓰는 작업을 할때 상대경로를 명시함으로써 일어나는 혼동을 피하기 위해서 권장하는 방법이라고 생각하면 될것이다.

데몬프로세스의 위의 3가지 조건만 만족시켜주면 된다. 그럼 예제를 통해서 실제 데몬 프로그램을 만들어서 실행시키고, 그 결과를 확인해 보도록 하자.

예제 daemon.c

#include
#include
#include
#include

int
main()
{
pid_t pid;

if ((pid =
fork()) < 0)
exit(0);

else if (pid != 0) //부모프로세스를 종료한다.
exit(0);

chdir("/");

setsid();
while (1) //여기에 프로그램 본체를 넣는다.
{
sleep(1);
}
}

아주 간단하게 데몬프로그램을 만들수 있음을 알수 있다.이제 결과를 한번 확인해 보도록 하자.

$ ./daemon
$ ps -efjc | grep daemon
UID PID PPIDPGID SID CLS PRI STIME TTY TIME CMD
yundream187101 18710 18710 - 30 23:42 ? 00:00:00 ./daemon

PPID가 1로 되어 있고 SID가 자신의 PID로 되어있으며 tty를 가지지 않은 프로세스가 만들어졌음을 알수 있을것이다.
모든 프로그램에 위의 코드만 추가시켜주면 어렵지 않게 데몬프로그램을 제작할수 있을 것이다.

데몬 프로세스를 만드는 코드

프로세스를 데몬화하는 간단한 프로그램이다.

인자로 mode가 주어지는데 이것은 데몬프로세스를 디버깅모드로 돌릴 것인지를 결정하기 위해서 사용한다. 만약 0이 아니라면 디버깅 모드로 작동하며 여러가지 메시지를 출력한다.

int main()
{
makedaemon(debug);

}

void makedaemon(int mode)
{
pid_t pid;

if ((pid = fork()) < 0)
exit(0);

else if (pid != 0)
exit(0);

if (mode == 0)
{
close(0);
close(1);
}
setsid();
}