Comportamento do código [RESOLVIDO]

1. Comportamento do código [RESOLVIDO]

Matheus
Matheus_Santos

(usa Debian)

Enviado em 08/12/2023 - 20:58h

Pessoal, boa noite!
Estou estudando algumas coisas internas do Kernel Linux, porém estou testando algumas coisas no User-Space para fins didáticos e práticos mesmo.
Executando o código:

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

int main(void)
{
pid_t pid =fork();

if(pid == 0)
{
printf("Processo filho\n");
exit(0);
}
else if(pid < 0)
{
perror("Houve um erro na criacao do processo\n");
exit(1);
}
else
{
printf("Processo pai\n");
exit(0);
}
return 0;
}

Fiquei sem entender o motivo de primeiro ser executado o ELSE e não o IF, já que fork foi executado(E teve sucesso, ele iria retornar 0).
A ideia que eu tive analisando foi a seguinte: Quando o processo é duplicado, todo conteúdo da página de memória do pai é copiada para o processo duplicado(filho), eis o COW, "logo o código executável tbm" e nisso ocorre uma espécie de loop, a primeiro vez(Quando executamos o programa "processo pai") e como ocorre a duplicação, o processo filho executa o código novamente, pois o conteúdo da página do pai foi copiado para o filho. E aí que rola a queda no IF, pois o fork já atribuiu 0 a pid(Já que foi executado). Bom, essa a ideia de possibilidade que cheguei! Se não for, desde já agradeço a todos que poderem me ajudar a entender esse comportamento.


  


2. Re: Comportamento do código

Buckminster
Buckminster

(usa Debian)

Enviado em 09/12/2023 - 22:12h

Aristoteles@Aristoteles ~/projC
$ ./frok
Processo pai
Processo filho

Você está certo, complementando que o código é lido e executado da esquerda para a direita de cima para baixo.
Às vezes coisas básicas (KISS) explicam melhor do que o complexo.

If-Else basicão em C:

if(expressão)
comando1;
else
comando2;

"A expressão é avaliada; se for verdadeira (isto é, se expressão tiver um valor diferente de zero), o comando1 é executado. Se for falsa (expressão é zero) e se houver uma parte else, o comando2 é executado".
C, A Linguagem de Programação Padrão Ansi, página 53;
Brian W. Kernigham
Dennis M. Ritchie

"E aí que rola a queda no IF, pois o fork já atribuiu 0 a pid(Já que foi executado).", ou seja, o comando1 é executado se tiver um valor diferente de zero, no caso, o valor é zero (condição falsa), daí foi para o else if (também condição falsa) e executou o else (condição verdadeira), daí executou o if (condição verdadeira agora).

E no link abaixo tem mais, que, aliás, explica e complementa tua explicação já bem explicada:
"A função fork é chamada uma única vez (no pai) e retorna duas vezes (uma no processo pai e outra no processo filho). O processo filho herda informações do processo pai:"
https://br-c.org/doku.php?id=fork

E sobre o kernel Linux, como explica no link acima "Todas as áreas do processo são duplicadas dentro do sistema operacional (código, dados, pilha, memória dinâmica)."; e, mais abaixo no mesmo link acima "A função retorna -1 em caso de erro (provavelmente devido a se ter atingido o limite máximo de processos por usuário configurado no sistema).", a parte "limite máximo de processos por usuário configurado no sistema", tem a ver com a espécie de loop que tu falou.

Sobre o Kernel Linux recomendo o livro "Desenvolvimento do kernel do Linux", de Robert Love, é de 2004, a edição que eu tenho é muito mal traduzida para o Português, mas tecnicamente falando, este livro, sobre o kernel Linux, é aquilo que o Anel é para o Sméagol/Gollum.

E sobre o fork aqui tem umas coisas boas que eu peguei nos meus alfarrábios:
https://www.vivaolinux.com.br/topico/C-C++/Problemas-utilizano-a-funcao-fork
https://www.vivaolinux.com.br/topico/C-C++/Criacao-fork-para-encontrar-numero-rand

_________________________________________________________
Always listen the Buck!
Enquanto o cursor estiver pulsando, há vida!


