nginx 학습 13 초기 fork 와 nginx 데 몬 ngxdaemon

nginx 를 공부 한 지 한 달 이 넘 었 습 니 다. 점점 힘 들 어 지고 있 습 니 다. 주요 원인 은 스스로 정 리 했 습 니 다. 1 플랫폼 은 Liux 를 바탕 으로 하 는 것 입 니 다. 예전 에 Liux 를 거의 접 한 적 이 없 었 고 nginx 는 Liux 의 함 수 를 많이 사 용 했 습 니 다.2. 프로 세 스 입 니 다. 이것 은 접촉 하 는 것 도 적 습 니 다. Liux 의 다 중 프로 세 스 는 말 할 필요 도 없습니다. 지금 마침 이곳 을 보고 매우 힘 들 어 합 니 다. 이것 은 nginx 데 몬 의 구축 을 보지 못 하고 자 료 를 찾 아 열심히 공부 하 겠 습 니 다. 그래서 본 고 는 fork 를 주요 내용 으로 배 웠 습 니 다.
자, nginx 의 데 몬 생 성 을 보고 fork 를 배우 고 있 습 니 다.
http://blog.csdn.net/xiaoliangsky/article/details/39998373
1nginx 데 몬
코드 직접 보기:
ngx_int_t ngx_daemon(ngx_log_t *log)
{
    int  fd;

    switch (fork()) {// fork      
    case -1://fork  -1    
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
        return NGX_ERROR;

    case 0://     
        break;

    default://     
        exit(0);//     
    }

    ngx_pid = ngx_getpid();

    if (setsid() == -1) {//      ,           
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
        return NGX_ERROR;
    }

    umask(0);//        

    /*       、   /dev/null(      )*/
    fd = open("/dev/null", O_RDWR);
    if (fd == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "open(\"/dev/null\") failed");
        return NGX_ERROR;
    }

    if (dup2(fd, STDIN_FILENO) == -1) {//      fd,  /dev/null  
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
        return NGX_ERROR;
    }

    if (dup2(fd, STDOUT_FILENO) == -1) {//      fd,      /dev/null
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
        return NGX_ERROR;
    }

