Skip to content

Processos

Day edited this page Apr 2, 2025 · 3 revisions

Manipulação de Processos

Os códigos descritos nesse tópico são referentes à seção de manipulação de processos.

Podem ser encontrados tanto aqui quanto nesse link.

meupid.c

Visualizar o pid, ppid e grpid do processo

Código:

#include <stdio.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
    printf("Eu sou o processo %d, meu pai é o processo %d, e o grupo é o %d\n", getpid(), getppid(), getpgrp());

    return 0;
}

Compilar e Executar:

gcc meupid.c -o meupid
./meupid

Nesse código, as funções getpid(), getppid(), getpgrp() servem, respectivamente, para:

  • Mostrar o pid do processo atual;
  • Mostrar o pid do processo pai;
  • Mostrar o id do grupo do processo.

Exemplo de saída:

Eu sou o processo 29176, meu pai é o processo 28754, e o grupo é o 29176

Nessa saída o processo sinaliza que seu PID é 29176, quem o criou foi o processo 28754, que correspondia ao terminal que foi executado o programa, e o grupo que ele se encontra é o 29176.

execv.c

Executar o cat e ler o conteúdo de /etc/issue

Código:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
    //char *cmd[] = {"cat", "/etc/passwd", (char *)0};
    char *cmd[] = {"cat", "/etc/issue", (char *)0};
    
    printf("Vou chamar o programa cat para ler o conteudo de /etc/issue\n");

    execv("/bin/cat", cmd);

    printf("Esta mensagem nao sera impressa.\n");

    exit(0);
}

Compilar e Executar:

gcc execv.c -o execv
./execv

O char *cmd[] armazena o comando que será passado para o cat, nesse caso o cat /etc/issue

O execv substitui o código do processo atual pelo informado no primeiro argumento (/bin/cat) e executa a instrução informada no segundo argumento.

Exemplo de saída:

Vou chamar o programa cat para ler o conteudo de /etc/issue
EndeavourOS Linux \r (\l)

Note que na primeira linha corresponde ao primeiro print do programa, já na segunda linha é o resultado da chamada da função que foi feita, onde o conteúdo lido pelo catfoi "EndeavourOS Linux \r (\l)", o sistema operacional usado na máquina que o processo foi executado.

Note

Como a função execv SUBSTITUI o código atual por outro, o último printf não é executado.

system.c

Chamar o cat e ler o conteúdo de /etc/issue

Código:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    printf("Vou chamar o programa cat para ler o conteudo de /etc/issue\n");

    system("/bin/cat /etc/issue");
    
    printf("Esta mensagem sera impressa\n");

    return(0);
}

Compilar e Executar:

gcc system.c -o system
./system

Diferente do execv , o system não substitui o código atual por um novo.

Ao invés disso, ele chama o programa passado por parâmetro, sem substituir o atual.

Exemplo de saída:

Vou chamar o programa cat para ler o conteudo de /etc/issue
EndeavourOS Linux \r (\l)

Esta mensagem sera impressa

Note que as duas primeiras linhas da saída gerada por esse programa são exatamente iguais a saída do programa anterior, porque ambos estão chamando o cat para ler o mesmo arquivo, mas nesse caso o último print também foi executado, porque o system não substitui o código atual do processo pelo do cat.

Note

Como a função system NÃO SUBSTITUI o código atual, o último printf é executado.

fork_simples.c

Cria um processo filho e o espera finalizar

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(int argc, const char *argv[])
{
    int id;
    id = fork();

    if (id != 0)
    {
        printf("Sou o pai esperando pelo filho %d\n", id);
        wait(0);
        printf("Meu filho acabou, terminando\n");
    }
    else
    {
        printf("Sou o filho %d, esperarei 10 segundos\n", getpid());
        sleep(10);
        printf("Ja esperei, terminando...\n");
    }

    return 0;
}

Compilar e Executar:

gcc fork_simples.c -o fork_simples
./fork_simples

Nesse programa, o fork() é responsável por criar um processo filho.

Caso seja criado com sucesso, a função retorna 0.

Após a chamada do fork(), o processo é “dividido em dois”.

  • Processo 1 (Pai)
    • A variável id NÃO possui o valor 0, pois vai receber o id do processo filho criado;
    • Sendo assim, o programa entra no primeiro if;
    • Então o processo pai espera o processo filho acabar (sinalizado pela função wait(0)) .
  • Processo 2 (Filho)
    • A variável id possui o valor 0, indicando que é o filho;
    • Sendo assim, o programa entra no else;
    • Então, espera 10 segundos antes de finalizar (sleep(10)).

Exemplo de saída:

Sou o pai esperando pelo filho 23074
Sou o filho 23074, esperarei 10 segundos
Ja esperei, terminando...
Meu filho acabou, terminando

Na primeira linha temos o primeiro print que está dentro do if, ele está esperando pelo seu filho cujo o PID é 23074, então na segunda linha se encontra o primeiro print do processo filho, o que está no else, onde ele diz seu PID, e após 10 segundos ele executa o segundo print, sinalizando que terminou, já na última linha o processo pai fala que está finalizando pois o seu filho também finalizou.

fork_loop.c

Cria um processo e deixa ele executando indefinidamente

Código:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(int argc, const char *argv[])
{
    int pid;

    printf("Meu numero de processo é %d. Vou criar um processo filho.\n", getpid());

    pid = fork();

    if (pid == 0)
    {
        printf("\t\tProcesso filho criado com PID %d\n",getpid());
        printf("\t\tVou ficar executando indefinidamente\n");
        for(;;);
    }
    else
    {
        sleep(5);
        printf("O processo pai termina e deixa filho orfao\n");
        printf("Veja se o processo filho continua rodando com o comando ps\n");
    }

    exit(0);
}

Compilar e Executar:

gcc fork_loop.c -o fork_loop
./fork_loop

A função fork() cria um novo processo filho.

Caso seja criado com sucesso, ela retorna 0.

Como no fork_simples, após isso o processo é "dividido em dois".

  • Processo 1 (Pai):
    • O valor do pid não é 0, entra no else;
    • Então, espera 5 segundos e então finaliza (sleep(5));
    • Nesse caso, o processo pai não é obrigado a esperar que o filho termine sua execução por não ter nenhum wait().
  • Processo 2 (Filho):
    • O valor do pid é 0, entra no if;
    • Após os prints, entra em um loop infinito causado pelo for(;;).
    • Sendo assim, o processo ficará rodando até que alguém o interrompa.

Exemplo de saída:

Meu numero de processo é 23673. Vou criar um processo filho.
                Processo filho criado com PID 23674
                Vou ficar executando indefinidamente
O processo pai termina e deixa filho orfao
Veja se o processo filho continua rodando com o comando ps

Na primeira linha tem o primeiro print do programa falando que um processo com PID 23673 vai criar um processo filho. A segunda e terceira linha corresponde aos prints da execução do que se encontra dentro do if, já na linha 4 o print que está no else, que seria o processo pai, indica que ele finalizou e o processo que está em loop infinito ficou órfão, então na última linha ele fala para usar o comando ps para verificar, se usa ps pid_processo, para esse exemplo de saída seria ps 23674.

Após isso, o processo filho ficará rodando indeterminadamente em background até que seja interrompido pelo usuário.

Tip

Para matar o processo órfão, utilize o comando kill -9 pid_processo_filho, para esse exemplo de saída seria kill -9 23674

Clone this wiki locally