3. Re: Comportamento do código [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 09/12/2023 - 23:01h

Não entendi qual loop a que você se refere. Pode explicar melhor ou mostrar a saída do programa que o faz pensar isso?

O que eu posso dizer com relação a fork() é que não existe nenhuma garantia de qual dos ramos vai executar primeiro. Ainda mais nestes tempos em que todo mundo tem multicore, é até possível que ambos executem juntos (tudo bem que, no seu caso, como a execução é só uma impressão na tela de um texto bem curto, provavelmente você nunca vai conseguir ver essa execução simultânea).


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


4. Re: Comportamento do código

Buckminster
Buckminster

(usa Debian)

Enviado em 09/12/2023 - 23:48h

paulo1205 escreveu:

Não entendi qual loop a que você se refere. Pode explicar melhor ou mostrar a saída do programa que o faz pensar isso?

O que eu posso dizer com relação a fork() é que não existe nenhuma garantia de qual dos ramos vai executar primeiro. Ainda mais nestes tempos em que todo mundo tem multicore, é até possível que ambos executem juntos (tudo bem que, no seu caso, como a execução é só uma impressão na tela de um texto bem curto, provavelmente você nunca vai conseguir ver essa execução simultânea).


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


O loop a que ele se refere, acredito eu, é "uma espécie de loop", não é exatamente o loop em programação, pois if, else if e else não são considerados laços tecnicamente, mas podem ser, basta enviar o else de volta para o if.
For, While e Do While são laços em si.

Ele refere-se ao compilador ter passado primeiro pelo if, mas ser executado primeiro no else e depois ter "voltado" e ter executado o if (processo pai e processos filhos do sistema), é bastante simples de entender.

Agora sou eu que pergunto em relação a isso que tu escreveu: "é até possível que ambos executem juntos".
Pode explicar melhor ou mostrar a saída do programa (sem alterar o código dele) que o fez pensar isso?

E isso: "não existe nenhuma garantia de qual dos ramos vai executar primeiro."; existe sim, com certeza um dos processos será executado primeiro tanto assim que na saída do código saiu primeiro "Processo pai" desconsiderando o if else e priorizando o fork, por isso são "processo pai e processos filhos", pois o processo pai origina os filhos, o contrário é impossível; e "multicore" não significa exatamente que os processos do sistema são executados ao mesmo tempo.

Agora, caso teu conceito de "execução" seja diferente, pois leitura e execução são coisas diferentes, por exemplo, tem linguagens que lêem os comentários, mas não executam; e tem outras linguagens de programação que sequer lêem os comentários, pois interrompem a execução com o símbolo do comentário e passam para a próxima linha.
Em linguagens interpretadas, por exemplo, cada caractere tem que ser interpretado, mas também depois de fazer o parsing não tem peso mais.
Em linguagens compiladas (como C) os comentários sequer "pesam".
É tudo muito rápido, ocorre num pentelímetro de segundo, mas mesmo assim a entrada e a saída não ocorrem ao mesmo tempo, posto que isso é impossível.
É aquela coisa de FIFO e LIFO que ainda tem validade... enquanto os computadores funcionarem com energia elétrica.

_________________________________________________________
Always listen the Buck!
Enquanto o cursor estiver pulsando, há vida!


5. Re: Comportamento do código [RESOLVIDO]

Matheus
Matheus_Santos

(usa Debian)

Enviado em 10/12/2023 - 09:07h


Sim, estou lendo exatamente este livro do Robert Love. A ideia do "loop" ao qual me referi é pq quando fork é chamado e o processo pai é duplicado, logo o código executável do processo pai é copiado para o processo filho, e aí quando o filho executa, acaba executando o mesmo código executável do processo pai(Por isso chamei de LOOP).
Porém, realizei alguns testes aqui com um novo código para testar a ideia que eu dei quando fiz o post, e aparentemente estou certo sim, código abaixo:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
pid_t pid = fork();
printf("PID INICIAL: %d\n", pid);
if(pid == 0)
{
printf("Processo filho\n");
exit(0);
}
else if(pid < 0)
{
perror("Houve um erro na criacao do processo\n");
exit(1);
}
else
{
printf("Processo pai\n");
printf("Meu pid: %d\n", pid);
exit(0);
}
return 0;
}

Quando FORK é chamado, ele duplica o processo pai criando um processo filho, quando o código tá sendo executado no contexto do processo pai o FORK retorna o mesmo PID do processo pai, por isso a condição do "IF(pid == 0)" não é verdadeira e cai no ELSE(Executando o processo pai), só que aí o processo filho começa a executar e FORK atribui 0 a pid "pid = 0" e aí a condição do "IF(pid ==0)" é verdadeira, caindo no contexto do processo filho.

Espero que tenha conseguido explicar direito para vocês conseguirem entender o que eu quis dizer kkkk. Desde já agradeço a todos pela ajuda que deram!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts