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

2014-11-24 13:08:36 · 作者: · 浏览: 2
用信号量解决生产者消费者问题: ipc.h #ifndef _IPC_H_
#define _IPC_H_


#include
#include
#include
#include
#include
#include
#include
#include
#include


#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)


union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
/* Linux specific part: */
struct seminfo *__buf; /* buffer for IPC_INFO */
};


int sem_create(key_t key);
int sem_open(key_t key);


int sem_p(int semid);
int sem_v(int semid);
int sem_d(int semid);
int sem_setval(int semid, int val);
int sem_getval(int semid);
int sem_getmode(int semid);
int sem_setmode(int semid,char* mode);




#endif /* _IPC_H_ */

ipc.c #include "ipc.h"


int sem_create(key_t key)
{
int semid = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);
if (semid == -1)
ERR_EXIT("semget");


return semid;
}


int sem_open(key_t key)
{
int semid = semget(key, 0, 0);
if (semid == -1)
ERR_EXIT("semget");


return semid;
}


int sem_p(int semid)
{
struct sembuf sb = {0, -1, 0};
int ret = semop(semid, &sb, 1);
if (ret == -1)
ERR_EXIT("semop");


return ret;
}


int sem_v(int semid)
{
struct sembuf sb = {0, 1, 0};
int ret = semop(semid, &sb, 1);
if (ret == -1)
ERR_EXIT("semop");


return ret;
}


int sem_d(int semid)
{
int ret = semctl(semid, 0, IPC_RMID, 0);
/*
if (ret == -1)
ERR_EXIT("semctl");
*/
return ret;
}


int sem_setval(int semid, int val)
{
union semun su;
su.val = val;
int ret = semctl(semid, 0, SETVAL, su);
if (ret == -1)
ERR_EXIT("semctl");


//printf("value updated...\n");
return ret;
}


int sem_getval(int semid)
{
int ret = semctl(semid, 0, GETVAL, 0);
if (ret == -1)
ERR_EXIT("semctl");


//printf("current val is %d\n", ret);
return ret;
}


int sem_getmode(int semid)
{
union semun su;
struct semid_ds sem;
su.buf = &sem;
int ret = semctl(semid, 0, IPC_STAT, su);
if (ret == -1)
ERR_EXIT("semctl");


printf("current permissions is %o\n",su.buf->sem_perm.mode);
return ret;
}


int sem_setmode(int semid,char* mode)
{
union semun su;
struct semid_ds sem;
su.buf = &sem;


int ret = semctl(semid, 0, IPC_STAT, su);
if (ret == -1)
ERR_EXIT("semctl");


printf("current permissions is %o\n",su.buf->sem_perm.mode);
sscanf(mode, "%o", (unsigned int*)&su.buf->sem_perm.mode);
ret = semctl(semid, 0, IPC_SET, su);
if (ret == -1)
ERR_EXIT("semctl");


printf("permissions updated...\n");


return ret;
}
sshfifo.h #ifndef _SHM_FIFO_H_
#define _SHM_FIFO_H_


#include "ipc.h"


typedef struct shmfifo shmfifo_t;
typedef struct shmhead shmhead_t;


struct shmhead
{
unsigned int blksize; // 块大小
unsigned int blocks; // 总块数
unsigned int rd_index; // 读索引
unsigned int wr_index; // 写索引
};


struct shmfifo
{
shmhead_t *p_shm; // 共享内存头部指针
char *p_payload; // 有效负载的起始地址


int shmid; // 共享内存ID
int sem_mutex; // 用来互斥用的信号量
int sem_full; // 用来控制共享内存是否满的信号量
int sem_empty; // 用来控制共享内存是否空的信号量
};


shmfifo_t* shmfifo_init(int key, int blksize, int blocks);
void shmfifo_put(shmfifo_t *fifo, const void *buf);
void shmfifo_get(shmfifo_t *fifo, void *buf);
void shmfifo_destroy(shmfifo_t *fifo);


#endif /* _SHM_FIFO_H_ */

sshfifo.c #include "shmfifo.h"
#include


shmfifo_t* shmfifo_init(int key, int blksize, int blocks)
{
shmfifo_t *fifo = (shmfifo_t *)malloc(sizeof(shmfifo_t));
assert(fifo != NULL);
memset(fifo, 0, sizeof(shmfifo_t));




int shmid;
shmid = shmget(key, 0, 0);
int size = sizeof(shmhead_t) + blksize*blocks;