fork 서브 프로 세 스 좀 비 문제 및 해결 방안

9847 단어 해결 방안
어, 원래 c 로 cgi 를 쓸 때 포크 를 사용 한 적 이 있어 요.그 때 는 cgi 의 생명 이 매우 짧 았 기 때문에 만난 문 제 는 전혀 발생 하지 않 았 다.이번에 도 더욱 깊이 있 게 포크 메커니즘 에 대해 알 아 봤 습 니 다.
여기 문서 참조:http://ju.outofmemory.cn/entry/98971
 
1. 우 리 는 모두 좀 비
다음은 이번 애플 리 케 이 션 의 fork 예 입 니 다.주 프로 세 스 는 데이터 처 리 를 계속 하고 일정 시간 후에 아래 코드 로 새 프로 세 스 를 열 고 처리 결 과 를 보 냅 니 다.별 문제 가 없 는 것 같 지만, 일정 시간 후, fork 는 항상 failed...프로 세 스 목록 을 ps aux 로 봅 니 다. 목록 이 좀 비 프로 세 스 로 가득 찼 습 니 다!!
...
        if ((pid=fork())<0)
        {
            printf("fork failed 
"); } else if ( 0 == pid) { test_result.error_1 = (double)error_1 / test_result.total * 10000; test_result.error_2 = (double)error_2 / test_result.total * 10000; test_result.error_4 = (double)error_4 / test_result.total * 10000; test_result.error_6 = (double)error_6 / test_result.total * 10000; n = sendto(sock, &test_result, sizeof(test_result), 0, (struct sockaddr *)&addr_to, sizeof(addr_to)); exit(0); } ...

그래, 설마 exit (0) 이후 에 도 무엇 을 그리워 하고 있 는 거 야?그래서 다시 돌아 와 서 무엇이 가장 가능성 이 있 는 지 계속 모색 했다.
 
2. 아기 좀 비가 아빠 를 찾는다
그래, 마지막 으로 시선 이 여기까지 왔 어. SIGCHLD.일반적으로 부모 프로 세 스 는 항상 대기 상태 에 있 지 않 고 다른 코드 를 실행 해 야 하기 때문에 '대기' 작업 은 신호 체 제 를 사용 하여 이 루어 집 니 다.또는 하위 프로 세 스 가 작업 을 처리 한 후에 커 널 에서 SIGCHLD 신 호 를 보 냅 니 다.그래, 이 아 이 는 아버지 에 게 마지막 작별 인 사 를 해 야 해.
그 애 아빠 가 뭘 할 수 있 을 까?
1) 아기 아빠 도 없어 졌어 요.
2) 아기 아빠 는 이 아이 에 대한 소식 을 기다 리 며 고별 식 을 마치 고 각자 차 일 드 에 안착 한다.
3) 아기 아빠 는 "나 는 아들 이 없 으 니 귀 찮 게 하지 마"라 는 게시 물 을 올 렸 다.
음, 첫 번 째 는 긍정 적 인 것 입 니 다. fork 체제 의 타고 난 속성 때문에 아이 아빠 가 없 으 면 init 에 보 내 져 서 관리 하고 키 울 것 입 니 다.init 는 책임감 있 는 좋 은 아빠 입 니 다. 모든 것 을 잘 처리 할 것 입 니 다.그럼 이제 두 개 는 어떻게 된 거 죠?
 
3. 아기 좀 비 와 아빠 의 마지막 이별
하위 프로 세 스 의 완성 상황 을 감독 하 는 데 사용 되 며, fork 세트 는 waitpid () 와 wait () 두 함수 가 있 습 니 다.waitpid () 의 기능 은 wait () 와 유사 하지만, waitpid () 는 waitpid (- 1, NULL, 0) 와 같은 추가 옵션 을 제공 합 니 다.예 를 들 어 wait () 함수 가 막 혔 고 waitpid () 는 WNOHANG 옵션 을 제공 합 니 다. 호출 후 바로 돌아 오 며 반환 값 에 따라 결 과 를 판단 할 수 있 습 니 다.
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <malloc.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <unistd.h>
#include <fcntl.h>

#include <signal.h>

void signal_handler(int signo) {
    if (signo == SIGCHLD) {
        pid_t pid;
        while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
            printf("SIGCHLD pid %d
", pid); } } } void mysleep(int sec) { time_t start = time(NULL), elapsed = 0; while (elapsed < sec) { sleep(sec - elapsed); elapsed = time(NULL) - start; } } int main(int argc, char **argv) { signal(SIGCHLD, signal_handler); while (1) { pid_t pid = fork(); if (pid > 0) { // parent process mysleep(5); } else if (pid == 0) { // child process printf("child pid %d
", getpid()); return 0; } else { fprintf(stderr, "fork error
"); return 2; } } }

예 를 들 어 위의 코드.우 리 는 실패 할 때 까지 신호 처리 에 순환 체 를 사용 하여 waitpid () 를 계속 호출 합 니 다.시스템 이 바 쁠 때 두 개의 키 프로 세 스 가 끝나 면 SIGCHLD 신 호 를 한 번 만 보 내 고 wait () 한 번 만 기다 리 면 좀 비 프로 세 스 가 생 길 수 있 기 때문이다.(기본 sleep () 함 수 는 신 호 를 받 았 을 때 바로 돌아 오기 때문에 프레젠테이션 을 편리 하 게 하기 위해 mysleep () 함 수 를 정의 합 니 다.
 
4. 무책임 한 아빠 가 되 기
간단 합 니 다. 아래 의 이 말 을 통 해 운영 체제 에 모든 하위 프로 세 스 의 생사 에 관심 이 없다 는 것 을 알려 드 립 니 다.
signal(SIGCHLD, SIG_IGN);

그러나 이렇게 하 는 문 제 는 일부 BSD 시스템 이 이런 용법 을 지원 하지 않 는 다 는 점 이다.그래서 더 광범 위 한 것 은 wait 를 사용 하 는 것 이다.
 
perl 중
다음은 perl 에서 fork - waitpid 를 사용 하 는 코드 이자 제 가 쓴 것 도 아 닙 니 다.
#!/usr/bin/perl
sub REAPER { my $pid;
while (($pid = waitpid(-1, WNOHANG)) > 0) { print "SIGCHLD pid $pid
"; } }
$SIG{CHLD}
= \&REAPER; my $pid = fork(); if ($pid > 0) { print "[Parent] child pid $pid
"; sleep(10); } elsif ($pid == 0) { print "[Child] pid $$
"; exit; }

이것 은 c 와 기본적으로 같다.SIGCHLD 를 무시 하려 면 사용 가능 $SIG{CHLD} = 'IGNORE'

좋은 웹페이지 즐겨찾기