#if 0
    if (dup2(fd, STDERR_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
        return NGX_ERROR;
    }
#endif

    if (fd > STDERR_FILENO) {
        if (close(fd) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}
여 기 는 설명 이 많 지 않 고 아래 의 내용 을 보면 위의 코드 가 매우 간단 하 다 는 것 을 알 수 있다.
2fork 함수
fork 에서 만 든 새 프로 세 스 를 하위 프로 세 스 (child process) 라 고 합 니 다.이 함 수 는 한 번 호출 되 었 으 나 두 번 되 돌 아 왔 다.두 번 의 반환 차 이 는 하위 프로 세 스 의 반환 값 이 0 이 고, 부모 프로 세 스 의 반환 값 은 새 프로 세 스 (하위 프로 세 스) 의 프로 세 스 id 입 니 다.하위 프로 세 스 id 를 부모 프로 세 스에 되 돌려 주 는 이 유 는 프로 세 스 의 하위 프로 세 스 가 하나 이상 일 수 있 기 때 문 입 니 다. 모든 하위 프로 세 스 의 프로 세 스 id 를 얻 을 수 있 는 함수 가 없습니다.하위 프로 세 스에 있어 서 fork 가 0 을 되 돌려 주 는 이 유 는 언제든지 getpid () 를 호출 하여 자신의 pid 를 가 져 올 수 있 기 때 문 입 니 다.부모 프로 세 스 의 id 를 가 져 오기 위해 getppid () 를 호출 할 수도 있 습 니 다.(프로 세 스 id 0 은 항상 교환 프로 세 스에 서 사용 되 기 때문에 하위 프로 세 스 id 가 0 일 수 없습니다.)fork 이후 운영 체 제 는 부모 프로 세 스 와 똑 같은 하위 프로 세 스 를 복사 합 니 다. 부자 관계 라 고 하지만 운영 체제 에서 볼 때 그들 은 형제 관계 와 같 습 니 다. 이 두 프로 세 스 는 코드 공간 을 공유 하지만 데이터 공간 은 서로 독립 되 어 있 습 니 다. 하위 프로 세 스 데이터 공간 에서 의 내용 은 부모 프로 세 스 의 완전한 복사 이 고 명령 포인터 도 똑 같 습 니 다.하위 프로 세 스 는 부모 프로 세 스 가 현재 실행 중인 위치 (두 프로 세 스 의 프로그램 카운터 pc 값 이 같 습 니 다. 즉, 하위 프로 세 스 는 fork 반환 에서 시작 합 니 다) 를 가지 고 있 지만, 한 가지 차이 가 있 습 니 다. fork 가 성공 하면 하위 프로 세 스 에서 fork 의 반환 값 은 0 입 니 다. 부모 프로 세 스 에서 fork 의 반환 값 은 하위 프로 세 스 의 프로 세 스 번호 입 니 다. fork 가 성공 하지 못 하면 부모 프로 세 스 는 오 류 를 되 돌려 줍 니 다.
열 을 열거 하 다.
int main()
{
	int   count;
	int   flag;
    pid_t pid;

    pid = fork();

    if (pid > 0)
    {
        printf("parent process is run
"); flag = 1; } else if (pid < 0) { printf("fork is error
"); exit(-1); } else { printf("child is run
"); flag = 0; } count = 0; if (flag) { printf("count in parent is : %d
", ++count); } else { printf("count in child is : %d
", ++count); } return 0; }
운행 결 과 는 다음 과 같다.
parent process is run
count in parent is : 1
child is run 
count in child is : 1
이 예 에서 알 수 있다.
1 부모 프로 세 스 와 하위 프로 세 스 가 같은 코드 를 실 행 했 습 니 다.
2. 부모 프로 세 스 와 하위 프로 세 스 는 데이터 공간 을 공유 하지 않 습 니 다. 그렇지 않 으 면 count 의 값 이 같 을 수 없습니다.
3fork 프로 세 스 가 두 번 되 돌 아 왔 고 부모 프로 세 스 가 돌아 올 때 pid 가 0 보다 크 며, 하위 프로 세 스 가 돌아 올 때 pid = 0 이 며, 하위 프로 세 스 는 돌아 올 때 부터 실 행 됩 니 다.
다음은 '고급 프로 그래 밍' 이 상세 하 게 소개 한 부자 프로 세 스 간 의 관계 다.
포크 에서 나 온 하위 프로 세 스 는 기본적으로 프로 세 스 번 호 를 제외 하고 부모 프로 세 스 의 모든 것 을 복사 합 니 다. 기본적으로 모든 것 이 아니 라 는 것 을 의미 합 니 다. 다음은 하위 프로 세 스 가 부모 프로 세 스에 서 무엇 을 물 려 받 았 는 지, 아무것도 물 려 받 지 않 았 다 는 것 을 말 합 니 다.하위 프로 세 스 는 부모 프로 세 스 자원 자체 가 아 닌 부모 프로 세 스 의 복사 만 받 을 수 있 음 을 주의해 야 합 니 다.하위 프로 세 스 에서 부모 프로 세 스 로 계승 하기:      1. 프로 세 스 의 자격 (real) / 유효 (effective) / 저 장 된 사용자 번호 (UID) 와 그룹 번호 (GID) 2. 환경 (environment) 3. 스 택 4. 메모리파일 설명자 설정 에 대해 POSIX. 1 은 모든 디 렉 터 리 흐름 이 exec 함수 호출 시 종료 되 어야 합 니 다. 더 자세 한 설명 은 'UNIX 환경 고급 프로 그래 밍' W. R. Stevens, 1993, 유 진원 등 역 (이하 '고급 프로 그래 밍'), 3.13 절 과 8.9 절 참조 7. 신호 (signal) 제어 설정 8. nice 값 설정(번역자 주: nice 값 은 nice 함수 로 설정 되 어 있 습 니 다. 이 값 은 프로 세 스 의 우선 순 위 를 표시 합 니 다. 수치 가 작 을 수록 우선 순위 가 높 습 니 다) 프로 세 스 스케줄 링 클래스 (scheduler class)(번역자 주: 프로 세 스 스케줄 링 카 테 고리 란 프로 세 스 가 시스템 에서 스케줄 링 될 때 속 하 는 카 테 고리 입 니 다. 카 테 고리 마다 우선 순위 가 다 릅 니 다. 프로 세 스 스케줄 링 카 테 고리 와 nice 값 에 따라 프로 세 스 스케줄 러 는 각 프로 세 스 의 전체 우선 순위 (Global process prority), 우선 순위 가 높 은 프로 세 스 를 계산 할 수 있 습 니 다. 8. 프로 세 스 그룹 번호 9. 대화 기 ID (Session ID) (번역자 주: 번역문 은'고급 프로 그래 밍' 이란 프로 세 스 가 속 한 대화 기 (session) ID 를 말 합 니 다. 하나의 대화 기 는 하나 이상 의 프로 세 스 그룹 을 포함 하고 '고급 프로 그래 밍' 9.5 절 참조) 10. 현재 작업 디 렉 터 리 11. 루트 디 렉 터 리 (번역자: 루트 디 렉 터 리 는 반드시 '/' 가 아니 라 chroot 함수 로 변경 할 수 있 습 니 다) 12. 파일 방식 으로 차단 자 (file mode creation mask (umask) 를 만 들 수 있 습 니 다.(번역자 주: 번역문 은 에서 추출 한 것 입 니 다. 새 파일 을 만 드 는 데 부족 한 차단 자 를 말 합 니 다) 13. 자원 제한 14. 터미널 하위 프로 세 스 만 의 고유: 프로 세 스 번호 1. 서로 다른 부모 프로 세 스 번호 (번역자 주: 즉, 하위 프로 세 스 의 부모 프로 세 스 번호 와 부모 프로 세 스 번호 가 다 르 고 부모 프로 세 스 번 호 는 getppid 함수 에서 얻 을 수 있 습 니 다) 2. 자신의 파일 설명자 와 디 렉 터 리 흐름 의 복사(번역자 주: 디 렉 터 리 흐름 은 opendir 함수 로 만 들 어 졌 습 니 다. 순서대로 읽 기 때문에 '디 렉 터 리 흐름' 이 라 고 부 릅 니 다) 3. 하위 프로 세 스 는 부모 프로 세 스 의 프로 세 스, 본문 (text), 데이터 와 다른 잠 금 메모리 (memory locks) 를 계승 하지 않 습 니 다.'The GNU C Library Reference Manual' 2.2 판, 1999, 3.4.2 절) 5. tms 구조 에서 시스템 시간 (번역자: tms 구 조 는 times 함수 에서 얻 을 수 있 습 니 다. 프로 세 스 를 기록 하기 위해 중앙 처리 장치 (CPU: Central Processing Unit) 를 사용 하 는 데 네 개의 데 이 터 를 저장 합 니 다.사용자 시간, 시스템 시간, 사용자 각 하위 프로 세 스 합계 시간, 시스템 각 하위 프로 세 스 합계 시간 포함) 6. 자원 사용 (resource utilizations) 을 0 8 로 설정 합 니 다. 차단 신호 집합 을 빈 집합 으로 초기 화 합 니 다.9. timer create 함수 로 만 든 타 이 머 를 계승 하지 않 음 10. 비동기 입력 과 출력 을 계승 하지 않 음
3 데 몬 생 성
데 몬배경 에서 실행 되 는 특수 한 프로 세 스 입 니 다. 터미널 을 제어 하 는 데 독립 되 어 있 으 며, 주기 적 으로 어떤 작업 을 수행 하거나 어떤 사건 을 처리 하 기 를 기다 리 고 있 습 니 다. 그 다음 데 몬 은 실행 전 환경 과 격 리 되 어야 합 니 다. 이 환경 은 닫 히 지 않 은 파일 설명자, 제어 터미널, 세 션 과 프로 세 스 그룹, 작업 디 렉 터 리, 파일 마스크 생 성 등 을 포함 합 니 다.항상 데 몬 은 부모 프로 세 스 (특히 셸) 에서 계승 합 니 다. 마지막 으로 데 몬 의 시작 방식 은 특별한 점 이 있 습 니 다. 리 눅 스 시스템 이 시 작 될 때 시작 스 크 립 트 / etc / rc. d 에서 시작 할 수 있 습 니 다. 작업 계획 프로 세 스 crond 에서 시작 할 수 있 고 사용자 터미널 (보통 셸) 에서 실행 할 수 있 습 니 다.
데 몬 생 성 절차:
1) 백그라운드 에서 실행
제어 단말 기 를 걸 지 않 기 위해 Daemon 을 백 엔 드 에 넣 고 실행 합 니 다. 방법 은 프로 세 스에 서 fork 를 호출 하여 부모 프로 세 스 를 종료 시 키 고, daemon 을 하위 프로 세 스에 서 백 엔 드 로 실행 시 키 는 것 입 니 다.
    pid = fork();
    if (pid > 0)
    {
        printf("parent is exit
"); exit(0);// }
2) 제어 단말기 에서 벗 어 나 세 션 과 프로 세 스 그룹 에 로그 인 합 니 다.
Linux 의 프로 세 스 와 제어 터미널, 로그 인 세 션 과 프로 세 스 그룹 간 의 관계: 프로 세 스 는 하나의 프로 세 스 그룹 에 속 합 니 다. 프로 세 스 그룹 번호 (GID) 는 프로 세 스 팀장 의 프로 세 스 (PID) 입 니 다.로그 인 세 션 은 여러 프로 세 스 그룹 을 포함 할 수 있 습 니 다. 이 프로 세 스 그룹 은 제어 단말 기 를 공유 합 니 다. 이 제어 단말 기 는 보통 프로 세 스 를 만 드 는 로그 인 터미널 입 니 다. 제어 단말 기 는 로그 인 세 션 과 프로 세 스 그룹 이 부모 프로 세 스에 서 계승 되 는 것 입 니 다. 우리 의 목적 은 프로 세 스 의 영향 을 받 지 않도록 하 는 것 입 니 다. 방법 은 첫 번 째 점 을 바탕 으로 setsid () 를 호출 하 는 것 입 니 다.프로 세 스 를 세 션 팀장 으로 만 들 기:
if (setsid() == -1)
{
	printf("setsid is failed
"); }
setsid () 호출 에 성공 하면 프로 세 스 는 새로운 세 션 팀장 과 새로운 프로 세 스 팀장 이 되 고 원래 로그 인 세 션 과 프로 세 스 그룹 과 분 리 됩 니 다. 세 션 과정 이 제어 단말기 에 대한 독점 성 때문에 프로 세 스 는 제어 단말기 와 분 리 됩 니 다.
3) 프로 세 스 가 제어 단말 기 를 다시 여 는 것 을 금지 합 니 다. (이 단 계 는 있 으 나 마 나 합 니 다. 상황 에 따라) 프로 세 스 는 터미널 이 없 는 세 션 팀장 이 되 었 습 니 다. 그러나 제어 단말 기 를 다시 열 어 달라 고 신청 할 수 있 습 니 다. 프로 세 스 가 더 이상 세 션 팀장 이 되 지 않도록 프로 세 스 가 제어 단말 기 를 다시 여 는 것 을 금지 할 수 있 습 니 다.
if(pid=fork()) exit(0); //       ,       (            )
4) 열 린 파일 이 있 으 면 열 린 파일 설명 자 를 닫 습 니 다.
프로 세 스 는 부모 프로 세 스 를 만 드 는 데 서 열 린 파일 설명 자 를 계승 합 니 다. 닫 지 않 으 면 시스템 자원 을 낭비 하여 프로 세 스 가 있 는 파일 시스템 을 지우 지 못 하고 예상 치 못 한 오 류 를 일 으 킬 수 있 습 니 다.
for(i=0;i<=getdtablesize();i++)
close(i)

5) 현재 작업 디 렉 터 리 (상황 에 따라) 프로 세 스 활동 을 변경 할 때 작업 디 렉 터 리 가 있 는 파일 시스템 을 해제 할 수 없습니다. 일반적으로 작업 디 렉 터 리 를 루트 디 렉 터 리 로 변경 해 야 합 니 다. 핵심 을 저장 해 야 하 는 프로 세 스 는 작업 디 렉 터 리 를 특정 디 렉 터 리 로 변경 합 니 다.
chdir("/tmp")

6) 파일 을 재 설정 하여 마스크 프로 세 스 를 만 듭 니 다. 부모 프로 세 스에 서 파일 을 계승 하여 마스크 를 만 듭 니 다. 데 몬 이 만 든 파일 의 액세스 위 치 를 수정 할 수 있 습 니 다. 이 를 방지 하기 위해 파일 을 마스크 로 만 듭 니 다.
umask(0);
ok, 기본 절차 가 완료 되 었 습 니 다. nginx 의 damon 프로 세 스 는 절차 1, 2, 6 만 있 습 니 다. 보통 이 3 단계 만 있 으 면 됩 니 다. 하지만 복잡 한 상황 은 절차 에 따라 쓰 십시오.
다음 에 우 리 는 하나의 예 를 보고 있다.
하위 프로 세 스에 서 파일 을 열 고 파일 에 데 이 터 를 기록 합 니 다. 일정한 조건 을 충족 시 킬 때 데 몬 이 종 료 됩 니 다.
void daemon_fork()
{
    pid_t pid;

    pid = fork();
    if (pid > 0)
    {
        printf("parent is exit
"); exit(0);// 1 } else if (pid < 0) { printf("fork is failed
"); exit(-1); } else { if (setsid() == -1)// 2 { printf("setsid is failed
"); } umask(000);// 6 printf("child is working
"); FILE *fp = fopen("test.txt", "a"); if (fp == NULL) { kill(pid, SIGTERM); } //do something int i = 0; for (;;) { fprintf(fp, "%s", (u_char*)("I am the deamon two
")); fprintf(fp, "i = %d
", ++i); sleep(10); if (i > 10) { fclose(fp); kill(pid, SIGTERM); } } } }

http://blog.csdn.net/xiaoliangsky/article/details/39998373
참고:
http://blog.csdn.net/theone10211024/article/details/13774669
http://blog.chinaunix.net/uid-25365622-id-3055635.html

좋은 웹페이지 즐겨찾기