【问题标题】:semaphore synchronization going wrong, in producer consumer example信号量同步出错,在生产者消费者示例中
【发布时间】:2014-03-20 03:36:41
【问题描述】:

我正在尝试编写单个生产者-消费者问题,如下所示。我将通过共享内存传递 i 的增量值。但是,我发现生产者发送的初始值丢失,生产者发送 0,但消费者未能捕获 0,而是从 1 捕获。我不明白为什么会这样。服务器将 0 写入共享内存,并等待空,一旦客户端程序开始运行,甚至在读取初始值之前,空在生产者中以某种方式释放,并写入 1。0 在这里丢失.我在这里指定了两个进程的代码。

Semaphore_Server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include<stdlib.h>
#include <sys/shm.h>

struct a
{
    int a;
    int b;
} a_s;

void wait(int semid)
{
    int err,nsops=1;
    struct sembuf *sopwait = (struct sembuf *) malloc(sizeof(struct sembuf));
    sopwait[0].sem_num = 0;
    sopwait[0].sem_op = -1;
    sopwait[0].sem_flg = 0;
    err = semop(semid, sopwait, nsops);
    if(err < 0)
        printf(" unable to do the sop \n");
}

void signal(int semid)
{
    int err,nsops=1;
    struct sembuf *sops = (struct sembuf *) malloc(sizeof(struct sembuf));      
    sops[0].sem_num = 0;
    sops[0].sem_op = 1;
    sops[0].sem_flg = 0;
    err = semop(semid, sops, nsops);
    if(err < 0)
        printf(" unable to do the sop \n");
}

int main()
{
    int i, err;
    int full,empty;
    key_t full_key = 1234, empty_key = 5678;
    int sem_flg = IPC_CREAT | 0666;
    int nsems = 1;
    int nsops = 2;
    int shmid;
    void *string;
    void *s;
    int shm_key = 9999;

    struct a *a_str = (struct a*)malloc(sizeof(struct a));
    /*****************************************/

    empty = semget(empty_key, nsems, sem_flg);
    if(empty < 0)
        printf(" failed to initialize the semaphore \n");

    semctl(empty, 0, SETVAL, 1) ;
    /****************************************/
    full = semget(full_key, nsems, sem_flg);
    if(full < 0)
        printf(" failed to initialize the semaphore \n");

    semctl(full, 0, SETVAL, 0) ;    

    /*****************************************/
    shmid = shmget(shm_key, 30, IPC_CREAT|0666); 
    if(shmid < 0) 
        printf(" unable to create shmem \n");
    else
        printf(" created shm \n");

    string = shmat(shmid, NULL, 0); 
    if(string == (void * ) (-1))
        printf(" unable to attach the string \n");
    else
        printf(" success with shmat \n");
    s = string;
    /******************************************/
    i = 0;
    while(i < 20)
    {
        wait(empty);
        a_str->a = i;
        memcpy( string, (void *) a_str, sizeof(struct a));
        printf(" wrote the string %d \n", i);
        i++;
        signal(full);
    }
}

信号量_client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include<stdlib.h>
#include <sys/shm.h>

struct a
{
    int a;
    int b;
} a_s;

void wait(int semid)
{
    int err,nsops=1;
    struct sembuf *sopwait = (struct sembuf *) malloc(sizeof(struct sembuf));
    sopwait[0].sem_num = 0;
    sopwait[0].sem_op = -1;
    sopwait[0].sem_flg = 0;
    err = semop(semid, sopwait, nsops);
    if(err < 0)
        printf(" unable to do the sop \n");
}

void signal(int semid)
{
    int err,nsops=1;
    struct sembuf *sops = (struct sembuf *) malloc(sizeof(struct sembuf));      
    sops[0].sem_num = 0;
    sops[0].sem_op = 1;
    sops[0].sem_flg = 0;
    err = semop(semid, sops, nsops);
    if(err < 0)
        printf(" unable to do the sop \n");
}

int main()
{
    int i, err;
    int full,empty;
    key_t full_key = 1234, empty_key = 5678;
    int sem_flg = IPC_CREAT | 0666;
    int nsems = 1;
    int nsops = 2;
    int shmid;
    void *string;
    void *s;
    int shm_key = 9999;

    struct a *a_str = (struct a*)malloc(sizeof(struct a));
    /*****************************************/

    empty = semget(empty_key, nsems, sem_flg);
    if(empty < 0)
        printf(" failed to initialize the semaphore \n");

    semctl(empty, 0, SETVAL, 1) ;
    /****************************************/
    full = semget(full_key, nsems, sem_flg);
    if(full < 0)
        printf(" failed to initialize the semaphore \n");

    semctl(full, 0, SETVAL, 0) ;    

    /*****************************************/
    shmid = shmget(shm_key, 30, IPC_CREAT|0666); 
    if(shmid < 0) 
        printf(" unable to create shmem \n");
    else
        printf(" created shm \n");

    string = shmat(shmid, NULL, 0); 
    if(string == (void * ) (-1))
        printf(" unable to attach the string \n");
    else
        printf(" success with shmat \n");
    s = string;
    /******************************************/
    i = 0;
    while(i < 20)
    {
        wait(full);
        memcpy((void *)a_str, (void *)s, sizeof(struct a));
        printf(" a %d \n",((struct a *)a_str)->a);
        i++;
        signal(empty);
    }

    return 0;
}

谁能告诉我为什么服务器在客户端读取一次之前写入两次? 这是服务器的输出。 写了字符串 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

客户端输出: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

【问题讨论】:

  • 为什么不使用更好的 POSIX IPC API?
  • 因为这需要与 -lpthreads 链接,我更愿意避免使用这种方法。这个方法在我们项目的其他地方使用。它可以很好地与它们一起工作。我不知道这里出了什么问题。
  • posix API 在哪些方面更好?
  • 嗯,它更简单,也更容易使用。
  • @leelduhem,谢谢,我正在尝试使用 lpthreads,但我仍然想知道这个会出现什么问题。我无法选择出了什么问题。

标签: c synchronization semaphore producer-consumer


【解决方案1】:

谁能告诉我为什么服务器在客户端读取一次之前写入两次?

这很容易解决,在您的Semaphore _client.c 中删除这两个对semctl() 的调用。

解释:

  1. 如果服务器先运行,它将向共享内存写入0,并在wait(empty);处等待;但是一旦你在客户端调用semctl(empty, 0, SETVAL, 1);,服务器中的等待就会返回,服务器可能会开始写1,在这种情况下,0会丢失。

  2. 如果客户端先运行,您的代码将正常运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多