2017-12-02 236 views
1

我正在實施一個簡單的shell程序,實現&|按預期工作。 但是,我想處理中斷,以便在收到SIGINT的情況下,父(shell)和後臺進程不應該終止,但任何前臺進程都應該終止。 我已經初始化了一個信號和一個處理程序,但我想獲得有關如何針對每個進程處理它的不同建議。如何在SIGINT時僅終止前臺子進程?

void intHandler() { 
    flagInt = 0; 
    fprintf(stderr, "interrupt\n"); 

} 

int process_arglist(int count, char** arglist) { 
    struct sigaction childSig; 
    struct sigaction intSig; 
    intSig.sa_handler = intHandler; 
    sigaction(SIGINT, &intSig, NULL); 
    //initialize intSig 


    int flagBg = 0; //turned to 1 in case there's a & 
    int flagPipe = 0; //turned to 1 in case there's a | 
    int index = 0; //index of | 0 if there's none 

    //Check if there's & and set flagBg and sigaction 
    if (strcmp(arglist[count - 1], "&") == 0) { 
     flagBg = 1; 
     childSig.sa_handler = SIG_IGN; 
     childSig.sa_flags = 0; 
     if(sigaction(SIGCHLD, &childSig, NULL)<0){ 
      fprintf(stderr, "ERROR: sigaction failed\n"); 
      exit(1); 
     } 
    } 

    //Look for pipes 
    int i = 0; 
    while (i < count) { 
     if (strcmp(arglist[i], "|") == 0) { 
      flagPipe = 1; 
      index = i; 
     } 
     i = i + 1; 
    } 

    //Handle & 
    if (flagBg == 1) { 
     int pid = fork(); 
     if (pid < 0) { //check if fork failed 
      fprintf(stderr, "ERROR: fork failed\n"); 
      return 1; 
     } 
     if (pid == 0) { // Child's process 
      arglist[count - 1] = NULL; 
      if (execvp(*arglist, arglist) < 0) {  //execute the command 
       fprintf(stderr, "ERROR: execvp failed\n"); 
       exit(1); 
      } 
     } 
     if (pid > 0) { //Parent's process 
      return 1; 

     } 
    } 

    //Handle | 
    if (flagPipe == 1) { 
     //create a new process 
     arglist[index] = NULL; 
     int fd[2]; 
     if(pipe(fd)<0){ 
      fprintf(stderr, "ERROR: pipe failed\n"); 
      exit(1); 
     } 
     int pid = fork(); 
     if (pid < 0) { //check if fork failed 
      fprintf(stderr, "ERROR: fork failed\n"); 
      return 1; 
     } 

     if (pid == 0) { // Child's process 

      close(STDOUT_FILENO); 
      dup(fd[1]); 
      close(fd[0]); 
      close(fd[1]); 
      if (execvp(*arglist, arglist) < 0) {  //execute the first part of the commands 
       fprintf(stderr, "ERROR: execvp failed\n"); 
       exit(1); 
      } 
     } 
     if (pid > 0) { //Parent's process 
      int pid2 = fork(); 
      if (pid2 < 0) { 
       fprintf(stderr, "ERROR: fork failed\n"); 
       return 1; 
      } 
      if (pid2 == 0) { // Child's process 
       close(STDIN_FILENO); 
       dup(fd[0]); 
       close(fd[1]); 
       close(fd[0]); 
       if (execvp(arglist[index+1], arglist+index+1) < 0) {  //execute the second part of the commands 
        fprintf(stderr, "ERROR: execvp failed\n"); 
        exit(1); 
       } 
       exit(1); 
      } else { //Parent's process 
       close(fd[0]); 
       close(fd[1]); 
       waitpid(pid, 0, 0); 
       return 1; 
      } 

     } 
    } 

    //No & and no | 
    if (flagBg == 0 && flagPipe == 0) { 
     int pid = fork(); 
     if (pid < 0) { //check if fork failed 
      fprintf(stderr, "ERROR: fork failed\n"); 
      return 1; 
     } 
     if (pid == 0) { 
      if (execvp(*arglist, arglist) < 0) { //execute the command 
       fprintf(stderr, "ERROR: execvp failed\n"); 
       exit(1); 
      } 
     } else { 
      waitpid(pid, 0, 0); 
      return 1; 
     } 
    } 

    return 0; 

} 

回答

0

你不應該需要使用SIGINT sighandler重新發送SIGINT向右孩子。如果您在單獨的進程組中運行每個作業並使用tcsetpgrp來設置終端的前臺進程組,則Ctrl+C應該使終端爲您發送SIGINT到相應的進程組。

+0

什麼是與信號處理這個問題?我的想法是將SIGINT的默認處理程序設置爲SIG_IGN,並將其更改爲另一個處理程序,該程序在運行前臺進程時終止。不過,我不明白我應該在代碼中放置處理程序分配。 – Tam211

相關問題