Functie open blocheaza procesul

Am o problema cu un cod de C… este o tema si presupune folosirea de pipe-uri anonime si cu nume.
Ca implementare se face un fork(), dupa un alt fork() in copilul rezultat. Problema care imi da batai de cap este cand nepotul sau copilul copilului incearca sa dea open pe pipe-ul cu nume cu drepturi de
write.

fd = open("pipe",O_WRONLY);
printf("FD: %d", fd);

Pur si simplu procesul este blocat pe linia cu open, nu se mai afiseaza printul de dupa.
In documentatie scrie ca open daca are vreo eroare da un file descriptor negativ, dar aici nu se mai intampla nimic dupa acel open.

Las si codul mai jos, mersi de ajutor.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Voi implementa un filter-reduce rudimentar.
Se vor trimite de la tastatura un sir de numere naturale, 
numarul care va inchide citirea va fi -1. 
Procesul parinte trimite numerele prn pipe-ul p1,
procesul copil le primeste si realizeaza 
operatia de filtrare (numere pare/impare), 
dupa care trimite si el copilului sau prin pipe-ul p2 numerele filtrate,
iar noul proces va face un reduce, 
poate calcula suma sau produsul numerelor pe care le primeste. 
Rezultatul va ajunge in procesul parinte printr-un pipe cu nume
pentru a folosi si acest tip de pipe, 
chiar daca se poate folosi un pipe anonim deoarece procesele sunt inrudite.*/

int main() {
	int p1[2], p2[2];
	int k, l, st, pid, fd;
	int paritate; //0 pentru pastrarea numerelor pare, 1 pentru pastrarea numerelor impare
	int operatie; //0 pentru suma, 1 pentru produs
    int reducere;
	char buf[50];
	int number;
	
	pipe(p1);
	pipe(p2);
	paritate=2;
	operatie=2;
	while(paritate<0 || paritate>1) {
		printf("Alegeti o valoare corespunzatoare pentru filtrare (0/1) \n");
		scanf("%d", &paritate);
	}
	while(operatie<0 || operatie>1) {
		printf("Alegeti o valoare corespunzatoare pentru reducere (0/1) \n");
		scanf("%d", &operatie);
	}
	
    reducere = operatie;

    if(mkfifo("pipe",0777) < 0) { 
        printf("Probleme la crearea pipe-ului cu nume !\n");
        exit(0);
    }


	pid = fork();
	
	if(pid < 0) {
		printf("eroare");
		return(-1);
	} else if(pid == 0) {
		pid = fork();
		
		if(pid < 0) {
			printf("eroare");
			return(-1);
		} else if(pid == 0) {
            fd = open("pipe",O_WRONLY);
            printf("FD: %d", fd);
			while(1) {
				while((k=read(p2[0], &number, sizeof(number))) > 0) {
                    printf("Primim in nepot: %d\n", number);
                    
					if(number == -1) {
                        
                        printf("CONDITIE STOP NEPOT\n");
                        
                        printf("FD: %d", fd);
                        write(fd, &reducere, sizeof(reducere));
                        printf("S-a trimis pe pipe din nepot\n");
                        exit(0);
                    }

					if(operatie == 0)
						reducere += number;
					else reducere *= number;
                    
                    printf("Operatia are valoarea: %d\n", reducere);
				}
			}
		} else {
			while(1) {
				while((k=read(p1[0],&number, sizeof(number))) > 0) {
                    printf("Primim in copil: %d\n", number);
					if(number == -1) {
                        printf("CONDITIE STOP COPIL\n");
						write(p2[1], &number, sizeof(number));
						printf("Inainte de wait copil\n");
		                wait(&st);
                        printf("Trecem de wait copil\n");
						exit(0);
					}
                    if(number % 2 == paritate) {
						write(p2[1], &number, sizeof(number));
					}
				}
			}
		}
	} else {
		number=0;
		while(number != -1) {
			if(scanf("%d", &number))
				write(p1[1], &number, sizeof(number));
            printf("Trimitem din parinte: %d\n", number);
		}
        printf("Inainte de wait, number: %d\n", number);
		wait(&st);
        printf("Trecem de wait\n");
		fd = open("pipe",O_RDONLY);
        read(fd, &reducere, sizeof(reducere));
        system("rm pipe");

        printf("Rezultatul este: %d", reducere);
	}
	return 0;
}
					

Fara sa ma uit peste cod altfel decat o simpla aruncare de privire superficiala si fara sa-ti fac tema, ca-s lenes si am alte lucruri de facut, esti sigur ca pipe-ul e deschis si pentru citire?

Altfel operatiunea de deschidere e blocata, trebuie deschise ambele ‘capete’.

Altfel spus, ti-a afisat si ‘Trecem de wait’?

E o problema intr-un cod, ca e tema, ca e munca, mi se pare irelevant.

Nu afiseaza trecem de wait, pentru ca am dat sa astepte copilul, iar copilul il asteapta pe nepot si nepotul nu face nimic pt ca se blocheaza in acel open().

Crearea se face cu mkfifo("pipe",0777), drepturi depline…

Nepotul face open, alta e problema. Codul tau se blocheaza in wait.
Ruleaza cu: strace -f ./a.out
Urmareste pid-urile si systemcall-urile.

1 Like

Stai ca acum m-am prins. Deci pentru ca eu deschid in nepot cu write, el o sa astepte sa se deschida in alta parte read si abia dupa o sa continue executia pt ambele procese?

‘Pentru ca’ nu mai conteaza.
Blocarea pe open in cazul ala e normala.
Trebuie sa deschizi ambele capete pentru ca sa deblocheze si sa poti sa scrii & citesti.

Exact. Probabil trebuie sa reorganizezi altfel codul. Considera procese copil diferite pentru pipe-urile cu nume si cele anonime.

Ma gandeam la un wait(NULL), dar las ca mai experimentez eu si vad ce iese