Pergunta

Para processos filhos, as funções wait() e waitpid() pode ser usado para suspende a execução do processo atual até que a criança saiu. Mas esta função não pode ser usada para processos não-criança.

Existe outra função, o que podemos esperar para a saída de qualquer processo?

Foi útil?

Solução

Nada equivalente a wait(). A prática usual é a sondagem usando kill(pid, 0) e olhando para o valor de retorno -1 e errno de ESRCH para indicar que o processo está desaparecido.

Outras dicas

Em BSDs e Mac OS X, você pode usar kqueue com EVFILT_PROC + NOTE_EXIT para fazer exatamente isso. Sem necessidade de polling. Infelizmente não há nenhum equivalente Linux.

Até agora, eu encontrei três maneiras de fazer isso no Linux:

  • Polling: você verificar a existência do processo de vez em quando, usando kill ou testando a existência de /proc/$pid, como na maioria das outras respostas
  • Use a chamada de sistema ptrace para anexar ao processo como um depurador para que você ser notificado quando ele sai, como em de a3nm
  • Use a interface netlink para escutar mensagens PROC_EVENT_EXIT - desta forma o kernel diz seu programa cada vez que um processo de saídas e você apenas aguardar o processo de identificação direita. Eu só vi este descrito em um lugar na internet.

Shameless plug: Eu estou trabalhando em um programa (open source é claro; GPLv2) que faz qualquer um dos três.

Você também pode criar um soquete ou um FIFO e ler sobre eles. O FIFO é especialmente simples: Ligue a saída padrão de seu filho com o FIFO e ler. A leitura será bloqueado até que a criança saídas (por qualquer motivo) ou até que ele emite alguns dados. Então você vai precisar de um pouco de loop para descartar os dados de texto indesejadas.

Se você tiver acesso à fonte da criança, abra o FIFO para escrever quando ele inicia e, em seguida, simplesmente esquecê-la. O novo sistema vai limpar o descritor de arquivo aberto quando a criança termina e seu processo de "pai" de espera vai acordar.

Agora, isso pode ser um processo que você não iniciar ou própria. Nesse caso, você pode substituir o binário executável com um script que inicia o binário real, mas também adiciona monitoramento conforme explicado acima.

Você pode anexar ao processo com ptrace(2). A partir do shell, strace -p PID >/dev/null 2>&1 parece trabalho. Este evitar a ocupado em espera, mas vai retardar o processo de traçado, e não vai funcionar em todos os processos (só seu, que é um pouco melhor do que apenas processos filhos).

Nenhum Estou ciente. Além da solução do caos, você pode usar semáforos se você pode mudar o programa que você quer esperar para.

As funções de biblioteca são sem_open(3), sem_init(3), sem_wait(3), ...

executa sem_wait(3) esperar, portanto, você não tem que fazer espera ocupada como em solução chaos'. Claro, usando semáforos faz seus programas mais complexa e pode não valer a pena.

Aqui está uma maneira de esperar por qualquer processo (não necessariamente uma criança) em linux para sair (ou ser morto) sem polling:

Usando inotify para esperar o / proc'pid' a ser eliminado seria a solução perfeita, mas infelizmente inotify não funciona com sistemas de arquivos pseudo como / proc. No entanto, podemos usá-lo com o arquivo executável do processo. Embora o processo ainda existe, este arquivo está sendo mantido aberto. Assim, podemos usar inotify com IN_CLOSE_NOWRITE para bloquear até que o arquivo é fechado. Claro que pode ser fechado por outras razões (por exemplo, se outro processo com as mesmas saídas executáveis) por isso temos de filtrar esses eventos por outros meios.

Podemos usar kill (pid, 0), mas que não pode garantir se ele ainda é o mesmo processo. Se estamos realmente paranóico com isso, podemos fazer outra coisa.

Aqui está uma maneira que deve ser% seguro 100 contra problemas pid-reutilização: abrimos o diretório pseudo / proc / 'pid', e mantê-la aberta até que estamos a fazer. Se um novo processo é criado nesse meio tempo com o mesmo PID, o descritor de arquivo diretório que nós prendemos ainda vai se referir ao original (ou tornar-se inválida, se o antigo processo deixam de existir), mas nunca irá submeter a novo processo com o pid reutilizados. Então podemos verificar se o processo original ainda existe pela verificação, por exemplo, se o arquivo "cmdline" existe no diretório com openat (). Quando um processo sai ou é morto, esses arquivos pseudo deixará de existir também, então openat () irá falhar.

aqui é um código de exemplo:

// return -1 on error, or 0 if everything went well
int wait_for_pid(int pid)
{
    char path[32];
    int in_fd = inotify_init();
    sprintf(path, "/proc/%i/exe", pid);
    if (inotify_add_watch(in_fd, path, IN_CLOSE_NOWRITE) < 0) {
        close(in_fd);
        return -1;
    }
    sprintf(path, "/proc/%i", pid);
    int dir_fd = open(path, 0);
    if (dir_fd < 0) {
        close(in_fd);
        return -1;
    }

    int res = 0;
    while (1) {
        struct inotify_event event;
        if (read(in_fd, &event, sizeof(event)) < 0) {
            res = -1;
            break;
        }
        int f = openat(dir_fd, "fd", 0);
        if (f < 0) break;
        close(f);
    }

    close(dir_fd);
    close(in_fd);
    return res;
}

Talvez ele poderia ser possível esperar / proc / [pid] ou / proc / [pid] / [algo] para desaparecer?

Existem poll () e outro arquivo de evento funções de espera, talvez que poderia ajudar?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top