Problem producenta i konsumenta z użyciem semaforów, pamięci dzielonej. Program zatrzymuje się po wejściu do sekcji krytycznej. Po zmianie semaforów w funkcji setValue (na końcu sekcji krytycznej) program wykonuje się do końca, ale plik wynikowy jest pusty. Prawdopodobnie napiszę obie sekcje krytyczne od nowa, na pewno zamienię semafory binarne na ogólne (informujące kolejno o pełnym i pustym buforze), tak by oba procesy mogły operować na pojedynczych (różnych od siebie) elementach bufora.
prod.c:
#include "mem_func.h"
#include "sem_func.h"
int main(int argc, char const *argv[])
{
const int id_sem=atoi(argv[1]);
const int mem_id=atoi(argv[2]);
char buf[BUF_SIZE];
const int file1=open(argv[3], O_RDONLY, 0644);
if(file1==-1)
{
perror("Blad funkcji open() - proc. producenta\n");
exit(9);
}
Towar *bufor;
bufor=(Towar*) memAtt(mem_id, O_WRONLY);
/*bufor[0].begin=0;
bufor[0].end=0;*/
setValue(id_sem, SEM0, VAL);
int bytes_read=0;
int bytes_written=0;
do
{
bufor->begin=0;
bufor->end=0;
bytes_read=read(file1, buf, sizeof(buf));
if(bytes_read==-1)
{
perror("Producent nie moze odczytac pliku\n");
exit(10);
}
bytes_written=0;
while(bytes_written<bytes_read)
{
down(id_sem, SEM0);
printf("Producent - sekcja krytyczna\n");
int i=0;
bufor->share[bufor->end]=buf[i];
++bytes_written;
++bufor->end;
//bufor->share[bufor->end]='\0';
++i;
up(id_sem, SEM1);
}
}while(bytes_read>0);
if(close(file1)==-1)
{
perror("Blad funkcji close() - proces producenta\n");
exit(11);
}
delAtt(bufor);
return 0;
}
kons.c:
#include "mem_func.h"
#include "sem_func.h"
int main(int argc, char const *argv[])
{
const int id_sem=atoi(argv[1]);
const int mem_id=atoi(argv[2]);
char buf[BUF_SIZE];
const int file2=open(argv[3], O_WRONLY|O_CREAT, 0644);
if(file2==-1)
{
perror("Blad funkcji open() - proc. konsumenta\n");
exit(9);
}
Towar *bufor;
bufor=(Towar*) memAtt(mem_id, O_RDONLY);
bufor->begin=0;
bufor->end=0;
setValue(id_sem, SEM1, VAL);
int bytes_read=0;
int bytes_written=0;
do
{
down(id_sem, SEM1);
printf("Konsument - sekcja krytyczna\n");
bytes_read=read(bufor->share[bufor->begin], buf, 1);
if(bytes_read==-1)
{
perror("Blad funkcji read() - proces konsumenta\n");
exit(10);
}
++bufor->begin;
if(bufor->begin==49)
{
bufor->begin=0;
}
up(id_sem, SEM0);
bytes_written=0;
ssize_t ret=(file2, buf+bytes_written, bytes_read-bytes_written);
if(ret==-1)
{
perror("Blad funkcji write()\n");
exit(11);
}
printf("%s\n", buf);
bytes_written+=ret;
}while(bytes_read>0);
if(close(file2)==-1)
{
perror("Blad funkcji close() - proces konsumenta\n");
exit(11);
}
delAtt(bufor);
return 0;
}
memfc.c:
#include "mem_func.h"
int memCreate()
{
const int key=ftok(PATH, 'b');
if(key==-1)
{
perror("Blad funkcji memCreate\n");
exit(12);
}
return key;
}
int memAccess(int key, int size)
{
const int mem_id=shmget(key, size, IPC_CREAT|IPC_EXCL|MODE);
if(mem_id==-1)
{
perror("Blad funkcji memAccess\n");
exit(13);
}
return mem_id;
}
void memDel(int mem_id)
{
struct shmid_ds buf;
if(shmctl(mem_id, IPC_RMID, (struct shmid_ds*)0)==-1)
{
perror("Blad funkcji memDel()\n");
exit(14);
}
else printf("Usunieto pamiec dzielona\n");
}
void *memAtt(int mem_id, int mode)
{
void *shm=shmat(mem_id, NULL, mode);
if(shm==(void*)-1)
{
fprintf(stderr, "Blad funkcji memAtt()\n");
exit(15);
}
else printf("Utworzono dowiazanie\n");
return shm;
}
void delAtt(void *shm)
{
if(shmdt(shm)==-1)
{
fprintf(stderr, "Blad funkcji delAtt()\n");
exit(16);
}
else printf("Usunieto dowiazanie\n");
}
int memSize(int mem_id)
{
struct shmid_ds x;
if(shmctl(mem_id, IPC_STAT, &x)==-1)
{
perror("Blad funkcji memSize()\n");
exit(17);
}
return x.shm_segsz;
}
semfc.c:
#include "sem_func.h"
#define SEM_NR 2 //liczba semaforów
#define MODE 0600 //tryb
#define PATH "./main.x" //ścieżka pliku dla funkcji ftok()
int semAccess(key_t key)
{
int semid;
semid=semget(key, SEM_NR, IPC_CREAT|MODE);
if(semid==-1)
{
perror("Blad funkcji semAccess()\n");
exit(4);
}
return semid;
}
void setValue(int semid, int nsem, int val)
{
union semun ctrl;
ctrl.val=val;
if(semctl(semid, nsem, SETVAL, ctrl)==-1) //SETVAL orzymuje wartość 1
{
perror("Blad funkcji setValue()\n");
exit(5);
}
}
void up(int semid, int nsem)
{
struct sembuf do_op = {
.sem_num=nsem,
.sem_op=1,
.sem_flg=0
};
//struktura zawiera kolejno: nr semafora, operację, flagę
//czyli: semnum, sem_op, sem_flg
//0 - operacja blokująca
if(semop(semid, &do_op, VAL)==-1)
{
perror("Blad funkcji up()\n");
exit(2);
}
}
void down(int semid, int nsem)
{
struct sembuf do_op = {
.sem_num=nsem,
.sem_op=-1,
.sem_flg=0
};
if(semop(semid, &do_op, VAL)==-1)
{
perror("Blad funkcji down()\n");
exit(2);
}
}
void semDelete(int semid, int nsem) //usuwanie semafora
{
if(semctl(semid, nsem, IPC_RMID)==-1) //obsługa błędów
{
perror("Blad funkcji semDelete\n");
exit(1);
}
else //komunikat
{
printf("Semafor zostal usuniety\n");
}
}
key_t createSem() //uzyskanie dostępu do semafora
{
int key;
if((key=ftok(PATH, 'a'))==-1)
{
perror("Blad funkcji createSem()\n");
exit(3);
}
return key;
}
memfc.h:
//biblioteka dla pamięci dzielonej
#ifndef MEM_FUNC_H
#define MEM_FUNC_H
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PATH "./consumer.x"
#define MODE 0600
#define MEM_SIZE 50
#define BUF_SIZE 50
typedef struct
{
char share[MEM_SIZE];
int begin;
int end;
} Towar;
int memCreate(); //tworzenie pamięci dzielonej
int memAccess(int key, int size); //dostęp do pamięci dzielonej
void memDel(int mem_id); //usuwanie pamięci dzielonej
void *memAtt(int mem_id, int mode); //tworzenie dowiązania
void delAtt(void *mem_id); //usuwanie dowiązania
int memSize(int mem_id); //rozmiar pamięci dzielonej
#endif
semfc.h:
//biblioteka dla semaforów
#ifndef SEM_FUNC_H
#define SEM_FUNC_H
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <time.h>
#ifdef _SEM_SEMUN_UNDEFINED
union semun {
int val; //wartosc dla SETVAL
struct semid_ds *buf; //bufor dla IPC_STAT, IPC_SET
unsigned short *array; //tablica dla GETALL, SETALL
struct seminfo *__buf; //bufor dla IPC_INFO (specyfika Linuksa)
};
#endif //_SEM_SEMUN_UNDEFINED
enum {SEM0, SEM1, VAL=1, VAL2, SLV=5};
int semAccess(key_t key); //utworzenie semafora
void setValue(int semid, int nsem, int val);
//przypisanie wartośći (inicjalizacja)
void up(int semid, int nsem); //podniesienie semafora...
void down(int semid, int nsem); //...i jego opuszczenie
key_t createSem(); //dostęp do semafora
//int queue(int semid); //kolejka
void semDelete(int semid, int nsem); //usunięcie semafora
#endif //FUNC_H
Prosiłbym o sprawdzenie kodu pod kątem błędów (oczywiście bez sekcji krytycznych, które idą do kosza).