Linux 프로 세 스 이해 와 실천 (5) 데 몬 에 대한 자세 한 이야기

데 몬 및 그 특성 
    데 몬 의 가장 중요 한 기능 은 배경 에서 실행 되 는 것 입 니 다.이 점 에서 도스 의 상주 메모리 프로그램 인 TSR 은 이와 비슷 하 다.그 다음으로 데 몬 은 실행 전의 환경 과 격 리 되 어야 합 니 다.이 환경 은 닫 히 지 않 은 파일 설명자, 제어 단말기, 세 션 과 프로 세 스 그룹, 작업 디 렉 터 리, 파일 마스크 생 성 등 을 포함한다.이 환경 들 은 보통 부모 프로 세 스 (특히 셸) 에서 데 몬 을 계승 합 니 다.마지막 으로 데 몬 의 시작 방식 은 특별한 점 이 있 습 니 다.리 눅 스 시스템 이 시 작 될 때 시작 스 크 립 트/etc/rc. d 에서 시작 할 수 있 습 니 다. 작업 계획 프로 세 스 crond 에서 시작 할 수 있 고 사용자 터미널 (보통 셸) 에서 도 실행 할 수 있 습 니 다. 
    한 마디 로 하면 이러한 특수성 을 제외 하고 데 몬 은 일반 프로 세 스 와 거의 다 르 지 않다.따라서 데 몬 을 만 드 는 것 은 실제 적 으로 일반 프로 세 스 를 위 데 몬 의 특성 에 따라 데 몬 으로 바 꾸 는 것 입 니 다.만약 독자 가 진행 과정 에 대해 비교적 깊 은 인식 을 가지 고 있다 면 더욱 쉽게 이해 하고 프로 그래 밍 할 수 있 을 것 이다. 
2. 데 몬 프로 그래 밍 요점 
    앞에서 말 했 듯 이 유 닉 스 환경 에 따라 데 몬 의 프로 그래 밍 규칙 이 일치 하지 않 습 니 다.다행히도 수호 프로 세 스 의 프로 그래 밍 원칙 은 모두 같 지만 구체 적 인 실현 세부 사항 이 다르다 는 데 차이 가 있다.이 원칙 은 데 몬 의 특성 을 만족 시 키 는 것 입 니 다.아울러 리 눅 스 는 Syetem V 의 SVR 4 를 기반 으로 하고 Posix 기준 을 따 르 는 것 으로 BSD 4 보다 훨씬 편리 하 게 구현 된다.프로 그래 밍 요점 은 다음 과 같다. 
1. 백 스테이지 에서 실행 합 니 다. 
    제어 단말 기 를 끊 지 않도록 Daemon 을 배경 에 넣 고 실행 합 니 다.방법 은 프로 세 스 에서 fork 를 호출 하여 부모 프로 세 스 를 종료 시 키 고 Daemon 이 하위 프로 세 스 의 배경 에서 실행 하도록 하 는 것 입 니 다. 
    if(pid=fork()) 
    exit(0);//부모 프로 세 스 입 니 다. 부모 프로 세 스 를 끝내 고 하위 프로 세 스 를 계속 합 니 다. 
2. 제어 단말기 에서 벗 어 나 세 션 과 프로 세 스 그룹 에 로그 인 합 니 다. 
    먼저 Linux 의 프로 세 스 와 제어 단말 기 를 소개 할 필요 가 있 습 니 다. 로그 인 세 션 과 프로 세 스 그룹 간 의 관 계 는 프로 세 스 그룹 에 속 합 니 다. 프로 세 스 그룹 번호 (GID) 는 프로 세 스 팀장 의 프로 세 스 번호 (PID) 입 니 다.로그 인 세 션 은 여러 프로 세 스 그룹 을 포함 할 수 있 습 니 다.이 프로 세 스 그룹 들 은 제어 단말 기 를 공유 합 니 다.이 제어 단말 기 는 보통 프로 세 스 를 만 드 는 로그 인 터미널 입 니 다. 
   터미널 을 제어 합 니 다. 로그 인 세 션 과 프로 세 스 그룹 은 보통 부모 프로 세 스에 서 물 려 받 습 니 다.우리 의 목적 은 그것들 을 벗 어 나 그들의 영향 을 받 지 않도록 하 는 것 이다.방법 은 첫 번 째 점 을 바탕 으로 setsid () 를 호출 하여 프로 세 스 를 세 션 팀장 으로 만 드 는 것 입 니 다. 
setsid 함 수 는 새 세 션 을 만 들 고 이 세 션 그룹의 팀장 을 맡 는 데 사 용 됩 니 다.setsid 를 호출 하면 다음 세 가지 역할 이 있 습 니 다:
(1) 프로 세 스 를 원래 세 션 의 제어 에서 벗 어 나 게 합 니 다.
(2) 프로 세 스 를 원래 프로 세 스 그룹의 제어 에서 벗 어 나 게 합 니 다.
(3) 프로 세 스 를 원 제어 단말기 의 제어 에서 벗 어 나 게 한다.
     데 몬 을 만 드 는 첫 번 째 단계 에서 fork 함 수 를 호출 하여 하위 프로 세 스 를 만 들 고 부모 프로 세 스 를 종료 한 것 입 니 다.fork 함 수 를 호출 했 을 때 하위 프로 세 스 는 부모 프로 세 스 의 세 션 기간, 프로 세 스 그룹, 제어 터미널 등 을 모두 복사 하 였 습 니 다. 부모 프로 세 스 가 종료 되 었 지만 세 션 기간, 프로 세 스 그룹, 제어 터미널 등 은 변 하지 않 았 습 니 다. 따라서 이것 은 진정한 의미 에서 독립 된 것 이 아니 라 setsid 함수 가 프로 세 스 를 완전히 독립 시 켜 다른 프로 세 스 의 제어 에서 벗 어 날 수 있 습 니 다.
설명: 프로 세 스 가 세 션 팀장 일 때 setsid () 호출 에 실 패 했 습 니 다.첫 번 째 는 프로 세 스 가 세 션 팀장 이 아니 라 는 것 을 보증 합 니 다.setsid () 호출 에 성공 하면 프로 세 스 는 새로운 세 션 팀장 과 새로운 프로 세 스 팀장 이 되 고 원래 로그 인 세 션 과 프로 세 스 그룹 과 분 리 됩 니 다.세 션 프로 세 스 가 제어 단말기 에 대한 독점 성 때문에 프로 세 스 는 제어 단말기 와 분리 된다. 
3. 프로 세 스 가 제어 단말 기 를 다시 여 는 것 을 금지 합 니 다. 
     현재 프로 세 스 는 터미널 이 없 는 세 션 팀장 이 되 었 습 니 다.하지만 제어 단말 기 를 다시 열 어 달라 고 신청 할 수 있다.프로 세 스 가 더 이상 세 션 팀장 이 되 지 않도록 제어 단말 기 를 다시 여 는 것 을 금지 할 수 있 습 니 다. 
    if(pid=fork()) 
    exit(0);//첫 번 째 하위 프로 세 스 를 끝내 고 두 번 째 하위 프로 세 스 를 계속 합 니 다 (두 번 째 하위 프로 세 스 는 더 이상 세 션 팀장 이 아 닙 니 다) 
주의: 많은 독자 들 이 왜 두 번 의 프로 세 스 를 만 들 었 느 냐 고 물 을 것 입 니 다.두 번 째 단계 가 끝 난 후에 프로 세 스 가 새로운 세 션 그룹 을 만 들 고 세 션 팀장 이 되 었 기 때 문 입 니 다. 세 션 팀장 은 제어 단말 기 를 얻 을 수 있 습 니 다. 제어 단말 기 를 얻 었 다 면 이 프로 세 스 는 데 몬 이 아 닙 니 다.그래서 이 몇 개의 코드 를 추가 하여 프로 세 스 가 세 션 팀장 의 신분 을 잃 게 하여 터미널 을 제어 할 수 있 는 권한 을 얻 지 못 했 습 니 다.
4. 열 린 파일 설명자 닫 기 
파일 권한 코드 와 마찬가지 로 fork 함수 로 새로 만 든 하위 프로 세 스 는 부모 프로 세 스에 서 열 린 파일 을 계승 합 니 다.이 열 린 파일 들 은 데 몬 에 의 해 읽 히 지 않 을 수도 있 지만, 시스템 자원 을 소모 할 수도 있 고, 있 는 파일 시스템 을 해제 할 수 없 을 수도 있 습 니 다.
위의 두 번 째 단계 이후 데 몬 은 소속 제어 단말기 와 연락 이 끊 겼 습 니 다.따라서 터미널 에서 입력 한 문 자 는 데 몬 에 도달 할 수 없습니다. 데 몬 에서 일반적인 방법 (예 를 들 어 printf) 으로 출력 한 문자 도 터미널 에 표시 할 수 없습니다.그래서 파일 설명자
0, 1, 2 인 3 개의 파일 (흔히 말 하 는 입 출력 과 오류) 은 존재 하 는 가 치 를 잃 었 고 닫 혀 야 합 니 다.보통 다음 과 같은 방식 으로 파일 설명 자 를 닫 습 니 다.
for(i=0;i
close(i);
5. 현재 작업 디 렉 터 리 변경 
    이 단계 도 필요 한 절차 입 니 다. fork 를 사용 하여 만 든 하위 프로 세 스 는 부모 프로 세 스 의 현재 작업 디 렉 터 리 를 계승 합 니 다. 프로 세 스 실행 중 현재 디 렉 터 리 가 있 는 파일 시스템 (예 를 들 어 "/mnt/usb") 을 마 운 트 해제 할 수 없 기 때문에 앞으로 사용 하 는 데 많은 문제 가 발생 할 수 있 습 니 다. (예 를 들 어 시스템 이 어떤 이유 로 단일 사용자 모드 에 들 어가 야 합 니 다) 따라서 일반적인 방법 은 "/"입 니 다.데 몬 의 현재 작업 디 렉 터 리 로 서 위 와 같은 문 제 를 피 할 수 있 습 니 다. 물론 특별한 필요 가 있 으 면 현재 작업 디 렉 터 리 를 다른 경로 로 바 꿀 수도 있 습 니 다. 예 를 들 어/tmp. 작업 디 렉 터 리 의 일반적인 함수 식 chdir 를 바 꿀 수도 있 습 니 다.
6. 파일 재 설정 마스크 만 들 기 
  프로 세 스 는 부모 프로 세 스에 서 파일 생 성 마스크 를 계승 합 니 다. 데 몬 이 만 든 파일 의 액세스 위 치 를 수정 할 수 있 습 니 다. 이 를 방지 하기 위해 파일 생 성 마스크 를 제거 합 니 다: umask (0); 
7. SIGCHLD 신호 처리 
   SIGCHLD 신 호 를 처리 하 는 것 은 필수 가 아 닙 니 다. 그러나 일부 프로 세 스, 특히 서버 프로 세 스 는 요청 이 올 때 하위 프로 세 스 처리 요청 을 생 성 합 니 다. 부모 프로 세 스 가 하위 프로 세 스 가 끝 날 때 까지 기다 리 지 않 으 면 하위 프로 세 스 는 좀 비 프로 세 스 (zombie) 가 됩 니 다.시스템 자원 을 사용 합 니 다. 부모 프로 세 스 가 하위 프로 세 스 가 끝 날 때 까지 기다 리 면 부모 프로 세 스 의 부담 이 증가 하고 서버 프로 세 스 의 병행 성능 에 영향 을 줍 니 다. Linux 에 서 는 SIGCHLD 신호 동작 을 SIG IGN 으로 간단하게 설정 할 수 있 습 니 다. 
signal(SIGCHLD,SIG_IGN); 
이렇게 하면 커 널 은 하위 프로 세 스 가 끝 날 때 좀 비 프로 세 스 가 발생 하지 않 습 니 다. 이 점 은 BSD 4 와 달리 BSD 4 에 서 는 하위 프로 세 스 가 끝 날 때 까지 명시 적 으로 기 다 려 야 좀 비 프로 세 스 를 풀 수 있 습 니 다.
    Liux 의 프로 세 스 는 하나의 트 리 에 속 하기 때문에 트 리 의 뿌리 결산 점 은 Liux 시스템 초기 화 종료 단계 에서 시 작 된 init 프로 세 스 입 니 다. 이 프로 세 스 의 pid 는 1 입 니 다. 모든 프로 세 스 는 자손 입 니 다. init 를 제외 하고 모든 프로 세 스 는 부모 프로 세 스 가 있 을 것 입 니 다. 부모 프로 세 스 는 할당 (fork), 회수 (wait 4) 를 책임 집 니 다.프로 세 스 자원 을 신청 합 니 다. 이 트 리 의 관계 도 비교적 건장 합 니 다. 프로 세 스 가 실행 중 일 때 부모 프로 세 스 가 종료 되 었 습 니 다. 이 프로 세 스 는 고아 프로 세 스 가 되 지 않 았 습 니 다. Liux 는 하나의 메커니즘 이 있 기 때문에 init 프로 세 스 가 부모 프로 세 스 를 인수 하고 부모 프로 세 스 가 되 기 를 바 랍 니 다. 이것 도 데 몬 의 유래 입 니 다. 데 몬 의 요구 중 하 나 는 init 가 데 몬 이 되 기 를 바 라 는 것 입 니 다.프로 세 스 의 부모 프로 세 스.
    프로 세 스 자체 가 종료 되면 exit 를 호출 하여 관련 콘 텐 츠 파일 등 자원 을 정리 한 후에 ZOMBIE 상태 로 들 어 갑 니 다. 부모 프로 세 스 는 wait 4 를 호출 하여 이 task struct 를 회수 합 니 다. 그러나 부모 프로 세 스 가 wait 4 를 호출 하여 하위 프로 세 스 의 task struct 를 방출 하지 않 으 면 문제 가 발생 합 니 다. 이 task struct 는 누가 회수 합 니까? 아버지 가 들 어가 지 않 는 한 영원히 아무 도 없습니다.프로그램 종료 후 init 프로 세 스에 의 해 이 ZOMBIE 프로 세 스 를 연결 하고 wait 4 를 호출 하여 프로 세 스 설명 자 를 회수 합 니 다. 부모 프로 세 스 가 계속 실행 되 고 있다 면 이 ZOMBIE 는 시스템 자원 을 영원히 점용 할 것 입 니 다. KILL 로 어떠한 신 호 를 보 내 도 풀 수 없습니다. 서버 에 수많은 ZOMBIE 프로 세 스 가 생 겨 서 기계 가 꺼 질 수 있 기 때 문 입 니 다.
 8. 데 몬 종료 처리  사용자 가 외부 에서 데 몬 실행 을 중지 해 야 할 때 kill 명령 을 사용 하여 데 몬 을 정지 합 니 다. 따라서 데 몬 에 서 는 kill 이 보 내 는 signal 신호 처 리 를 인 코딩 하여 프로 세 스 의 정상 적 인 종료 에 도달 해 야 합 니 다. = = = = = = = = = = = = = = = = = = = = = = = = = signal (SIGTERM, sigterm handler), void sigterm handler (int arg) {    _running = 0;} = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 이렇게 하면 간단 한 데 몬 이 만들어 진다.
#include < unistd.h > 
#include < signal.h > 
#include < sys/param.h > 
#include < sys/types.h > 
#include < sys/stat.h > 
void init_daemon(void) 
{ 
    int pid; 
    int i; 
    if(pid=fork()) 
        exit(0);//    ,      
    else if(pid< 0) 
        exit(1);//fork  ,   
    //      ,       
    setsid();//                   
    //         
    if(pid=fork()) 
        exit(0);//      ,        
    else if(pid< 0) 
        exit(1);//fork  ,   
    //      ,   
    //             

    for(i=0;i< NOFILE;++i)//           
        close(i); 
    chdir("/tmp");//       /tmp 
    umask(0);//         
    return; 
} 
2. test.c   
#include < stdio.h > 
#include < time.h > 

void init_daemon(void);//          

main() 
{ 
    FILE *fp; 
    time_t t; 
    init_daemon();//    Daemon 

    while(1)//      test.log       
    { 
        sleep(60);//      
        if((fp=fopen("test.log","a")) >=0) 
        { 
            t=time(0); 
            fprintf(fp,"Im here at %s/n",asctime(localtime(&t)) ); 
            fclose(fp); 
        } 
    } 
} 

프로 세 스 보기: ps - ef 
출력 에서 test 데 몬 의 다양한 특성 이 위의 요 구 를 만족 시 키 는 것 을 발견 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기