2017-12-02 324 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