共享内存和 POSIX 信号量
Posted
技术标签:
【中文标题】共享内存和 POSIX 信号量【英文标题】:Shared memory and POSIX semaphores 【发布时间】:2015-05-08 10:04:19 【问题描述】:我用 C 编写了简单的消费者-生产者程序。当我有 1 个生产者和 1 个消费者时,它运行良好。但是当我增加消费者数量时,它的行为很奇怪。
-
我启动生产者进程
制片人正在制作
我启动消费者进程
消费者在消费,生产者在生产
我启动 2 号消费者进程
消费者进程 no2 永远不会获得元素
当我启动消费者 no3、no4... 等等时,也会发生同样的情况
第二个问题:
-
生产者生产了最多的元素
消费者消费所有元素,但生产者不再继续生产
我不知道为什么会这样。
代码:
制作人:
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <fcntl.h>
#include "common.h"
int memoryID;
struct wrapper *memory;
int rc;
void atexit_function()
rc = shmctl(memoryID, IPC_RMID, NULL);
rc = shmdt(memory);
sem_destroy(&memory->pmutex);
sem_destroy(&memory->cmutex);
sem_destroy(&memory->empty);
sem_destroy(&memory->full);
int main(int argc, char **argv)
atexit(atexit_function);
//creating key for shared memory
srand(time(NULL));
key_t sharedMemoryKey = ftok(".", MEMORY_KEY);
if (sharedMemoryKey == -1)
perror("ftok():");
exit(1);
memoryID = shmget(sharedMemoryKey, sizeof(struct wrapper), IPC_CREAT | 0600);
if (memoryID == -1)
perror("shmget():");
exit(1);
memory = shmat(memoryID, NULL, 0);
if (memory == (void *) -1)
perror("shmat():");
exit(1);
//initialization
printf("Initializtaion !\n");
memset(&memory->array, 0, sizeof(memory->array));
sem_init(&memory->pmutex, 0, 1);
sem_init(&memory->cmutex, 0, 1);
sem_init(&memory->empty, 0, SIZE_OF_ARRAY);
sem_init(&memory->full, 0, 0);
memory->n = -1;
if (memoryID == -1)
perror("shmget(): ");
exit(1);
while(1)
int r = rand();
sem_wait(&memory->empty);
sem_wait(&memory->pmutex);
memory->n++;
(memory->array)[memory->n]=r;
printf("Adding task\t Value:%d\tNumber of tasks waiting:%d \n",r,memory->n);
usleep(10000);
sem_post(&memory->pmutex);
sem_post(&memory->full);
消费者:
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include <sys/shm.h>
int memoryID;
struct wrapper *memory;
int check_prime(int a);
int main(int argc, char **argv)
srand(time(NULL));
key_t sharedMemoryKey = ftok(".",MEMORY_KEY);
if(sharedMemoryKey==-1)
perror("ftok():");
exit(1);
memoryID=shmget(sharedMemoryKey,sizeof(struct wrapper),0);
if(memoryID==-1)
perror("shmget(): ");
exit(1);
memory = shmat(memoryID,NULL,0);
if(memory== (void*)-1)
perror("shmat():");
exit(1);
while(1)
sem_wait(&memory->full);
sem_wait(&memory->cmutex);
int n = memory->n;
int temp = (memory->array)[n];
printf("Removed item: %d\tPrime:%d\tNumer of tasks left:%d\n",
temp, check_prime(temp),n);
memory->n--;
usleep(10000);
sem_post(&memory->cmutex);
sem_post(&memory->empty);
common.h:
#define MEMORY_KEY 12
#define SIZE_OF_ARRAY 10
struct wrapper
int array[SIZE_OF_ARRAY];
sem_t empty;
sem_t pmutex;
sem_t cmutex;
sem_t full;
int n;
;
【问题讨论】:
我认为您必须为其他流程留出时间来获取 sem。例如。 sem 发布后睡一会儿。 不幸的是它没有帮助 发布的代码似乎过于复杂。似乎没有/零需要任何信号量。数据需要互斥体、计数器和数组。当没有可处理的对象/int 时,消费者需要睡一会儿。当数组已满时,生产者需要休眠一会儿。我还建议,为避免未及时处理旧数据,将数组视为带有头尾指针的循环列表 【参考方案1】:问题解决了。
我正在设置int sem_init(sem_t *sem, int pshared, unsigned int value);
我将 pshared
值设置为 0 但是:
The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes. If pshared has the value 0, then the semaphore is shared between the threads of a process, and should be located at some address that is visible to all threads (e.g., a global variable, or a variable allocated dynamically on the heap). If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since a child created by fork(2) inherits its parent's memory mappings, it can also access the semaphore.) Any process that can access the shared memory region can operate on the semaphore using sem_post(3), sem_wait(3), etc.
【讨论】:
以上是关于共享内存和 POSIX 信号量的主要内容,如果未能解决你的问题,请参考以下文章