Criação fork() para encontrar numero rand

1. Criação fork() para encontrar numero rand

Rodrigo Ferreira dos Anjos
webbester

(usa Ubuntu)

Enviado em 17/11/2016 - 11:32h

Pessoal bom dia,
Sou novato na área Open e gostaria, se possível, de uma ajudinha com a criação de código C a pedido do meu professor.

O problema é assim:
Desenvolva um programa em linguagem C, utilizando a primitiva fork( ), que:
1. Receba um número: $./fork <número>
Dica: argv[1]

2. Crie uma função para percorrer um conjunto de números randômicos de 0 a 100.000, e pare
a execução quando encontrar o número indicado em linha de comando;
Dica: rand() % 100.000;

3. Iniciar 3 processos filhos – cada processo filho deverá chamar essa função, e o primeiro
processo que encontrar o número solicitado irá retornar ao processo pai uma mensagem
dizendo que o número foi encontrado e pode encerrar a procura.
Dica: Utilizar um PIPE para realizar a comunicação entre processos
pipe(fd) >> write >> read

Exemplo de execução:
./procure 4
MSG: Criando o filho 3 - PID 1819.
MSG: Criando o filho 2 - PID 1818.
MSG: filho 2 achou o número 4.
MSG: Criando o filho 1 - PID 1817.


Eu tentei fazer alguma coisa seguindo um exemplo que mostra como criar processos filho (passado pelo professor), mas não consigo fazer o com que seja criado um filho 2. Somente o 1º é criado.

Meu código:

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

void exibe(int filho, int num)
{
int rando=0;

if (filho == 0)
{
printf ("Criando filho %d - %d\n", filho, getpid());
do {
rando = rand() % 100000;
if (rando == num)
{
printf ("\nFilho %d encontrou o numero %d primeiro.\n", filho, rando);
exit(0);
}

} while (rando != num);
}

}

void main()
{
int num=23584; // Este num seria o numero obtido por linha de comando

exibe(0,num);
if (fork() == 0)
{
exibe(1,num);
system("sleep 3");
} else {
if (fork() == 0)
exibe(2,num);
system("sleep 6");
}

system ("sleep 10");
}

Bom, espero ter sido claro o suficiente. Desde já, fico grato por qualquer ajuda!


  


2. Re: Criação fork() para encontrar numero rand

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/11/2016 - 13:59h

webbester escreveu:

[ ... ]

Eu tentei fazer alguma coisa seguindo um exemplo que mostra como criar processos filho (passado pelo professor), mas não consigo fazer o com que seja criado um filho 2. Somente o 1º é criado.


Há outros problemas, além desse.

O tipo de retorno de main() tem de ser int, não void.

Seu professor pediu que a comunicação entre os processos ocorra através de um pipe, mas eu não vi nenhum pipe no seu programa.

Do jeito como foi especificado, existe a chance de que o processo que achou o número primeiro não seja aquele que vai escrever no pipe, pois é possível que a troca de contexto entre processos, feita pelo sistema operacional, ocorra justamente entre o momento em que o número foi encontrado e o envio dessa informação ao processo gestor, e outro processo que achou o número depois pode ser escolhido pelo SO para execução, e acabar enviando seus dados antes. Mesmo que isso não faça diferença para você, é bom saber que pode acontecer, pois pode haver aplicações em que isso seja relevante.

Se você não inicializar a semente geradora de números (pseudo-)aleatórios, ou se a inicializar com o mesmo valor nos três processos, os três vão gerar exatamente as mesmas sequências de números. Desse modo, você não vai realmente medir nada a respeito da (pseudo-)aleatoriedade dentro de cada processo, mas tão-somente qual deles ganhou mais tempo de CPU (não deixa de ser relativamente aleatório, mas o será somente por causa de fatores externos ao programa).

Os três processos que fazem o sorteio têm de ser filhos do mesmo processo pai. Isso significa que o processo pai tem de chamar fork() três vezes. Isso pode ser feito dentro de um laço de repetição ou com três chamadas consecutivas a fork(). No seu programa, você só fez duas chamadas.

Após chamar a função especificada, que faz a busca do número aleatório e envia o resultado pelo pipe, só resta a cada processo terminar. Você não precisa fazer um sleep de 13 (3+10) ou 16 (6+10) segundos.

Como você só precisa imprimir qual foi o primeiro processo a terminar, o processo pai poderia matar, através da função kill(), os dois outros processos, até porque existe o risco, com um programa que depende de aleatoriedade para terminar, de ele seguir executando por longo tempo, até mesmo por tempo indefinido.


3. Re: Criação fork() para encontrar numero rand

Rodrigo Ferreira dos Anjos
webbester

(usa Ubuntu)

Enviado em 18/11/2016 - 11:48h

paulo1205 escreveu:

webbester escreveu:

[ ... ]

Eu tentei fazer alguma coisa seguindo um exemplo que mostra como criar processos filho (passado pelo professor), mas não consigo fazer o com que seja criado um filho 2. Somente o 1º é criado.


Há outros problemas, além desse.

O tipo de retorno de main() tem de ser int, não void.

