[Solved][C][Linux] pamieć dzielona i semafory

0

witam,
mam drobny problem (podobno z pamięcią dzieloną) pod linuxem, objawia się on następująco- rozpoczyna się komunikacja między procesami, po czym, po pewnym czasie, proces pierwszy przestaje dalej działać i jak się dalej okazuje, nie znajduję się on dłużej w puli procesów w systemie... prawdopodobnie jakiś błąd powoduje jego zamknięcie, jednak nie mogę go namierzyć :( mógłby mi ktoś wyjaśnić, dlaczego coś takiego występuje i jak temu zarazdzić?

poniżej przedstawiam fragment kodu (procesy biorące udział w komunikacji z procesem pierwszym):

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/sem.h>

#define N 10

int main(void){
	
	if(!fork()){
		printf("nadawca\n");
		
		int shmid;			/* systemowy identyfikator bloku pamięci dzielonej */
		int semid;			/* systemowy identyfikator semafora */
		unsigned int *tab;	/* wskaźnik na tablicę z danymi */
		int pos;			/* pozycja w tablicy */
		struct sembuf op;	/* struktura dla operacji na semaforze */
		
		shmid = shmget(0x123, sizeof(int)*N, 0744 | IPC_CREAT);
		if(shmid == -1){
			perror("shmget");
			exit(1);}
	
		tab = (unsigned int*)shmat(shmid, NULL, 0);
		if(tab == NULL){
			perror("shmat");
			exit(1);}
		
/* utworzenie nowego dwuelementowego semafora 
* 0 - semafor producenta
* 1 - semafor konsumenta
*/
		semid = semget(0x234, 2, 0700 | IPC_CREAT);
		if(semid == -1){
			perror("semget");
			exit(1);}
	
		/* ustawienie wartości początkowych semaforów */
		semctl(semid, 0, SETVAL, N);
		semctl(semid, 1, SETVAL, 0);
	
		op.sem_flg = 0;
		pos = 0;	
		
		for(;;){
			/* opuszczenie semafora producenta */
			op.sem_num = 0;
			op.sem_op = -1;
			semop(semid, &op, 1);
		
			/* zapis elementu do tablicy */
			fscanf(stdin, "%d", &tab[pos]);
			printf("proces nr 1: zapisałem %d na pozycji %d\n", tab[pos], pos);
			pos = (pos + 1) % N;
			//sleep(5);
		
			/* podniesienie semafora konsumenta */
			op.sem_num = 1;
			op.sem_op = 1;
			semop(semid, &op, 1);}
	}
	
	if(!fork()){
		printf("odbiorca\n");
		
		int shmid;			/* systemowy identyfikator bloku pamięci dzielonej */
		int semid;			/* systemowy identyfikator semafora */
		unsigned int *tab;	/* wskaźnik na tablicę z danymi */
		int pos;			/* pozycja w tablicy */
		struct sembuf op;	/* struktura dla operacji na semaforze */

		char buffer[20];

		shmid = shmget(0x123, sizeof(int)*N, 0744 | IPC_CREAT);
		if(shmid == -1){
			perror("shmget");
			exit(1);}
	
		tab = (unsigned int*)shmat(shmid, NULL, 0);
		if(tab == NULL){
			perror("shmat");
			exit(1);}
				
		semid = semget(0x234, 2, 0700);
		if (semid == -1){
			perror("semget");
			exit(1);}
			
		op.sem_flg = 0;
		pos = 0;
		
		for(;;){
			/* opuszczenie semafora konsumenta */
			op.sem_num = 1;
			op.sem_op = -1;
			semop(semid, &op, 1);
			
			/* odczyt elementu z tablicy */
			sprintf(buffer, "%xh", tab[pos]);
			printf("proces nr 2: odczytałem %d z pozycji %d, po przekonwertowaniu %s\n", tab[pos], pos, buffer);
			pos = (pos + 1) % N;
			//sleep(5);
			
			/* podniesienie semafora producenta */
			op.sem_num = 0;
			op.sem_op = 1;
			semop(semid, &op, 1);}
	}
	
	return 0;
}

sam program wywołuję poprzez:
./program < /dev/urandom
stąd też wykorzystywanie standardowego strumienia wejscia ;)

próbowałem walczyć z tym kodem, by znaleźć przyczyny problemu, ale problem nie zawsze występuje i przeważnie trzeba na niego dosyć długo czekać... dlatego proszę o pomoc bardziej zaznajomionych z tematem ^^

z góry dziekuję za pomoc,
pozdrawiam,
p.

0

Nie wiem czy w tym tkwi problem, ale - z procesu rodzica tworzysz dwa procesy potomne, po czym rodzic kończy działanie. Procesy potomne przechodzą pod "władzę" init i zazwyczaj zostają zakończone. Warto byłoby dodać w rodzicu wait() na oba procesy potomne. (http://linux.die.net/man/2/wait)

Mogę głosić herezję, więc jeżeli coś napisałem źle proszę o poprawienie mnie :) Z góry dziękuję :)

0
sznurek napisał(a)

Procesy potomne przechodzą pod "władzę" init i zazwyczaj zostają zakończone. Warto byłoby dodać w rodzicu wait() na oba procesy potomne. (http://linux.die.net/man/2/wait)

AFAIK init nie zabija adoptowanych dzieci, tylko spokojnie czeka na ich naturalny koniec.
Ale IMVHO użycie wait to bardzo dobry pomysł: będziesz mógł wywalić info dokładnie kiedy wywala się jeden z procesów, jak również po analizie kodu zwróconego przez tą funkcję dowiedzieć sie więcej o przyczynie wywalenia (np. SIGSEGV)

0

po kilku dniach prób (strasznie rzadko to wyskakuje) w końcu udało mi się wyciągnąć przez perror() informację o błędzie^^ jakieś sugestie, co w tym przypadku może znaczyć: Illegal seek? z tego co kojarzę, to wiązało się chyba z błednym przesunięciem lub jakoś tak...

[EDIT]
rozwiazanie- ktoś w pracowni zmapował dużo wiecej zasobów, niż było dostępnych (system przenoszony z innego kompa bez rekonfiguracji) i stąd problem... :/

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