用信号量解决生产者消费者问题(二)

2014-11-24 13:08:36 · 作者: · 浏览: 1

if (shmid == -1)
{
fifo->shmid = shmget(key, size, IPC_CREAT | 0666);
if (fifo->shmid == -1)
ERR_EXIT("shmget");


fifo->p_shm = (shmhead_t*)shmat(fifo->shmid, NULL, 0);
if (fifo->p_shm == (shmhead_t*)-1)
ERR_EXIT("shmat");


fifo->p_payload = (char*)(fifo->p_shm + 1);


fifo->p_shm->blksize = blksize;
fifo->p_shm->blocks = blocks;
fifo->p_shm->rd_index = 0;
fifo->p_shm->wr_index = 0;

fifo->sem_mutex = sem_create(key);
fifo->sem_full = sem_create(key+1);
fifo->sem_empty = sem_create(key+2);


sem_setval(fifo->sem_mutex, 1);
sem_setval(fifo->sem_full, blocks);
sem_setval(fifo->sem_empty, 0);
}
else
{
fifo->shmid = shmid;
fifo->p_shm = (shmhead_t*)shmat(fifo->shmid, NULL, 0);
if (fifo->p_shm == (shmhead_t*)-1)
ERR_EXIT("shmat");


fifo->p_payload = (char*)(fifo->p_shm + 1);


fifo->sem_mutex = sem_open(key);
fifo->sem_full = sem_open(key+1);
fifo->sem_empty = sem_open(key+2);
}


return fifo;
}


void shmfifo_put(shmfifo_t *fifo, const void *buf)
{
sem_p(fifo->sem_full);
sem_p(fifo->sem_mutex);


memcpy(fifo->p_payload+fifo->p_shm->blksize*fifo->p_shm->wr_index,
buf, fifo->p_shm->blksize);
fifo->p_shm->wr_index = (fifo->p_shm->wr_index + 1) % fifo->p_shm->blocks;
sem_v(fifo->sem_mutex);
sem_v(fifo->sem_empty);
}


void shmfifo_get(shmfifo_t *fifo, void *buf)
{
sem_p(fifo->sem_empty);
sem_p(fifo->sem_mutex);


memcpy(buf, fifo->p_payload+fifo->p_shm->blksize*fifo->p_shm->rd_index,
fifo->p_shm->blksize);
fifo->p_shm->rd_index = (fifo->p_shm->rd_index + 1) % fifo->p_shm->blocks;
sem_v(fifo->sem_mutex);
sem_v(fifo->sem_full);
}


void shmfifo_destroy(shmfifo_t *fifo)
{
sem_d(fifo->sem_mutex);
sem_d(fifo->sem_full);
sem_d(fifo->sem_empty);


shmdt(fifo->p_shm);
shmctl(fifo->shmid, IPC_RMID, 0);
free(fifo);
}

ssmfifo_free.c #include "shmfifo.h"


typedef struct stu
{
char name[32];
int age;
} STU;


int main(void)
{
shmfifo_t *fifo = shmfifo_init(1234, sizeof(STU), 3);
shmfifo_destroy(fifo);
return 0;
}

shmfifo_recv.c #include "shmfifo.h"


typedef struct stu
{
char name[32];
int age;
} STU;


int main(void)
{
shmfifo_t *fifo = shmfifo_init(1234, sizeof(STU), 3);


STU s;
memset(&s, 0, sizeof(STU));
int i;

for (i=0; i<5; i++)
{
shmfifo_get(fifo, &s);
printf("name = %s age = %d\n", s.name, s.age);
}

return 0;
}

shmfifo_send.c #include "shmfifo.h"


typedef struct stu
{
char name[32];
int age;
} STU;
int main(void)
{
shmfifo_t *fifo = shmfifo_init(1234, sizeof(STU), 3);


STU s;
memset(&s, 0, sizeof(STU));
s.name[0]='A';
int i;

for (i=0; i<5; i++)
{
s.age = 20 +i;
shmfifo_put(fifo, &s);
s.name[0] = s.name[0] + 1;


printf("send ok\n");
}

return 0;
}