2016-04-13 28 views
0

Kodumda nerede "çocuklar bitene kadar beklemeliyim"? Özel bir kabuğa benzer bir C programım var. Şimdi sıralı ortam değişkenlerini yazdırabilen bir yerleşik işlev checkEnv var. Ortam değişkenlerini sayarken Şimdi çıkış sonlandırma sinyali yakalamak istiyorumHangi sinyali kullanmalıyım ve nasıl yapmalıyım?

if(StartsWith(line, "checkEnv")) { 
    built_in_command=1; 
    pagerValue = getenv ("PAGER"); 
    if (! pagerValue) { 
     if (ret == 0) { 
     pager_cmd[0]="less"; 
     } else { 
     pager_cmd[0]="more"; 
     } 
    } 
    else { 
    pager_cmd[0]=pagerValue; 
    } 


    if(i==1) { 
     cmd[0].argv= printenv; 
     cmd[1].argv= sort; 
     cmd[2].argv= pager_cmd; 
     fork_pipes(3, cmd); 


    } 
    else { 

    for (k = 1; k < i; k++) 
    { 
     len += strlen(argv2[k]) + 2; 
    } 
    tmp = (char *) malloc(len); 
    tmp[0] = '\0'; 
    for (k = 1; k < i; k++) 
    { 
     pos += sprintf(tmp + pos, "%s%s", (k == 1 ? "" : "|"), argv2[k]); 
    } 
    grep[0]="grep"; 
    grep[1]="-E"; 
    grep[2]= tmp; 
    grep[3]= NULL; 
    cmd2[0].argv= printenv; 
    cmd2[1].argv= grep; 
    cmd2[2].argv= sort; 
    cmd2[3].argv= pager_cmd; 
    fork_pipes(4, cmd2); 
    free(tmp); 

      } 

:

$ ./a.out 
miniShell>> checkEnv 
"'><;|&(: 
_=./a.out 
CLUTTER_IM_MODULE=xim 
COMPIZ_CONFIG_PROFILE=ubuntu 
COMP_WORDBREAKS=   
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-mh5oMhyCI6 
DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path 
DESKTOP_SESSION=ubuntu 

arkasında kod şudur vermez: Yani benim kabuk başlatmak ve benim ortam değişkenleri listeleyebilirsiniz çağrı programını kullanarak program tüm programı sonlandırmak yerine özel kabuğa geri döner. Bu yüzden bazı sinyal işlemlerini kullanmam gerektiğini, ama nasıl ve hangi sinyali kullanmalıyım?

Gerçek çatal bu işlevden kaynaklanır.

/* Helper function that forks pipes */ 
void fork_pipes(int n, struct command *cmd) { 
    int i; 
    int in = 0; 
    int fd[2]; 
    /** loop and fork() */ 
    for (i = 0; i < n - 1; ++i) { 

     if (pipe(fd) == -1) { 
      err_syserr("Failed creating pipe"); 
     } 

     spawn_proc(in, fd[1], cmd + i); 
     close(fd[1]); 
     in = fd[0]; 
    } 
    if (dup2(in, 0) < 0) { 
     err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]); 
    } 
    fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd[i].argv[0]); 
    execvp(cmd[i].argv[0], cmd[i].argv); 
    err_syserr("failed to execute %s: ", cmd[i].argv[0]); 
} 

Sinyal işleme nereye gitmeli? Ne yapmaya çalıştığımın en az çalışan örneği nerede? Bunun bir örneği görmüyorum ve bence bu belgeler korkunç, sadece parçacıklar ve tam bir örnek değil.

My yardımcı işlevi

/* Helper function that spawns processes */ 
int spawn_proc(int in, int out, struct command *cmd) { 
    pid_t pid; 
    pid = fork(); 
    if (pid == 0) { 
     if (in != 0) { 
      if (dup2(in, 0) < 0) 
       err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]); 
      close(in); 
     } 
     if (out != 1) { 
      if (dup2(out, 1) < 0) 
       err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]); 
      close(out); 
     } 
     printf("** we are executing parent ***"); 
     fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd->argv[0]); 
     execvp(cmd->argv[0], cmd->argv); 
     err_syserr("failed to execute %s: ", cmd->argv[0]); 
    } 
    else if (pid < 0) { 
     err_syserr("fork failed: "); 
    } else { 
     /* */ 
     printf("** we are the parent ***"); 
    } 
    return pid; 
} 

main() şimdi şuna benzer Benim: Ben gdb benim kabuk çalıştırırsanız

