您的位置:首页 > 其它

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

2014-05-19 19:22 411 查看
用信号量解决生产者消费者问题:
ipc.h
#ifndef _IPC_H_

#define _IPC_H_

#include <sys/types.h>

#include <unistd.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/shm.h>

#include <errno.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#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 <assert.h>

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;

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;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