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

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

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;

}

用信号量解决生产者消费者问题,布布扣,bubuko.com

时间: 2025-01-03 23:47:33

用信号量解决生产者消费者问题的相关文章

Linux下用环形buf以及POSIX版本信号量解决生产者消费者问题

一.Semaphore(信号量) Mutex变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源, 加锁时获得该资源,将Mutex减到0,表示不再有可用资源,解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源. 信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1. 即,如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同! 本次使用的是POSIX semaphore库函数,这种信号量不仅可以

用记录型信号量解决生产者-消费者问题

1 int in = 0, out = 0;//in: 输入指针, out: 输出指针; 2 item buffer[n];//n个缓冲区组成的数组; 3 semaphore mutex = 1, full = 0, empty = n; 4 //mutex: 互斥信号量, 生产者进程和消费者进程都只能互斥访问缓冲区; 5 //full: 资源信号量, 满缓冲区的数量; 6 //empty: 资源信号量, 空缓冲区的数量;//信号量不允许直接参与运算, 故都要定义; 7 8 //生产者程序; 9

基于POSIX的信号量的生产者消费者模型

信号量和Mutex类似,表示可用资源的数量,和Mutex不同的是,这个数量可以大于1,即如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同. 下面我们看看POSIX semaphore库函数,它既可以用于同一进程的线程间同步,也可以用于不同进程间的同步. 1. int sem_init(sem_t *sem,int pshared,unsigned int value) 我们可以用此函数来创建一个未命名的信号量,pshared参数表明是否在多个进程中使用信号量,如果是,将其设置为非0 值,

两种方式解决 生产者消费者问题

一.通过wait().notify()线程通信来实现 输出结果: 二.通过阻塞队列来解决生产者消费者问题 输出结果: 由输出结果可以看出:"最后阻塞队列中还剩下4个鸡蛋"明显是正确的,可知阻塞队列内部意见实现了同步,不需要我们额外同步,是线程安全的.

使用条件量解决生产者消费者问题

在linux多线程同步中,除了互斥量以外,pthread提供了另一种同步机制:条件变量.正如名字一样,条件量允许线程由于一些未达到的条件而阻塞. 条件变量与互斥量经常一起使用.这种模式用于让一个线程锁住一个变量,然后当它不能获得它期待的结果时等待一个条件变量.最后另一个线程会向他发出信号,使它可以继续执行.pthread_cond_wait原子性地调用并解锁它持有的互斥量.由于这个原因,互斥量是参数之一. 下面通过代码演示如何通过条件量来解决生产者消费者问题. #include<stdio.h>

java多线程解决生产者消费者问题

import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class Test { public static void main(String[] args) { GunClip clip = new GunClip(); Producer p = new Producer(clip); customer c = new customer(clip); p.star

【译】使用阻塞队列解决生产者-消费者问题

如果你想避免使用错综复杂的wait–notify的语句,BlockingQueue非常有用.BlockingQueue可用于解决生产者-消费者问题,如下代码示例.对于每个开发人员来说,生产者消费者问题已经非常熟悉了,这里我将不做详细描述. 为什么BlockingQueue适合解决生产者消费者问题 任何有效的生产者-消费者问题解决方案都是通过控制生产者put()方法(生产资源)和消费者take()方法(消费资源)的调用来实现的,一旦你实现了对方法的阻塞控制,那么你将解决该问题. Java通过Blo

Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post 有名信号量 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> sem_t *sem_open(co

【Windows】用信号量实现生产者-消费者模型

线程并发的生产者-消费者模型: 1.两个进程对同一个内存资源进行操作,一个是生产者,一个是消费者. 2.生产者往共享内存资源填充数据,如果区域满,则等待消费者消费数据. 3.消费者从共享内存资源取数据,如果区域空,则等待生产者填充数据. 4.生产者的填充数据行为和消费者的消费数据行为不可在同一时间发生. 下面用Windows的信号量以及线程等API模拟生产者-消费者模型 #include <Windows.h> #include <stdio.h> #define N 100 #d