C synchronizacja procesów za pomocą semaforów

0

Witam, mam problem z synchronizacją procesów, mianowicie: moim celem jest uzyskanie takiej synchronizacji dla dwóch procesów, że gdy proces macierzysty pisze wartości do łącza w pętli, to później zostaje on na chwilę zablokowany po to, aby proces potomny wywołał program dla nich i tak w kółko aż do osiągnięcia warunku pętli. Oto kod:

Poniżej znajdują się funkcje odpowiedzialnie za podniesienie/opuszczenie semaforu.

static struct sembuf buf;   //operacje beda wykonywane tylko na jednym elemencie tablicy semaforow

void podnies(int semid,int semnum){
		buf.sem_num = semnum;
		buf.sem_op = 1;
		buf.sem_flg = 0;
		if(semop(semid,&buf,1) == -1){
			perror("Podniesienie semafora");
			exit(EXIT_FAILURE);
		}
}

void opusc(int semid,int semnum){
	buf.sem_num = semnum;
	buf.sem_op = -1;
	buf.sem_flg = 0;
	if(semop(semid,&buf,1) == -1){
		perror("Opuszczenie semafora");
		exit(EXIT_FAILURE);
	}
}

...

Poniżej pobieram klucz, dla którego to tworzę tablicę semaforów składająca się z dwóch elementów. Podnoszę oba semafory na początku.

key_t klucz;
	int semaforID;
	int sem_status;		
	
	if((klucz = ftok(argv[0],4)) == -1){
		perror("Blad przy tworzeniu klucza");
		exit(EXIT_FAILURE);
	}
	
	if((semaforID = semget(klucz,2,IPC_CREAT | IPC_EXCL | 0600)) == -1){
		perror("tworzenie tablicy seamforow");
		exit(EXIT_FAILURE);
	}

	union semun{
		int val; // wartosc dla setval
		struct semid_ds *buf; // bufor dla IPC_STAT i IPC_SET
		ushort *array; // tablica dla GETALL i SETALL
	};
	// ustawiamy wartosc domyslna
	union semun opcje;
	opcje.val = 1;
	

	if((sem_status = semctl(semaforID,0,SETVAL,opcje)) == -1){  // 0 - piewrszy semafor w zestawie
		perror("Blad przy ustawianiu semafora");
		exit(EXIT_FAILURE);
	}
	if((sem_status = semctl(semaforID,1,SETVAL,opcje)) == -1){
		perror("Blad przy usuwaniu semafora");
		exit(EXIT_FAILURE);
	}

Z kolei w tym fragmencie kody ma się dokonać wcześniej wspomniana synchronizacja procesów.

 ppid = fork();		
	
		switch(ppid)
		{
			case -1: // Blad przy wywolaniu funkcji fork() 
				perror("fork");
				exit(EXIT_FAILURE);

			case 0: // Proces potomny 
				if(close(0) == -1){				// Zamykamy standardowy deskryptor do odczytu
					perror("Potomek: close(0)");
					exit(EXIT_FAILURE);
				}
				if(dup(pipe_fd1[0]) != 0){	 		// Na skutek zduplikowania standardowe WE/WY
					perror("Potomek: dup(pipe_fd1[0])");    // zostalo przekierowane do utworzonego lacza.
					exit(EXIT_FAILURE);
				}
				if(close(pipe_fd1[0]) == -1){			// Zduplikowany deskryptor nie jest juz potrzebny
					perror("Potomek: close(pipe_fd1[0])");
					exit(EXIT_FAILURE);
				}		
				if(close(pipe_fd1[1]) == -1){			// Deskryptor do zapisu rowniez nie jest potrzebny
					perror("Potomek: close(pipe_fd1[1])");
					exit(EXIT_FAILURE);
				}
							
				int c;
				for(c=0;c<ilosc_testow;c++){
					// dodane
					opusc(semaforID,1);   // SEMAFOR

					execl(argv[1],NULL);

					podnies(semaforID,1);   // SEMAFOR

					
				}		

			default:
				if(close(pipe_fd1[0]) == -1){			// Zamykamy deskryptor do odczytu
					perror("Macierzysty: close(pipe_fd1[0])");
					exit(EXIT_FAILURE);
				}
				
				// TUTAJ JAKIS KOD KTORY TO BEDZIE PISAL DO LACZA 
				for(i=0;i<ilosc_testow;i++){
					if((d = fopen(dane[i*3],"r")) == NULL){				
						perror("dane[i*3]");	
						exit(EXIT_FAILURE);
					}
					liczba_wierszy = 0;
					while((znak = getc(d)) != EOF){
						if(znak == '\n'){
							++liczba_wierszy;
						}
					}
					fseek(d,0,SEEK_SET);
					int *dane_tmp = (int*)malloc(liczba_wierszy*sizeof(int));
					j = 0;
					while(fscanf(d,"%d",&(dane_tmp[j])) != EOF){
						printf("%d\n",dane_tmp[j]); // DO USUNIECIA POZNIEJ
						j++;
					}
					
					for(j=0;j<liczba_wierszy;j++){
							/*cos*/
						opusc(semaforID,0);	   // SEMAFOR							
				
						podnies(semaforID,0);     // SEMAFOR
							/*cos*/
					} // end for
					free(dane_tmp);
					fclose(d);
				} // end for
				sleep(1);
		
				if(close(pipe_fd1[1]) == -1){
					perror("Macierzysty: close(pipe_fd1[1])");
					exit(EXIT_FAILURE);
				}
				pid = waitpid(ppid,&status,0);			
										
		} // koniec switch

Na koniec przed zwróceniem 0, usuwam ID semafora.

sem_status = semctl(semaforID,0,IPC_RMID);

Pozdrawiam i mam nadzieję, że ktoś zdoła mnie nakierować.

0

A pytanie jest jakie, albo w czym tkwi problem?

0

Masz potoki, po co ci jeszcze semafory?

Musisz opisać, tylko dokładnie, co chcesz osiągnąć. Co mają robić procesy i w jaki sposób. Widzę, że kombinujesz jak koń pod górkę. Opisz problem to na pewno podpowiemy w jaki sposób je synchronizować. Synchronizacja powinna być możliwie prosta.

0

Problem tkwi w tym, że wywołując program dla załóżmy dwóch testów, to wypisywane są wartości z dwóch plików testowych jeden po drugim na wyjściu jednakże dopiero potem zostaje uruchomiony program, ale tylko jeden raz. Chcę, aby to wyglądało w następujący sposób: wyświetlam wartości dla pierwszego testu, wykonuje program i tak w kółko dla jakiejś tam odczytanej ilości testów.

Jak również mam problem z pisaniem tych wartości do łącza. Załóżmy, że plik z wartościami po zliczeniu ma trzy wiersze, a więc wypadałoby je w pętli wczytywać do łącza. Wiem, że musi być to podany łańcuch znaków, dlatego też staram się w pętli konwertować liczbę całkowitą na napis i wczytywać do łącza. Tutaj wczyta tylko pierwszą wartość, reszta wartości to przysłowiowe śmiecie - przynajmniej tak powiadamia miprogram, który to wczytuje dane z standardowego wejścia a potem wyświetla co wczytał na wyjście.

for(i=0;i<ilosc_testow;i++){
					if((d = fopen(dane[i*3],"r")) == NULL){				
						perror("dane[i*3]");	
						exit(EXIT_FAILURE);
					}
					liczba_wierszy = 0;
					while((znak = getc(d)) != EOF){
						if(znak == '\n'){
							++liczba_wierszy;
						}
					}
					fseek(d,0,SEEK_SET);
					int *dane_tmp = (int*)malloc(liczba_wierszy*sizeof(int));
					j = 0;
					while(fscanf(d,"%d",&(dane_tmp[j])) != EOF){
						printf("%d\n",dane_tmp[j]); // DO USUNIECIA POZNIEJ
						j++;
					}
					
					for(j=0;j<liczba_wierszy;j++){
							
					//	opusc(semaforID,1);						
						int pom = dane_tmp[j];

						char* line=(char*)malloc(max*sizeof(char));
						sprintf(line,"%d",pom);
					       	   write(pipe_fd1[1],line,sizeof(line));
						free(line);


					//	podnies(semaforID,0);
							
					} // end for
					free(dane_tmp);
					
					fclose(d);
					pid = waitpid(ppid,&status,0);
				} // end for
				sleep(1);
		
				if(close(pipe_fd1[1]) == -1){
					perror("Macierzysty: close(pipe_fd1[1])");
					exit(EXIT_FAILURE);
				}
0

Temat do zamknięcia. Problem rozwiązałem już sam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1