我试图编码一个生产者-消费者问题,如下所示。我将通过共享内存传递I的增量值。但是,我发现producer发送的初始值丢失,producer发送0,但是consumer无法捕获0,而是从1捕获。我不明白为什么会这样。服务器将0写入共享内存,并等待为空,一旦客户端程序开始运行,即使在读取初始值之前,empty也会在生产者中以某种方式释放,并写入1。0在此处丢失。我在这里指定这两个进程的代码。
信号量服务器.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);
}
}
信号量客户机
#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 16 17 18 19
客户端输出:
a 1 2 3 4 5 6 7 9 10 11 13 14 16 17 18 19
最佳答案
有谁能告诉我为什么服务器在客户机读一次之前写两次吗?
这很容易修复,删除semctl()
中对Semaphore _client.c
的这两个调用。
说明:
如果服务器先运行,它会将0写入共享内存,并在wait(empty);
处等待;但一旦在客户端调用semctl(empty, 0, SETVAL, 1);
,服务器中的等待将返回,服务器可能开始写入1,在这种情况下,0将丢失。
如果客户端先运行,则代码将正常工作。
关于c - 在生产者使用者示例中,信号量同步出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22522968/