Seu professor pediu que a comunicação entre os processos ocorra através de um pipe, mas eu não vi nenhum pipe no seu programa.

Do jeito como foi especificado, existe a chance de que o processo que achou o número primeiro não seja aquele que vai escrever no pipe, pois é possível que a troca de contexto entre processos, feita pelo sistema operacional, ocorra justamente entre o momento em que o número foi encontrado e o envio dessa informação ao processo gestor, e outro processo que achou o número depois pode ser escolhido pelo SO para execução, e acabar enviando seus dados antes. Mesmo que isso não faça diferença para você, é bom saber que pode acontecer, pois pode haver aplicações em que isso seja relevante.

Se você não inicializar a semente geradora de números (pseudo-)aleatórios, ou se a inicializar com o mesmo valor nos três processos, os três vão gerar exatamente as mesmas sequências de números. Desse modo, você não vai realmente medir nada a respeito da (pseudo-)aleatoriedade dentro de cada processo, mas tão-somente qual deles ganhou mais tempo de CPU (não deixa de ser relativamente aleatório, mas o será somente por causa de fatores externos ao programa).

Os três processos que fazem o sorteio têm de ser filhos do mesmo processo pai. Isso significa que o processo pai tem de chamar fork() três vezes. Isso pode ser feito dentro de um laço de repetição ou com três chamadas consecutivas a fork(). No seu programa, você só fez duas chamadas.

Após chamar a função especificada, que faz a busca do número aleatório e envia o resultado pelo pipe, só resta a cada processo terminar. Você não precisa fazer um sleep de 13 (3+10) ou 16 (6+10) segundos.

Como você só precisa imprimir qual foi o primeiro processo a terminar, o processo pai poderia matar, através da função kill(), os dois outros processos, até porque existe o risco, com um programa que depende de aleatoriedade para terminar, de ele seguir executando por longo tempo, até mesmo por tempo indefinido.


Paulo, obrigado pelo comentário..
Mal entendi como funciona o fork( ) quando o professor explicou. Coloquei dois processos filho para fazer o teste de acordo com o exemplo passado pelo professor. O pipe tbm não sei como funciona. Terei que dar mais uma pesquisada por ai para ver isso.

Obrigado pelas dicas!



4. Re: Criação fork() para encontrar numero rand

Paulo
paulo1205

(usa Ubuntu)

Enviado em 18/11/2016 - 13:48h

Confesso que fico tentado a dar uma resposta didática com código, mas não vou fazer isso.

Em lugar disso, estimulo-o a pôr a mão na massa, e depois trazer suas dúvidas -- ou o programa pronto -- aqui. Se houver algo a melhorar, poderemos dizer o que é e por quê.


5. Re: Criação fork() para encontrar numero rand

Rodrigo Ferreira dos Anjos
webbester

(usa Ubuntu)

Enviado em 26/11/2016 - 14:18h

paulo1205 escreveu:

Confesso que fico tentado a dar uma resposta didática com código, mas não vou fazer isso.

Em lugar disso, estimulo-o a pôr a mão na massa, e depois trazer suas dúvidas -- ou o programa pronto -- aqui. Se houver algo a melhorar, poderemos dizer o que é e por quê.


Paulo, desculpe-me a demora em responder o tópico. Estava ocupado com outros trabalhos e com este tbm.
Vasculhei a internet atrás de informações sobre como funciona o fork( ) e o pipe. Pedi ajuda ao meu professor tbm.
Ficou assim:

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

int fd[2];

void exibe(char filho[1], int num)
{
int rando=0;

printf ("Criando filho %s - %d\n", filho, getpid());
do {
rando = rand() % 10000000;
if (rando == num)
{
write(fd[1],filho,1);
exit(0);
}

} while (rando != num);

}

void main(int argc, char* argv[])
{

int num = 0;
num = atoi(argv[1]);

pipe(fd);

srand ((unsigned) time(NULL));

if (fork() == 0){
exibe("1", num);

} else {
if (fork() == 0) {
exibe("2", num);

} else {
if (fork() == 0) {
exibe("3", num);
} else {
char msg[1];
read(fd[0],msg,1);
printf ("\nProcesso filho %s encontrou primeiro.\n", msg);
}
}
}
}


Agradeço o incentivo e se alguém precisa, esta aqui.
Abraços.


6. Re: Criação fork() para encontrar numero rand

Paulo
paulo1205

(usa Ubuntu)

Enviado em 27/11/2016 - 07:43h

Quero de novo chamar sua atenção com relação ao tipo de retorno da função main(): nos nossos PCs, e no mundo UNIX em particular, ele tem de ser int.


7. Re: Criação fork() para encontrar numero rand

Perfil removido
removido

(usa Nenhuma)

Enviado em 27/11/2016 - 08:53h

Usar módulo 1000000 não dá espaço equiprovável.
Leia este texto: https://www.vivaolinux.com.br/dica/Numeros-aleatorios-em-shell-script/

É para shell script mas serve para outras linguagens.

----------------------------------------------------------------------------------------------------------------
Nem direita, nem esquerda. Quando se trata de corrupção o Brasil é ambidestro.
(anônimo)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts