Por que processos bifurcados às vezes aparecem com colchetes [] ao redor do nome em ps? [duplicado]

6

Em um sistema Linux, um processo C é iniciado na inicialização, o que cria um fork de si mesmo. Não é um processo de kernal ou algo assim. Na maioria dos casos, um ps -ef mostra ambos os processos como expecxted, mas às vezes se parece com o seguinte:

1258 root       0:00 myproc 
1259 root       0:00 [myproc]

i.e. um dos processos cercados por colchetes. De acordo com ps :

If the arguments cannot be located (usually because it has not been set, 
as is the case of system processes and/or kernel threads) the command name 
is printed within square brackets.

Eu não entendo o que significa quando os 'argumentos não podem ser localizados'. O processo é iniciado sempre exatamente da mesma forma e o fork é sempre criado exatamente da mesma maneira. Como pode acontecer que às vezes 'os argumentos não podem ser localizados' e às vezes eles podem?

Além disso, o processo é sempre iniciado sem quaisquer argumentos ...

Perguntas que tenho:

  • O que esses colchetes realmente significam? O processo é executado quando /proc/{pid}/cmdline está vazio?
  • Por que recebo esses colchetes às vezes e nem sempre?
  • Como / onde corrigir esse problema?

Informações adicionais:

  • O processo é sempre iniciado sem argumentos! Apenas o nome do comando myproc .
  • O processo principal parece estar sempre correto (sem colchetes ao redor do nome, executável em /proc/x/cmdline ).
  • O processo filho às vezes tem seu nome entre colchetes.
  • O conteúdo de /proc/child-pid/cmdline de um processo filho em execução correto é myproc .
  • O conteúdo de /proc/child-pid/cmdline de um processo filho em execução incorreto está vazio!
  • Novamente: o mesmo código, diferentes processos filhos!
por Alex 23.01.2014 / 15:11

2 respostas

8

ps -f normalmente mostra a lista de argumentos passada para a última chamada de sistema execve() que o processo ou qualquer um dos seus antecessores fez.

Quando você executa um comando xxx arg1 arg2 em um prompt do shell, seu shell geralmente bifurca um processo que procura um comando pelo xxx name e o executa como:

execve("/path/to/that/xxx", ["xxx", "arg1", "arg2"], @exported_variables)

Deve-se notar que o primeiro argumento é xxx .

Após a execução, toda a memória do processo é apagada e esses argumentos (e ambiente) são encontrados na parte inferior da pilha do processo.

Você obtém os primeiros 4096 bytes desses argumentos em /proc/<the-pid>/cmdline e é de onde ps obtém isso.

Em um fork ou clone, o filho herda toda a memória de seu pai, incluindo essa lista de argumentos.

Você recebe o [xxx] quando /proc/<the-pid>/cmdline está vazio. Nesse caso, em vez de exibir a lista arg, ps exibe o nome do processo que encontra em /proc/<the-pid>/stat (para comandos executados, são os primeiros 16 bytes da base do arquivo executável passado para o último execve() ). Isso pode acontecer por três razões (que eu posso pensar):

  • O processo ou qualquer um de seus ancestrais nunca executou nada. Esse é o caso dos encadeamentos do kernel (e só pode ser o caso dos encadeamentos do kernel, pois todos os outros processos são descendentes de init (que é executado)).

    $ ps -fp2
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         2     0  0 Jan13 ?        00:00:00 [kthreadd]
    
  • O processo executou um comando com uma lista vazia de argumentos. Isso geralmente nunca acontece porque geralmente os programas sempre passam pelo menos um argumento, o nome do comando, mas você pode forçá-lo com, por exemplo:

    int main(int argc, char *argv[]) {
      if (argc) execve("/proc/self/exe",0,0);
      else system("ps -fp $PPID");
    }
    

    Depois de compilado e executado:

    $ test1
    UID        PID  PPID  C STIME TTY          TIME CMD
    stephane 31932 29296  0 15:16 pts/5    00:00:00 [exe]
    
  • O processo sobrescreve seu argv[] em sua pilha.

    Os argumentos são sequências terminadas em NUL na memória. Se você tornar o último caractere da lista arg não nulo, por exemplo, com envp[0][-1]=1 (os valores envp[] seguem os argv[] na pilha), então o kernel assume que você o modificou e só retorna em /proc/xxx/cmdline o primeiro argumento até o primeiro caractere NUL. Então

    int main(int argc, char* argv[], char *envp[]) {
      envp[0][-1]=1;
      argv[0][0]=0;
      system("ps -fp $PPID");
    }
    

    Também mostraria [xxx] .

    Dado que o arglist (e environ) estão na parte inferior da pilha, esse tipo de cenário pode acontecer se você tiver um bug no código que faz com que você escreva na pilha após o final do que ele pretendia escreva, por exemplo, se estiver usando strcpy em vez de strncpy . Para depurar esse tipo de problema, valgrind é muito útil.

por 23.01.2014 / 16:41
2

Não há problema nisso. Quando ps não é capaz de determinar o caminho completo do comando porque os argumentos não estão disponíveis:

Sometimes the process args will be unavailable; when this happens, ps will instead print
the executable name in brackets. 

Extrato do homem

Veja também: link

    
por 23.01.2014 / 15:38