Por que o processo não faz parte do grupo de processos esperado?

5

Estou aprendendo sobre o relacionamento entre processos, grupos de processos (e sessões) no Linux.

Eu compilei o seguinte programa ...

#include <iostream>
#include <ctime>
#include <unistd.h>

int main( int argc, char* argv[] )
{
  char buf[128];
  time_t now;
  struct tm* tm_now;
  while ( true )
  {
    time( &now );
    tm_now = localtime( &now );
    strftime( buf, sizeof(buf), "%a, %d %b %Y %T %z", tm_now );
    std::cout << buf << std::endl;
    sleep(5);
  }
  return 0;
}

... para a.out e o executou como um processo em segundo plano, assim ...

a.out &

Este site diz o seguinte ...

Every process is member of a unique process group, identified by its process group ID. (When the process is created, it becomes a member of the process group of its parent.) By convention, the process group ID of a process group equals the process ID of the first member of the process group, called the process group leader.

Por minha leitura, a primeira sentença entra em conflito com o conteúdo entre parênteses: é um processo um membro de um grupo de processos exclusivo , ou é um membro do grupo de processos de seus pai ?

Eu tentei investigar com ps ...

ps xao pid,ppid,pgid,sid,command | grep "PGID\|a.out"
  PID  PPID  PGID   SID COMMAND
24714 23890 24714 23890 ./a.out

Isso me diz que meu a.out processo é pid 24714 , gerado a partir do pai pid 23890 e parte do grupo de programas 24714 . Para começar, não entendo porque esse pgid combina com o pid.

Em seguida, tentei investigar o processo pai ...

ps xao pid,ppid,pgid,sid,command | grep "PGID\|23890"
  PID  PPID  PGID   SID COMMAND
23890 11892 23890 23890 bash
24714 23890 24714 23890 ./a.out

Faz sentido para mim que o processo pai do meu a.out seja bash . No começo eu pensei que o pid do bash é igual ao pgid - deve ser porque é o líder do grupo de processos.Talvez isso faça sentido porque o bash é o tipo de "primeira coisa" que foi executada, da qual eu executei o meu processo. / em> "Mas esse raciocínio não faz sentido porque a.out 's pgid também corresponde ao seu próprio pid.

Por que o pgid de a.out não é igual ao pgid de bash ? Isso é o que eu esperava, da minha compreensão da citação.

Alguém pode esclarecer a relação entre pids e pgids?

    
por StoneThrow 04.05.2017 / 23:15

2 respostas

4

Não há conflito; um processo estará, por padrão, em um grupo de processos exclusivo, que é o grupo de processos de seu pai:

$ cat pg.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    fork();
    printf("pid=%d pgid=%d\n", getpid(), getpgrp());
}
$ make pg
cc     pg.c   -o pg
$ ./pg 
pid=12495 pgid=12495
pid=12496 pgid=12495
$ 

O fork divide nosso processo em pai ( 12495 ) e filho ( 12496 ), e o filho pertence ao grupo de processos exclusivo do pai ( 12495 ). bash se afasta disso porque emite chamadas adicionais do sistema:

$ echo $$
12366
$

E depois, em outro terminal, corremos:

$ strace -f -o blah -p 12366

E depois de volta ao primeiro terminal:

$ ./pg
pid=12676 pgid=12676
pid=12677 pgid=12676
$

E então nós controlamos + c o strace , e inspecionamos as chamadas do sistema:

$ egrep 'exec|pgid' blah
12366 setpgid(12676, 12676)             = 0
12676 setpgid(12676, 12676 <unfinished ...>
12676 <... setpgid resumed> )           = 0
12676 execve("./pg", ["./pg"], [/* 23 vars */]) = 0
12676 write(1, "pid=12676 pgid=12676\n", 21 <unfinished ...>
12677 write(1, "pid=12677 pgid=12676\n", 21 <unfinished ...>

bash usou a chamada setpgid para definir o grupo de processos, colocando assim o nosso processo pg no grupo de processos não relacionado ao do shell. ( setsid(2) seria outra maneira de ajustar o grupo de processos, se você estiver procurando por chamadas do sistema.)

    
por 04.05.2017 / 23:43
5

O Bash coloca seu programa em seu próprio grupo de processos como parte de seu controle de tarefas. Por exemplo, no bash manpage:

To facilitate the implementation of the user interface to job control, the operating system maintains the notion of a current terminal process group ID. Members of this process group (processes whose process group ID is equal to the current terminal process group ID) receive keyboard-generated signals such as SIG‐ INT. These processes are said to be in the foreground. Background processes are those whose process group ID differs from the terminal's; such processes are immune to keyboard-generated signals. Only foreground processes are allowed to read from or, if the user so specifies with stty tostop, write to the terminal. Background processes which attempt to read from (write to when stty tostop is in effect) the terminal are sent a SIGTTIN (SIGTTOU) signal by the kernel's terminal driver, which, unless caught, suspends the process.

Além disso, a parte sobre set -m :

Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL above). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.

Então, se você quer o comportamento que está esperando, você pode:

  1. Use fork dentro do código para criar um processo sem fazer nada.
  2. Use set +m para desativar o modo monitor no bash. Isso vai quebrar coisas como fg , embora.
por 04.05.2017 / 23:40