Linux下的简单生产、消费模型的实现(下)
来源:互联网 发布:mac twisted 安装 编辑:程序博客网 时间:2024/05/20 02:21
生产消费模型中生产者与消费者是互相独立进程,而各个进程的内存空间是相互独立的,因为我们需要为生产者与消费者建立一块共享内存区,用于保存生产出的“产品”。
本文使用循环队列保存“产品”,队列为空时有head=tail=0
struct sharebuf
{
int buffer[MAX_BUFFER_SIZE];
int head;
int tail;
};
共享内存的命名与信号量的命名相同,我们一般使用宏定义
#define KEY_MEM ((key_t)103040914)
Linux提供的库函数为
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_tsize, int shmflg);此函数将建立一块大小为size字节的共享内存。
需要注意的是,shmget建立的一块共享内存必须使用shmat()才能得到这块内存的地址,库函数如下:
void *shmat(int shmid, const void*shmaddr, int shmflg);
其中shmaddr,shmflg参数使用0即可。返回值得到的地址,就可以像普通指针一样操作了。还需要注意的是这个指针应该进行相应的强制类型转换。
一段建立并初始化共享内存的代码如下:
struct sharebuf * ptr;
int id = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
buf.head = buf.tail = 0;
ptr = (struct sharebuf *)shmat(id, 0, 0);
ptr->tail = ptr->head = 0;
综合上文信号量和共享内存的操作方法,我们将所有相关的操作编写成share.h和share.c
//share.h
#define KEY_MEM ((key_t)103040914)
#define KEY_FULL ((key_t)203040914)
#define KEY_EMPTY ((key_t)303040914)
#define KEY_MUTEX ((key_t)403040914)
#define MAX_BUFFER_SIZE 10
struct sharebuf
{
int buffer[MAX_BUFFER_SIZE];
int head;
int tail;
};
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 create(int * id_mem, int * id_full, int * id_empty, int * id_mutex);
void init(int id_mem, int id_full, int id_empty, int id_mutex);
void wait(int id);
void release(int id);
void * getmem(int id);
//share.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "share.h"
int create(int * id_mem, int * id_full, int * id_empty, int * id_mutex)
{
*id_mem = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
*id_full = semget(KEY_FULL, 1, IPC_CREAT|0660);
*id_empty = semget(KEY_EMPTY, 1, IPC_CREAT|0660);
*id_mutex = semget(KEY_MUTEX, 1, IPC_CREAT|0660);
return (*id_mem != -1 && *id_full != -1 &&
*id_empty != -1 && *id_mutex != -1);
}
void init(int id_mem, int id_full, int id_empty, int id_mutex)
{
union semun un;
struct sharebuf * ptr;
un.val = MAX_BUFFER_SIZE;
semctl(id_empty, 0, SETVAL, un);
un.val = 0;
semctl(id_full, 0, SETVAL, un);
un.val = 1;
semctl(id_mutex, 0, SETVAL, un);
ptr = getmem(id);
ptr->tail = ptr->head = 0;
}
void wait(int id)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
}
void release(int id)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
}
void * getmem(int id)
{
return shmat(id_mem, 0, 0);
}
生产者的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"
int main(int argc, char ** args)
{
int count = 0;
int id_mem, id_full, id_empty, id_mutex;
struct sharebuf * ptr;
create(&id_mem, &id_full, &id_empty, &id_mutex);
init(id_mem, id_full, id_empty, id_mutex);
ptr = (struct sharebuf *)getmem(id_mem);
while (1)
{
wait(id_empty);
wait(id_mutex);
ptr->buffer[ptr->tail] = count++;
ptr->tail = (ptr->tail+1)%MAX_BUFFER_SIZE;
printf("producer:%d/n", count);
release(id_mutex);
release(id_full);
}
return 0;
}
消费者代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"
int main(int argc, char ** args)
{
int n = 0;
int id_mem, id_full, id_empty, id_mutex;
struct sharebuf * ptr;
create(&id_mem, &id_full, &id_empty, &id_mutex);
ptr = (struct sharebuf *)getmem(id_mem);
while (1)
{
wait(id_full);
wait(id_mutex);
n = ptr->buffer[ptr->head];
ptr->head = (ptr->head+1)%MAX_BUFFER_SIZE;
printf("customer:%d/n", n);
release(id_mutex);
release(id_empty);
}
return 0;
}
本文使用循环队列保存“产品”,队列为空时有head=tail=0
struct sharebuf
{
int buffer[MAX_BUFFER_SIZE];
int head;
int tail;
};
共享内存的命名与信号量的命名相同,我们一般使用宏定义
#define KEY_MEM ((key_t)103040914)
Linux提供的库函数为
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_tsize, int shmflg);此函数将建立一块大小为size字节的共享内存。
需要注意的是,shmget建立的一块共享内存必须使用shmat()才能得到这块内存的地址,库函数如下:
void *shmat(int shmid, const void*shmaddr, int shmflg);
其中shmaddr,shmflg参数使用0即可。返回值得到的地址,就可以像普通指针一样操作了。还需要注意的是这个指针应该进行相应的强制类型转换。
一段建立并初始化共享内存的代码如下:
struct sharebuf * ptr;
int id = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
buf.head = buf.tail = 0;
ptr = (struct sharebuf *)shmat(id, 0, 0);
ptr->tail = ptr->head = 0;
综合上文信号量和共享内存的操作方法,我们将所有相关的操作编写成share.h和share.c
//share.h
#define KEY_MEM ((key_t)103040914)
#define KEY_FULL ((key_t)203040914)
#define KEY_EMPTY ((key_t)303040914)
#define KEY_MUTEX ((key_t)403040914)
#define MAX_BUFFER_SIZE 10
struct sharebuf
{
int buffer[MAX_BUFFER_SIZE];
int head;
int tail;
};
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 create(int * id_mem, int * id_full, int * id_empty, int * id_mutex);
void init(int id_mem, int id_full, int id_empty, int id_mutex);
void wait(int id);
void release(int id);
void * getmem(int id);
//share.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "share.h"
int create(int * id_mem, int * id_full, int * id_empty, int * id_mutex)
{
*id_mem = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
*id_full = semget(KEY_FULL, 1, IPC_CREAT|0660);
*id_empty = semget(KEY_EMPTY, 1, IPC_CREAT|0660);
*id_mutex = semget(KEY_MUTEX, 1, IPC_CREAT|0660);
return (*id_mem != -1 && *id_full != -1 &&
*id_empty != -1 && *id_mutex != -1);
}
void init(int id_mem, int id_full, int id_empty, int id_mutex)
{
union semun un;
struct sharebuf * ptr;
un.val = MAX_BUFFER_SIZE;
semctl(id_empty, 0, SETVAL, un);
un.val = 0;
semctl(id_full, 0, SETVAL, un);
un.val = 1;
semctl(id_mutex, 0, SETVAL, un);
ptr = getmem(id);
ptr->tail = ptr->head = 0;
}
void wait(int id)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
}
void release(int id)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
}
void * getmem(int id)
{
return shmat(id_mem, 0, 0);
}
生产者的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"
int main(int argc, char ** args)
{
int count = 0;
int id_mem, id_full, id_empty, id_mutex;
struct sharebuf * ptr;
create(&id_mem, &id_full, &id_empty, &id_mutex);
init(id_mem, id_full, id_empty, id_mutex);
ptr = (struct sharebuf *)getmem(id_mem);
while (1)
{
wait(id_empty);
wait(id_mutex);
ptr->buffer[ptr->tail] = count++;
ptr->tail = (ptr->tail+1)%MAX_BUFFER_SIZE;
printf("producer:%d/n", count);
release(id_mutex);
release(id_full);
}
return 0;
}
消费者代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"
int main(int argc, char ** args)
{
int n = 0;
int id_mem, id_full, id_empty, id_mutex;
struct sharebuf * ptr;
create(&id_mem, &id_full, &id_empty, &id_mutex);
ptr = (struct sharebuf *)getmem(id_mem);
while (1)
{
wait(id_full);
wait(id_mutex);
n = ptr->buffer[ptr->head];
ptr->head = (ptr->head+1)%MAX_BUFFER_SIZE;
printf("customer:%d/n", n);
release(id_mutex);
release(id_empty);
}
return 0;
}
- Linux下的简单生产、消费模型的实现(下)
- Linux下的简单生产、消费模型的实现(上)
- 生产/消费模型的java实现
- 生产/消费模型的java实现
- Wait, notify实现的生产消费模型
- 一个简单linux和window下的生成、消费模型类
- 多线程内部类 实现的生产消费模型
- 简单生产消费模式的代码流程(Java代码)
- 线程的简单生产消费模式
- 生产-消费模式的synchronized和lock实现(十)
- 生产消费模式的几种实现
- 集群下的kafka实现多线程消费
- 用go的goroutine和channel实现一个简单的“生产、消费”(带有超时控制)小例子
- 基于单链表和环形队列的生产消费模型
- LINUX下简单的LED驱动模型(转载)
- wait/notify实现生产消费模型
- 多线程—NSThread实现生产消费模型。
- 阻塞队列实现--生产消费模型
- 简明 HTML CSS 开发规范
- 详细解说STL string
- 驳:女生怎么了
- Oracle8i/9i EXP/IMP使用经验
- Apache简介与配置
- Linux下的简单生产、消费模型的实现(下)
- 在Red Hat Linux中自动运行程序
- Gcc使用的内嵌汇编语法格式小教程zt
- gdb基础zt
- 微软的正则表达式教程 【索引】
- js 中的dom操作
- WinForm中Application.Exit与Environment.Exit的区别
- 测试先行的敏捷方法
- 学习ASP.NET月记(1)