c - 共享内存和 POSIX 信号量

标签 c concurrency posix ipc

我用 C 编写了简单的消费者-生产者程序。当我有 1 个生产者和 1 个消费者时,它工作正常。但是当我增加消费者数量时,它表现得很奇怪。

  1. 我启动生产者进程
  2. 制作人正在制作
  3. 我启动消费者进程
  4. 消费者在消费,生产者在生产
  5. 我启动第 2 个消费者进程
  6. 消费者进程 2 永远不会获取元素
  7. 当我启动第 3 号、第 4 号消费者...等等时,同样的事情发生了

第二个问题:

  1. 生产者生产了最多的元素
  2. 消费者消费所有元素,但生产者不再继续生产

我不知道为什么会这样。

代码:

制作人:

#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);
    }

}

通用.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;
};

最佳答案

问题解决了。 我正在设置 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.

关于c - 共享内存和 POSIX 信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30121124/

相关文章:

c - 可以在另一个 .c 文件中包含一个 .c 文件吗?

c - C/linux 中的排序 glob

c - 如何将自己的输出通过管道传递给另一个进程?

c# - 与 C# 和 C++ 相比,Python 中的并发支持

c - 在线程中安全地返回浮点值

c - Linux 上的 read() 和页对齐缓冲区

c 中的连接字符 : argument of type "char" is incompatible with parameter of type "const char*"

java - Spring 异步不起作用

go - 如何使用 channel 对 golang 管道阶段中的项目进行批处理?

c - 用于 Visual Studio C 的 POSIX 兼容正则表达式库