2016-05-09 3 views
2

Я делаю небольшой shell program.I хотят приостановить программу переднего плана в sigtstp_handler й sigchld_handler пожинать zombie .А когда я тип ctrl z, даже если у меня нет переднего план программы, то sigchld_handler еще получит SIGTSTP.Почему sigchld_handler получит SIGTSTP?

Signal(SIGINT, sigint_handler); /* ctrl-c */ 
    Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */ 
    Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */ 

обработчик

void sigchld_handler(int sig) 
{ 
    int status; 
    pid_t pid; 

    while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { 

     if (WIFEXITED(status)) { /*checks if child terminated normally */ 
      deletejob(jobs, pid); 
     } 

     if (WIFSIGNALED(status)) { /*checks if child was terminated by a signal that was not caught */ 
      printf("Job [%d] (%d) terminated by signal %d\n", pid2jid(pid), pid, WTERMSIG(status)); 
      deletejob(jobs,pid); 
     } 

     if (WIFSTOPPED(status)) {  /*checks if child process that caused return is currently stopped */ 
      getjobpid(jobs, pid)->state = ST; 
      printf("Job [%d] (%d) stopped by signal %d\n", pid2jid(pid), pid, WTERMSIG(status)); 
      //printf("[%d] Stopped %s\n", pid2jid(pid), jobs->cmdline); 
     } 

    } 
    if (pid < 0 && errno != ECHILD) { 
     printf("waitpid error: %s\n", strerror(errno)); 
    } 

    return; 
} 


void sigtstp_handler(int sig) 
{ 
    pid_t pid = fgpid(jobs);//Return PID of current foreground job, 0 if no such job 

    if (pid!=0){ 
     struct job_t *p = getjobpid(jobs, pid); 
     printf("kill %d %s %d\n",p->pid,p->cmdline,p->state); 

     kill(pid,SIGTSTP); 
    } 
    return; 
} 

void sigint_handler(int sig) 
{ 

    pid_t pid = fgpid(jobs); 
    if (pid!=0){ 
     struct job_t *p = getjobpid(jobs, pid); 
     printf("kill %d %s %d\n",p->pid,p->cmdline,p->state); 
     kill(pid,SIGINT); 
    } 
    return; 
} 

Я просто setpgid(0,0), после I fork дочернего процесса, то решить эту problem.but я не знаю, что происходит на самом деле ...

+0

В коде отсутствует 'sigint_handler'. Также покажите код, как вы установили эти обработчики. – fluter

+0

Вы имели в виду, что 'sigtstp_handler' получит сигнал' SIGTSTP'? – fluter

+0

, конечно, 'sigtstp_handler' получит' SIGTSTP'. Моя проблема: 'sigchld_handler' получит' SIGTSTP', даже не выполнил 'kill' – TIMFUNNY

ответ

0

Вы обязательно имеют передний процесс (если вы используете терминал). Если вы не запустили подпроцесс, то оболочка сама находится в состоянии переднего плана, так же как и приемник TSTP. Переднего плана/фонового управления требуется больше работы, чем просто обработка сигналов. Вам нужно установить группы процессов и объявить, какая группа является группой переднего плана.

Основными задачами являются:

  1. создать группу при запуске команды (setpgid)
  2. объявить группу в качестве переднего плана группы, если это необходимо (tcsetpgrp)
  3. сделать оболочку об изменениях состояния детей (обработка SIGCHLD и статус WIFSTOPPED/WSTOPPED и управление списком должностей соответственно
  4. сделать интерактивные оболочки нечувствительными к SIGTSTP (ig nore этот сигнал в оболочке)

Управление заданиями - это сложная задача, чтобы выполнить ... Прочитайте документацию очень тщательно.

+0

Как сделать интерактивные оболочки незаметными? В моем обработчике, если pid == 0, просто означает, что это процесс оболочки. – TIMFUNNY

+0

Я просто 'setpgid (0,0)', после того, как я развил дочерний процесс, затем решил эту проблему. Но я не знаю, что на самом деле происходит. – TIMFUNNY

Смежные вопросы