2014년 6월 22일 일요일

[리눅스 시스템 프로그래밍] 6 세션과 프로세스 그룹

세션 시스템 호출

셸은 로그인 시점에 새로운 세션을 생성한다. 이러한 작업은 새로운 세션을 쉽게 생성하는 특수 시스템 호출을 사용해서 수행한다.
#include <unistd.h>

pid_t setsid (void);
setsid()는 새로운 세션 내부에 새로운 프로세스 그룹을 생성하며, 호출한 프로세스를 세션과 프로세스 그룹 모두의 리더로 만든다.(새로운 세션에서 제어하는 tty가 없는 유일한 구성원이 된다.) 이는 데몬이나 셸에 유용한 특성이다. 데몬은 세션 구성원과 터미널 제어를 원하지 않으며, 셸은 사용자가 로그인할 때마다 새로운 세션 생성을 원하기 때문이다.

여기서 tty는
유닉스 전문 용어로 tty는 단순히 읽기와 쓰기를 넘어 몇 가지 추가적인 명령어를 지원하는 디바이스 파일을 뜻합니다. 그리고 터미널은 사실상 이 tty와 동일한 의미로 사용됩니다. 일부 tty는 하드웨어 디바이스를 위해 커널이 제공하며 그 예로 키보드에서 들어오는 입력과 텍스트 모드 화면으로 나가는 출력, 시리얼 라인을 통해 전송되는 입출력이 있습니다. 그 외의 tty는 씬 커널 레이어를 통해 터미널 에뮬레이터라고 불리는 프로그램으로 제공되며 이런 tty를pseudo-tty로 부르기도 합니다. 터미널 에뮬레이터로는 Xterm(X 윈도우 시스템), Screen(프로그램과 다른 터미널 사이에 독립적인 계층을 제공), SSH(한 머신에서 프로그램으로 다른 머신의 터미널에 연결), Expect(스크립팅 터미널 인터랙션용) 등이 있습니다.
http://www.myservlab.com/144

성공하면 setsid()는 새롭게 생성된 세션의 세션 ID를 반환한다.
실패하면 호출은 -1을 반환하며 유일하게 가능한 errno 코드는 EPERM이다.(프로세스가 현재 프로세스 그룹 리더라는 사실을 알려준다.) 특정 프로세스가 프로세스 그룹 리더가 되지 않도록 만드는 확실한 방법은 fork이며,  부모 프로세스가 종료된 다음에 자식 프로세스가 setsid()를 수행하면 된다. 예를 들면 다음과 같다.


pid_t pid;

pid = fork ();
if (pid == -1) {
    perror ("fork");
        return -1;
    } else if (pid != 0)
        exit (EXIT_SUCCESS);

    if (setsid () == -1) {
        perror ("setsid");
        return -1;
    }

조금 덜 유용하긴 하지만, 현재 세션 ID를 얻으려면 다음과 같은 함수를 사용한다.

#define _XOPEN_SOURCE 500
#include <unistd.h>

pid_t getsid (pid_t pid);

getsid()는 pid가 가리키는 프로세스의 세션 ID를 반환한다. 오류 발생시 -1을 반환한다. 유일한 errno 값은 ESRCH로, pid가 유효한 프로세스에 대응하지 않음을 알려준다.
이 기능을 실제로 활용하는 경우는 드물며, 주로 진단 목적으로 쓰인다.

pid_t sid;

sid = getsid (0);
if (sid == -1)
    perror ("getsid"); /* 가능하지 않은 경우다. */
else
    printf ("My session id=%d\n", sid);


프로세스 그룹 시스템 호출

setpgid()를 호출하면 pid가 가리키는 프로세스의 그룹 ID를 pgid로 설정한다.

#define _XOPEN_SOURCE 500
#include <unistd.h>

int setpgid (pid_t pid, pid_t pgid);

-p230

출처 : 리눅스 시스템 프로그래밍, 로버트 러브 지음, 박재호 옮김, 한빛미디어 2009년 펴냄

댓글 없음:

댓글 쓰기