Problemas utilizando a função fork

1. Problemas utilizando a função fork

IV
nirvs9

(usa Ubuntu)

Enviado em 06/04/2019 - 22:03h

Ola pessoal, tudo bem? Espero que sim. Bom meu problema é o seguinte, preciso formular um programa em C que calcule o somatorio do quadrado de i numeros, os termos dessa somatoria devem ser calculados por um numero de processos determinado pelo utilizador. Devo utilizar a funcao fork para criar os processos. Bem, estou conseguindo criar tais processos, no entanto a ideia era que essa arvore de processos funcionasse da seguinte forma: O ultimo processo é o primeiro a calcular, assim que terminar o calculo de sua parte dos termos, ele finaliza e o processo anterior sai da hibernacao, calcula seus termos e finaliza, e assim subsequentemente até chegar ao processo raiz(pai), que ira ler no ficheiro que os processos escreveram e vai realizar o somatorio de todas as partes.
O problema é que nao estou conseguindo fazer essa "escadinha" de espera utilizando a funcao wait. Alguem pode me ajudar?
Segue o codigo:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

main(int argc, char *argv[])
{
pid_t filhoID, filhoID2;
int estado, i=2, status, x=0, N=0, NP=0, TPP=0;

// criando a variável ponteiro para o arquivo
FILE *pont_arq;

//abrindo o arquivo
pont_arq = fopen("arquivo.txt", "a");


for(x=0;x<argc;x++){
printf("argv[%d] %s\n", x, argv[x]);
}
N+= atoi(argv[1]);
NP+= atoi(argv[2]);
TPP+=atoi(argv[1])/atoi(argv[2]);

filhoID=fork();

if (filhoID==0){
printf("Filho 1 com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());

for(i=2;i<=NP;i++){
filhoID=fork();
if(filhoID==0){
printf("Filho %d com pid=%ld ppid=%d\n",i,(long)getpid(), (int)getppid());
}else{break;}
}
}else{
printf("Pai com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());


exit(0);
}

}



  


2. Resolucao Parcial

IV
nirvs9

(usa Ubuntu)

Enviado em 07/04/2019 - 03:09h

Ola meus caros, consegui resolver o problema da escadinha, resta agora repartir a tarefa entre os processos. Alguma sugestao? Segue o codigo.

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

main(int argc, char *argv[])
{
pid_t filhoID, filhoID2;
int estado, i=2, status, x=0, N=0, NP=0, TPP=0, ab=0, ac=0;

// criando a variável ponteiro para o arquivo
FILE *pont_arq;

//abrindo o arquivo
pont_arq = fopen("arquivo.txt", "a");


for(x=0;x<argc;x++){
printf("argv[%d] %s\n", x, argv[x]);
}
N+= atoi(argv[1]);
NP+= atoi(argv[2]);
TPP+=atoi(argv[1])/atoi(argv[2]);

filhoID=fork();

if (filhoID==0){
printf("Filho 1 com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());
filhoID2 = wait(&status);
for(;x<N;x++){
ab=x;
ab*=x;
ac+=ab;
printf("ab:[%d]\n", ac);
}

for(i=2;i<=NP;i++){
filhoID=fork();
filhoID2 = wait(&status);
if(filhoID==0){
printf("Filho %d com pid=%ld ppid=%d\n",i,(long)getpid(), (int)getppid());

for(;x<N;x++){
ab=x;
ab*=x;
ac+=ab;
printf("ab:[%d]\n", ac);
}


}else{break;}
}
}else{
printf("Pai com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());
filhoID2 = wait(&status);
printf("fim hiber\n");
exit(0);
}

}



3. Re: Problemas utilizando a função fork

IV
nirvs9

(usa Ubuntu)

Enviado em 08/04/2019 - 21:41h

Ola, tudo bem? consegui fazer quase tudo, so estou tendo um problema: Quando utilizo mais de dois processos da problema na escrita dos numeros no bloco de notas. Alguem para me ajudar?

segue o codigo
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
main(int argc, char *argv[])
{
pid_t filhoID, filhoID2;
int estado, i=2, status, s=0, x=1, N=0, NP=0, TPP=0, ab=0, ac=0, VA=0, y=1, soma=0, soma2=0;
N+= atoi(argv[2]);
NP+= atoi(argv[1]);
TPP+=atoi(argv[2])/atoi(argv[1]);
printf("TPP: %d\n", TPP);
int numeros[N];
filhoID=fork();
if (filhoID==0){
printf("Filho 1 com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());
filhoID2 = wait(&status);
if(N%NP==0) {
for(x=1;x<=TPP;x++){
ab=y;
ab*=y;
y++;
ac=ab;
printf("ab:[%d]\n", ac);
VA=x;
pont_arq = fopen("arquivo.txt", "wb");
fwrite(&ac, sizeof(int), 1,pont_arq);
fclose(pont_arq);
}
} else {
for(x=0;x<=TPP;x++){
ab=y;
ab*=y;
y++;
ac=ab;
printf("ab:[%d]\n", ac);
VA=x;
pont_arq = fopen("arquivo.txt", "wb");
fwrite(&ac, sizeof(int), 1,pont_arq);
fclose(pont_arq);
}
}
for(i=2;i<=NP;i++){
filhoID=fork();
filhoID2 = wait(&status);
if(filhoID==0){
printf("Filho %d com pid=%ld ppid=%d\n",i,(long)getpid(), (int)getppid());
for(x=0;x<TPP;x++){
ab=y;
ab*=y;
y++;
ac=ab;
printf("ab:[%d]\n", ac);
VA=x;
pont_arq = fopen("arquivo.txt", "wb");
fwrite(&ac, sizeof(int), 1,pont_arq);
fclose(pont_arq);
}
}else{break;}
}
}else{
// criando a variável ponteiro para o arquivo
FILE *pont_arq;
printf("Pai com pid=%ld ppid=%d\n",(long)getpid(), (int)getppid());
filhoID2 = wait(&status);
printf("fim hiber\n");
pont_arq=fopen("arquivo.txt", "rb");
while(fread(&numeros,sizeof(int), N, pont_arq)>0){
}
for(s=0;s<N;s++){
soma+=numeros[s];
printf("numero: %d\n", numeros[s]);
}
printf("Total: %d\n", soma);
soma2+=N*(N+1)*(2*N+1);
soma2/=6;
printf("Valor Esperado: %d\n", soma2);
exit(0);
}
}



4. Re: Problemas utilizando a função fork

Paulo
paulo1205

(usa Ubuntu)

Enviado em 09/04/2019 - 09:10h

Essa “escadinha”, que você mencionou, é algo requerido pelo exercício, ou foi apenas uma ideia sua para implementar a soma em múltiplos processos? Porque ela não me parece fazer muito sentido: por que ter múltiplos processos para implementar uma execução sequencial? Faz muito sentido ter múltiplos processos se for para implementar execução em paralelo, situação em que, em lugar de uma “escadinha”, você teria algo mais parecido com um asterisco.

Além disso, eis o modo como normalmente se estrutura um programa com múltiplos processos, no modelo master (processo pai)/workers (processos filhos):
int main(){
// prepara/recebe o conjunto de dados totais.
for(int i=0; i<N_FILHOS; i++){
// Calcula o pedaço da massa de dados que corresponde ao i-ésimo filho.
pid_t filho=fork();
if(filho==0 /* este é o i-ésimo processo filho, worker */){
// Realiza o processamento que cabe a este filho.
// Grava resultados em disco ou envia-os para o pai (por socket, pipe ou outro mecanismo de comunicação entre processos).
_exit(0); // <--- Isto aqui é muito importante! Depois de terminar seu processamento, o filho geralmente termina a execução, sem seguir pelo código que vai abaixo.
}
// Aqui vai código que só cabe ao processo pai (master).
// (Neste caso, não há muito o que fazer, a não ser preparar o próximo filho, na próxima iteração do laço de repetição.)
}
// Neste ponto, o pai já criou todos os filhos (workers), que, agora, estão trabalhando em paralelo.
// Ao pai, então, só resta esperar que eles todos terminem, para consolidar os resultados parciais.
for(int i=0; i<N_FILHOS; i++){
// Recebe/lê dados do i-ésimo filho.
int status;
pid_t filho=wait(&status);
// Pode querer tomar decisões diferentes em função dos valores de filho e, principalmente, de status.
}
// Consolida dados recebidos de todos os filhos e gera saída final.
return 0;
}


Além de adotar um modelo que me parece estranho, seu código tem outros problemas. Entre tais problemas, temos o fato de que todos os processos intermediários sobrescrevem o mesmo arquivo, provocando a perda de tudo o que os processos anteriores tiverem produzido como saída. Não bastasse isso, ainda existe um questão de formato: você dá ao arquivo um nome com sufixo “.txt”, mas grava dentro dele dado em formato binário.

A maneira como você faz os cálculos também me parece estranha e desnecessariamente complicada, usando variáveis demais para guardar valores intermediários (mas admito que não fiz uma análise muito detalhada para confirmar ou afastar essa impressão).

Por outro lado, em outros lugares em que variáveis intermediárias teriam sido úteis para evitar a repetição de análises de strings, você não as usou. Por exemplo, ao calcular o valor de TPP, você invocou novamente atoi(argv[2]) e atoi(argv[1]), embora já as tivesse invocado imediatamente acima para definir os valores de N e NP, que você poderia ter simplesmente reaproveitado no cálculo de TPP.

Por falar nisso, não entendi por que você fez, por exemplo, “N=0; N+=atoi(argv[1]);” (atribuição seguida de acúmulo) em lugar de, simplesmente, “N=atoi(argv[1]);” (apenas atribuição).


... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts