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ć.