2017-05-23 14 views
0

루프에 fork를 사용하여 16 개의 하위 프로세스를 만든 상위 프로세스가 있습니다. 결국, 모든 하위 프로세스는 SIGUSR1 신호를 보내고, 이는 상위 프로세스의 핸들러 함수에 의해 처리됩니다.C - 여러 자식 - 서로 겹쳐 쓰는 신호

내 문제는 일부 어린이가 다른 어린이의 신호를 처리하는 동안 신호를 보내는 것입니다. 핸들러 함수가 멈추고 현재 신호를 무시하고 새로운 신호를 처리한다는 것을 읽었습니다.

처리기 기능의 시작 부분에 kill(0,SIGSTOP)을 전송하여 문제를 해결하려고 시도했지만 부모 프로세스도 중지됩니다. 이 신호를 아이들에게만 보낼 수있는 방법이 있습니까?

불가능할 경우 wait, waitpid and kill을 사용하면 목표를 달성 할 수 있습니까?

struct sigaction new_action; 
memset(&new_action, 0, sizeof(new_action)); 
new_action.sa_handler = my_signal_handler; 
new_action.sa_flags = SA_SIGINFO; 
if(0 != sigaction(SIGUSR1, &new_action, NULL)) 
{ 
    printf("Signal handle registration failed. %s\n", strerror(errno)); 
    return -1; 
} 
for(int i=0; i<16; i++){ 
    pid_t cpid = fork(); 
    if(cpid == 0) // child 
    { 
     execv("./counter",argvv); // some arguments to the function 
     printf("execv failed: %s\n", strerror(errno)); 
     return -1; 
    } 
    else{ 
     continue; 
    } 

:

void my_signal_handler(int signum, siginfo_t* info, void* ptr) 
{ 
    kill(0, SIGSTOP); 
    int sonPid = info->si_pid; 
    char* pipeName = malloc(14 + sizeof(int));//TODO ok? 
    sprintf(pipeName, "//tmp//counter_%d" , (int) sonPid); //TODO double //? 
    size_t fdPipe = open(pipeName, O_RDONLY); 
    int cRead; 
    int countRead = read(fdPipe,&cRead,sizeof(int)); 
    COUNT+= cRead; 
    kill(0, SIGCONT); 
    return; 
} 

자식 프로세스를 만들기 :

추가 아래 코드, 나는

처리기 기능 등 오픈 읽기에 대한 반환 값을 확인 같은 물건을 왼쪽으로 즉, 그것은 어린이의 카운터 프로그램, 즉 그것은 파일의 일부에서 counc 숯의 모양을 계산 다음 파이프에 인쇄합니다. :

int main(int argc, char** argv){ 
    int counter = 0; 
    char counc = argv[1][0]; 
    char* filename = argv[2]; 
    off_t offset = atoll(argv[3]); 
    ssize_t length = atoll(argv[4]); 
    int fd = open(filename, O_RDWR | O_CREAT); 
    char* arr = (char*)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); 
    for(int i=0; i<length; i++){ 
     if(arr[i] == counc){ 
      counter++; 
     } 
    } 
    pid_t proid = getpid(); 
    pid_t ppid = getppid(); 
    char* pipeName = malloc(14 + sizeof(pid_t)); 
    sprintf(pipeName, "//tmp//counter_%d" , (int) proid); 
    size_t fdPipe = mkfifo(pipeName, 0777); 
    int didopen = open(pipeName,O_WRONLY); 
    size_t wrote = write(fdPipe,&counter , 1); 
    if(wrote < 0){ 
     printf(OP_ERR, strerror(errno)); 
     return errno; 
    } 
    kill(ppid, SIGUSR1); 
//close the pipe and unmap the array 
return 1; 
} 
+0

코드를 [최소, 완료 및 검증 가능한 예제] (https://stackoverflow.com/help/mcve)로 게시하십시오 (페이지를주의 깊게 읽으십시오). – Arash

+0

이 경우에는 설명이 괜찮을 것이라고 생각했지만 곧 코드 예제를 추가하겠습니다. – Gray

+0

이것은 사실이 아닙니다. 처리되는 신호는 처리기가 끝날 때까지 차단되므로 모두가 동일한 신호를 보내면 정상적으로 처리됩니다. 일부 코드는 ** 실제 ** 문제를 식별하는 데 도움이됩니다. Btw, 핸들러를 짧게 유지하고 플래그 만 설정하고 신호 처리기 외부에서 복잡한 처리를 수행하십시오. –

답변

0

질문을 올바르게 이해하면 아버지와 자녀가 원하는 신호 기능을 별도로 사용하는 데 문제가 있습니다. 이게 네 사건이 아니라면 내가 바로 잡아라.

문제가있는 경우 if 문을 만들고 pid을 호출하여 fork() 호출이 반환되는지 확인한 다음 자신이 아버지 인 경우에만 실행하십시오. 그래서 ... 당신이 전역 변수로 size_t pid을 정의해야

if (pid == 0) 
      //ChildProcess(); 
      // do nothing! 
    else 
      //ParentProcess(); 
      // do something! 

주 두 주에 볼 수 있도록하고, 신호 처리기 함수 당신이 구현된다!

+0

그게 아니라 - 문제는 부모 프로세스에 16 명의 자식이 있고 자식 1의 신호를 처리 할 때 자식 2가 자식의 신호를 보내는 새로운 신호를 보낸다는 것이다 1이 제대로 처리되지 않았습니다. – Gray

+0

그러면 어떤 PID가 어떤 자식을 참조하는지 미리 정의하고 이와 같은 if 문을 생성해야합니다. – Diaman

0

게다가 다른 사람은 이미 시그널 핸들러 내에서 비 ​​비동기 안전 기능의 사용에 대한 지적 것을, 나는 거 사지에 나가서 문제가이 두 가지 중 하나를이라고 생각 해요 :

  1. kill을 통해 전송 된 신호가 전송되는 프로세스에 대기하고 있다고 잘못 가정합니다. 그들은 대기열에 올라 있지 않습니다 (지원하는 운영 체제에서 sigqueue을 사용하지 않는 한). 대상 프로세스에 대한 보류중인 (아직 처리되지 않은) 신호 세트가 대신 업데이트됩니다. signal queuing in C을 참조하십시오. 또는
  2. "신뢰할 수있는 신호 의미론"을 지원하지 않는 운영 체제에서이 코드를 실행하고 있습니다.같은 통찰력 (공포)에 대한 man 3 sysv_signal를 참조하십시오 :

() 시스템 V 신뢰할 수없는 신호의 의미, 즉를 제공하지만 sysv_signal : A) 신호의 처리가 핸들러가 호출되는 기본으로 재설정됩니다; b) 신호 처리기가 실행되는 동안 신호의 추가 인스턴스 전달이 차단되지 않습니다.