Como o identificador de controle de trabalho do bash parou ou finalizou as tarefas em segundo plano?

2

Enquanto estudava os componentes internos do mecanismo de controle de tarefas do bash no Linux, me deparei com um pequeno problema de compreensão. Vamos supor o seguinte cenário:

script é executado em segundo plano | usuário @ linux: ~ # ./script.sh &

mesmo script é executado em primeiro plano ao mesmo tempo
usuário @ linux: ~ # ./script.sh

Agora, a primeira execução do script é executada como uma tarefa em segundo plano durante a segunda execução do script em primeiro plano. O Bash agora executa uma chamada de espera de bloqueio com o PID do processo de primeiro plano até que ele termine e, em seguida, obtém as informações correspondentes. Após o término do bash do processo forground, o status de todos os jobs em background é informado e informa sobre todas as alterações antes de retornar ao prompt. Este é geralmente o comportamento padrão chamado "+ b".

Mas existe um outro modo chamado "-b". Neste modo, o bash informa imediatamente sobre cada mudança de status do job em background. No meu entender, isso é feito enviando o sinal SIGCHLD pelo processo em segundo plano. Mas como poderia reagir a esse sinal de um processo de segundo plano terminado e imprimir uma mensagem no terminal, embora ele execute uma chamada de espera de bloqueio. Porque, na minha opinião, os sinais são tratados apenas antes de retornar ao modo de usuário.
O bash chama wait com a opção WNOHANG dentro de um loop até que o primeiro plano atual termine?

Além disso, ao operar no modo "-b", o bash pode gravar no terminal, embora não pertença ao grupo de processos em primeiro plano do terminal. Mesmo quando eu defino a opção "tostop" com stty, o bash pode gravar no terminal sem fazer parte do grupo de processos em primeiro plano. O bash obtém permissões especiais porque faz parte do grupo de processos de controle do terminal.

Espero poder esclarecer onde estão meus problemas de compreensão.

    
por idlmn89 13.04.2018 / 03:59

1 resposta

1

Sim, bash usa waitpid() com WNOHANG em um loop. Você pode ver isso em waitchld() in jobs.c :

static int
waitchld (wpid, block)
     pid_t wpid;
     int block;
{

...

  do
    {
      /* We don't want to be notified about jobs stopping if job control
         is not active.  XXX - was interactive_shell instead of job_control */
      waitpid_flags = (job_control && subshell_environment == 0)
                        ? (WUNTRACED|wcontinued)
                        : 0;
      if (sigchld || block == 0)
        waitpid_flags |= WNOHANG;

...

  if (block == 1 && queue_sigchld == 0 && (waitpid_flags & WNOHANG) == 0)
    {
      internal_warning (_("waitchld: turning on WNOHANG to avoid indefinite block"));
      waitpid_flags |= WNOHANG;
    }

  pid = WAITPID (-1, &status, waitpid_flags);

...

  /* We have successfully recorded the useful information about this process
     that has just changed state.  If we notify asynchronously, and the job
     that this process belongs to is no longer running, then notify the user
     of that fact now. */
  if (asynchronous_notification && interactive)
    notify_of_job_status ();

  return (children_exited);
}

A função notify_of_job_status() simplesmente escreve para o bash process 'stream de erro padrão.

Infelizmente, não posso dizer muito se a configuração de tostop com stty deve influenciar o shell em que você faz isso.

    
por 13.04.2018 / 08:57