int main(int argc, char *argv[]) { 

    sourceCount = 0; 
    const char *commandFile; 

    commandFile = NULL; 
    char *pathValue; 
/* struct sigaction sa, osa; 
    struct sigaction sa2;*/ 
    int errflag; 
    int cOption; 
    struct sigaction action; 
    /* use getopt_long() */ 
    char *argv1[] = {"version", "par2", 0}; 
/* char *argv2[] = {"help", "-m", "arg1", 0};*/ 

    /* use sigaction */ 

    sigemptyset(&action.sa_mask); 
    action.sa_handler = handle_sigchld; 
    action.sa_flags = 0; 

    sigaction(SIGPIPE, &action, NULL); //Not work with kill -13 process_id 
    //works well 
    sigaction(SIGINT, &action, NULL); //work with kill -2 process_id 

    errflag = 0; 

    /* use getopt_long() */ 
    while ((cOption = getopt(2, argv1, "m:t:n:fs?")) != -1) { 

     switch (cOption) { 
      case 'a': 
       printf("apples\n"); 
       break; 
      case 'b': 
       printf("bananas\n"); 
       break; 
      case 't': 
       printf("tree = %s\n", optarg); 
       break; 
      case '?': 
       ++errflag; 
       break; 
     } 
    } 
/* 
    while ((cOption = getopt (3, argv2, "m:t:n:fs?")) != -1) { 
     switch (cOption) { 
      case 'm': 
       printf("\n Help msg : %s \n", optarg); 
       exit(0); 
      case '?': 
       printf("\n -? Arg : %s \n", optarg); 
       break; 
      case 'n': 
       printf("\n -n Arg : %s \n", optarg); 
       break; 
     } 
    } 
*/ 


    /* get the PATH environment to find if less is installed */ 
    pathValue = getenv("PATH"); 
    if (!pathValue || getenv("PATH") == NULL) { 
     printf("'%s' is not set.\n", "PATH"); 

     /* Default our path if it is not set. */ 

     putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc"); 
    } 
    else { 
     printf("'%s' is set to %s.\n", "PATH", pathValue); 
    } 
    exec_program(commandFile); 
    return (0); 
} 

Ben normal bir çıkışı olsun.

(gdb) run 
Starting program: /home/dac/ClionProjects/shell2/openshell/shell 
'PATH' is set to /home/dac/proj/google-cloud-sdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin. 
dac:/home/dac/ClionProjects/shell2/openshell $ checkenv 
7429: executing printenv 
7430: executing grep 
7417: executing less 
7431: executing sort 
process 7417 is executing new program: /bin/less 
[Inferior 1 (process 7417) exited normally] 
(gdb) 
+1

: Orijinal istekte

kodunuzu çok eksik, işte bir örnek gelirse? SIGPIPE? Gerçek kabuğun sana söylemeli. –

cevap

1

, bunu çocuğunuzun öldü ve şimdi hasat olduğunu dönünceye kadar sadece bekleyin() çağrısı, herhangi bir sinyal almak gerekmez. Kabuğunuz şimdi yeni bir görev yapmaya hazır. Programınızı sonlandırmak neden olan şey nedir sinyal

#include <stdio.h> 
#include <unistd.h> 
#include <wait.h> 

void foobar() 
{ 
    int pipe_fd[2]; 
    pid_t pid1, pid2; 

    pipe(pipe_fd); 

    pid1=fork(); 
    if (pid1 == 0) 
    { 
    /* child1 - let us pretend that we wanted to replace stdin and this child */ 
    close (0); 
    dup(pipe_fd[0]); 
    close(pipe_fd[0]); 
    close(pipe_fd[1]); 
    execlp("wc", "wc", NULL); 
    perror ("execlp(wc)"); 
    _exit(0); 
    } 

    pid2=fork(); 
    if (pid2 == 0) 
    { 
    /* child - let us pretent that we wanted to replace stdout */ 
    close (1); 
    dup(pipe_fd[1]); 
    close(pipe_fd[0]); 
    close(pipe_fd[1]); 
    execlp("ls", "ls", "-l", NULL); 
    perror ("execlp(ls)"); 
    _exit(0); 
    } 

    close(pipe_fd[0]); 
    close(pipe_fd[1]); 

    /* wait until children are finished */ 
    while ((pid1 >= 0) || (pid2 >= 0)) 
    { 
    pid_t pid; 
    int status; 
    pid = wait(&status); 
    if (pid < 0) 
    { 
     continue; 
    } 
    if (pid == pid1) 
    { 
     pid1 = -1; 
    } 
    if (pid == pid2) 
    { 
     pid2 = -1; 
    } 
    } 
} 

int main(int argc, char *argv[]) 
{ 
     foobar(); 
     return 0; 
} 
+0

Teşekkürler. Sadece 'çatal' zorunda kaldım ve ne yaptığımı biliyorum. –

1

Sen SIGCHLD yakalamak ve wait() işlevlerinden biri ile çocuk durumunu biçmek istiyoruz.

Aşağıdaki bilgiler online tutorial'dan alınmıştır. Ayrıca

void handle_sigchld(int sig) { 
    int saved_errno = errno; 
    while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {} 
    errno = saved_errno; 
} 

struct sigaction sa; 
sa.sa_handler = &handle_sigchld; 
sigemptyset(&sa.sa_mask); 
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; 
if (sigaction(SIGCHLD, &sa, 0) == -1) { 
    perror(0); 
    exit(1); 
} 

, büyük olasılıkla SIGPIPE görmezden isteyecektir.

ebeveyn olarak
struct sigaction sa; 
sa.sa_handler = SIG_IGN; 
sigemptyset(&sa.sa_mask); 
sa.sa_flags = 0; 
if (sigaction(SIGPIPE, &sa, 0) == -1) { 
    perror(0); 
    exit(1); 
} 
+0

Cevabınız için teşekkür ederiz. Biraz detaylandırır mısın lütfen? Bunu daha önce yapmadım ve bir C uzmanı değilim. –

+1

@ Programmer400 Eğiticiye bir bağlantı var. Burada daha fazla kopyalamanın bir anlamı yok sanırım ... –

+0

@EugeneSh. Kodda _where_ anlamıyorum, bekle() yapmalıyım, bu yüzden detaylar için fazladan ödüllendiriyorum. –

İlgili konular