.:: Jorge Pereira ::.

- Checando processos com a libproc

Creio que quase todas as pessoas que utilizam Linux tiveram a necessidade de utilizar algum dos comandos kill, killall, ps, pgrep,… entre tantos outros programas que fazem parte do pacote procps[1].

Justamente a minha necessidade foi diferente, estava precisando em algum momento verificar se um determinado executável estava em execução na lista de processos, foi desta forma que baixei o código fonte do pacote procps e fui da uma olhada para entender sua API que por sinal não existe nenhuma documentação! isto mesmo, existe apenas o pacote procps e o procps-devel que possui os headers utilizado para a acessar os métodos existentes na libproc (geralmente em /lib/libproc.so) conforme abaixo.

[jpereira@jiraya codes]$ ls -1 /usr/include/procps/
alloc.h
devname.h
escape.h
procps.h
pwcache.h
readproc.h
sig.h
slab.h
sysinfo.h
version.h
wchan.h
whattime.h
[jpereira@jiraya codes]$

Desta forma segue um simples código de exemplo utilizado para verificar se o programa especifico passado como parâmetro está em execução.

/**
 * Autor: Jorge Pereira <jpereiran@gmail.com>
 * Data:  Ter Jan 13 14:29:29 BRST 2009
 * Desc:  Simples aplicacao utilizada para verificar se existe um
 * processo em execucao utilizando a procps (libproc)
 *
 * Build: gcc -o checkps checkps.c -lproc
 **/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>

#include <readproc.h>

bool check_process(const char *proc)
{
	int32_t flags = 0;
	PROCTAB *ptp  = NULL;
	bool 	 st   = false;
	proc_t task;

	memset(&task, 0, sizeof (task));

	if (!proc || strlen(proc) < 1)
		return false;

	flags = PROC_FILLCOM | PROC_FILLSTATUS;

	if ((ptp = openproc (flags)) == NULL)
		return false;

	while(!st && readproc(ptp, &task))
	{
        const char *cmd = (task.cmdline != NULL) ? task.cmdline[0] : task.cmd;

		st = !strncmp(proc, cmd, strlen(proc));
		memset (&task, 0, sizeof (task));
	}

	closeproc (ptp);

    return st;
}

int main (int argc, char *argv[])
{
    if (argc < 2)
    {
        printf ("Usage: %s <nome do processo>\n", argv[0]);
        exit(EXIT_SUCCESS);
    }

    printf("O Programa (%s) %sesta em execucao\n", argv[1], check_process(argv[1]) ? "" : "nao ");

    return EXIT_SUCCESS;
}

Baixando este código de exemplo, compilando e fazendo uma checagem se existe o processo “dbus-launch” em execução! :)

[jpereira@jiraya tmp]$ wget http://blog.jorgepereira.com.br/jorge/wp-content/uploads/2009/01/checkps.c
[jpereira@jiraya tmp]$ gcc -o checkps checkps.c -lproc
[jpereira@jiraya tmp]$ ./checkps dbus-launch
O Programa (dbus-launch) está em execução
[jpereira@jiraya tmp]$ ./checkps dbus-lanche
O Programa (dbus-lanche) não está em execução
[jpereira@jiraya tmp]$

8 Comments

  1. Lutieri G. B. says:

    Opa!!

    Interessante o codigo. To querendo comecar a utilizar algumas API’s. Nao posso parar de programar senao enferrujo… Vida de sysadmin me deixou assim.. hehe

    Porem acho que o mesmo pode ser alacancao usando o killall:

    Neste momento eu estava rodando um “man algumacoisa” em outra janela:

    zeuspc ~ # killall -s 0 man
    zeuspc ~ # echo $?
    0
    zeuspc ~ # killall -s 0 mana
    mana: no process killed
    zeuspc ~ # echo $?
    1

    O sinal -0 apenas tenta enviar um sinal pro processo. Caso consiga, retorna 0, do contrario falha…

    Eu ainda estou revirando meus feeds, mas jah fazem alguns minutos e nao estou conseguindo encontrar.. Mas se nao me engano ainda tem outro jeito de fazer isso.

    Abraco

  2. jpereira says:

    Olá Lutieri,

    Em relação a sua dica de utilizar o “kill -0″, seria via shellscript quando na realidade eu precisei fazer isto em um código C. Além de que as interfaces para manipulação de sinais no Linux, mais precisamente o tgkill(), kill(), killpg() são todas utilizadas passando como parâmetro o PID e o SINAL desejado.

    Quando na verdade eu estava precisando verificar se um processo estava sendo executado através de seu NOME!

    De qualquer forma, valeu pela dica! :)
    Abraços!
    []s

  3. noisebleed says:

    Muito obrigado pelo exemplo! Ajudou-me imenso. Procurei na net por exemplos/documentação sobre a libproc e este blog fez a diferença. Já estou a usar num programa em que preciso de 1) verificar qual o pid de um determinado processo e 2) obter o nome do processo e argumentos dado um pid. Funciona na perfeição. Só tive de alterar o include de para (Gentoo Linux) e adicionei a verificação dos argumentos => for(i<sizeof(cmdline))…

    Força aí no blog! Abraço.

  4. Praise says:

    Olá Jorge, esse sua dica ta d+, mas ae eu não estou conseguindo compilar esse codigo no meu ubuntu 9.04, eu recebo o seguinte erro “error: readproc.h: Arquivo ou diretório inexistente”, o que eu tenho que configurar para essa lib ser encontrada.

    valeu

  5. Ahmad says:

    Jorge eu nao estou conseguindo compilar, o gcc não está encontrando o readproc.h, como eu configura o ambiente para realizar essa compilação, eu estou usando o ubuntu 9.04

    valeu

  6. jpereira says:

    Olá!

    1) Instala os headers da libproc

    # apt-get install libproc-dev

    2) Informe o path dos headers

    # gcc -o checkps checkps.c -lproc -I/usr/include/proc

    []s

  7. Ahmad says:

    Legal, Jorge funcionou muito obrigado. Jorge pela libproc tem como pegar o usuario do sistema que está executando esse processo.

  8. Muito bom artigo, resolveu minha vida! Só como observação, o Slackware não instala os headers do procps por padrão. Eu precisei fazer manualmente. E ele também não tem um link de libproc..so para libproc.so. Mas isso é fácil de resolver.

Leave a Reply

*