我正在尝试使用双流程方案实现生产者 - 消费者问题。
Process1 - Producer和Process2 - Consumer。消费者流程正在等待条件变量(pthread_cond_wait(cond)
),生产者将通过pthread_cond_signal(cond)
向消费者发送信号。
我已经浏览过这些链接shared mutex and condition variable across process pthread_mutexattr_setpshared
,据说可以在多个进程中使用互斥和条件变量,
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
在此链接shared mutexes中,作为void的推荐,据说检查我的系统是否支持?我已经检查过,我得到了200809作为sysconf(_SC_THREAD_PROCESS_SHARED)
的返回值,表示我的系统支持PTHREAD_PROCESS_SHARED
。
我正在尝试将pthread_cond_signal
从生产者(进程-1)发送到使用者(进程-2)。生产者和使用者都使用初始化的相同互斥/条件变量。
但是,消费者没有收到信号。似乎信号未发送或丢失。
我在哪里犯错误?我使用的是Ubuntu,gcc-4.6.3。
这是我的代码。
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sched.h>
#include <syscall.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>
pthread_cond_t* condition;
pthread_mutex_t* mutex;
#define OKTOWRITE "/oktowrite"
#define MESSAGE "/message"
#define MUTEX "/lock"
struct shared_use_st
{
bool conditionSatisfied;
};
struct shared_use_st *shared_stuff;
void create_shared_memory()
{
int shmid;
void *shared_memory=(void *)0;
shmid =shmget( (key_t)1234, 4096, 0666 | IPC_CREAT );
if (shmid == -1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory =shmat(shmid, (void *)0,0);
if(shared_memory == (void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
shared_stuff = (struct shared_use_st *)shared_memory;
}
int main()
{
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_mutex < 0) {
perror("failure on shm_open on des_mutex");
exit(1);
}
if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED ) {
perror("Error on mmap on mutex\n");
exit(1);
}
des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_cond < 0) {
perror("failure on shm_open on des_cond");
exit(1);
}
if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED ) {
perror("Error on mmap on condition\n");
exit(1);
}
/* set mutex shared between processes */
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mutex, &mutexAttr);
/* set condition shared between processes */
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(condition, &condAttr);
create_shared_memory();
shared_stuff->conditionSatisfied=0;
int count=0;
while(count++<10)
{
pthread_mutex_lock(mutex);
shared_stuff->conditionSatisfied=1;
pthread_mutex_unlock(mutex);
pthread_cond_signal(condition);
printf("signal sent to consumer, %d\n",count);
sleep(3);
}
pthread_condattr_destroy(&condAttr);
pthread_mutexattr_destroy(&mutexAttr);
pthread_mutex_destroy(mutex);
pthread_cond_destroy(condition);
shm_unlink(OKTOWRITE);
shm_unlink(MESSAGE);
shm_unlink(MUTEX);
return 0;
}
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sched.h>
#include <syscall.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>
pthread_cond_t* condition;
pthread_mutex_t* mutex;
#define OKTOWRITE "/oktowrite"
#define MESSAGE "/message"
#define MUTEX "/lock"
struct shared_use_st
{
bool conditionSatisfied;
};
struct shared_use_st *shared_stuff;
void create_shared_memory()
{
int shmid;
void *shared_memory=(void *)0;
shmid =shmget( (key_t)1234, 4096, 0666 | IPC_CREAT );
if (shmid == -1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory =shmat(shmid, (void *)0,0);
if(shared_memory == (void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
shared_stuff = (struct shared_use_st *)shared_memory;
}
int main()
{
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_mutex < 0) {
perror("failure on shm_open on des_mutex");
exit(1);
}
if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED ) {
perror("Error on mmap on mutex\n");
exit(1);
}
des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_cond < 0) {
perror("failure on shm_open on des_cond");
exit(1);
}
if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED ) {
perror("Error on mmap on condition\n");
exit(1);
}
/* set mutex shared between processes */
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mutex, &mutexAttr);
/* set condition shared between processes */
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(condition, &condAttr);
create_shared_memory();
shared_stuff->conditionSatisfied=0;
while(1)
{
printf("Receiver waits on for signal from hello1.c \n");
pthread_mutex_lock(mutex);
while(!shared_stuff->conditionSatisfied)
pthread_cond_wait(condition, mutex);
pthread_mutex_unlock(mutex);
printf("Signal received, wake up!!!!!!!!\n");
//reset
pthread_mutex_lock(mutex);
shared_stuff->conditionSatisfied=0;
pthread_mutex_unlock(mutex);
}
}
答案 0 :(得分:2)
进程间共享的互斥锁只能由其中一个进行初始化
错误是您正在初始化两个进程上的互斥和条件。但是,由于它们是共享的,因此您只应在使用者上初始化它们。
我还建议不要将旧的System V shmget / shmat 函数与新的POSIX shm_open 混合使用。
我定义了一个新的共享整数 shint ,它指向一个用 shm_open 初始化并通过 mmap 连接的共享内存。 shint 用作等待pthread 条件的标志。
在我看来,生产者,在消费者之后启动,不需要截断内存段,只能用O_RDWR打开共享内存。生产者首先获取锁定并将 shint 设置为1。
另一方面,首先启动的使用者必须创建共享内存段并使用 ftruncate 调整它们的大小。它还将共享标志 shint 设置为0并等待它。此外,在调用 shm_open 之前,最好取消链接(通过shm_unlik)所有使用的共享内存段,以清除先前调用的最终错误(例如,如果代码在取消链接之前崩溃)。
我在开始时移动了互斥和条件的属性的初始化,因为它看起来更清晰和正确。
<强> Producer.c 强>
int main()
{
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
/* set mutex shared between processes */
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
/* set condition shared between processes */
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
des_mutex = shm_open(MUTEX, O_RDWR, mode);
if (des_mutex < 0) {
perror("failure on shm_open on des_mutex");
exit(1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED ) {
perror("Error on mmap on mutex\n");
exit(1);
}
des_cond = shm_open(OKTOWRITE, O_RDWR, mode);
if (des_cond < 0) {
perror("failure on shm_open on des_cond");
exit(1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t), PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED ) {
perror("Error on mmap on condition\n");
exit(1);
}
int fd = shm_open(MESSAGE, O_RDWR, 0644);
if (fd < 0) {
perror("failure on shm_open on fd");
exit(1);
}
if(ftruncate(fd, sizeof(int)) == -1) {
perror("Error on ftruncate to sizeof ftruncate fd\n");
exit(-1);
}
int *shint;
shint = (int *) mmap(NULL, sizeof(int), PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if (shint == MAP_FAILED ) {
perror("Error on mmap on shint\n");
exit(1);
}
// set ot 0
*shint = 0;
int count=0;
while(count++<10)
{
pthread_mutex_lock(mutex);
*shint = 1;
pthread_mutex_unlock(mutex);
pthread_cond_signal(condition);
printf("signal sent to consumer, %d\n",count);
sleep(3);
}
pthread_condattr_destroy(&condAttr);
pthread_mutexattr_destroy(&mutexAttr);
pthread_mutex_destroy(mutex);
pthread_cond_destroy(condition);
shm_unlink(OKTOWRITE);
shm_unlink(MESSAGE);
shm_unlink(MUTEX);
return 0;
}
<强> Consumer.c 强>
int main()
{
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
// Unlink first to clean
shm_unlink(MUTEX);
shm_unlink(OKTOWRITE);
shm_unlink(MESSAGE);
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR, mode);
if (des_mutex < 0) {
perror("failure on shm_open on des_mutex");
exit(1);
}
if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED ) {
perror("Error on mmap on mutex\n");
exit(1);
}
des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR, mode);
if (des_cond < 0) {
perror("failure on shm_open on des_cond");
exit(1);
}
if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED ) {
perror("Error on mmap on condition\n");
exit(1);
}
int fd = shm_open(MESSAGE, O_CREAT|O_RDWR, 0644);
if (fd < 0) {
perror("failure on shm_open on fd");
exit(1);
}
if(ftruncate(fd, 16) == -1) {
perror("Error on ftruncate to sizeof ftruncate fd\n");
exit(-1);
}
int *shint;
shint = (int *) mmap(NULL, sizeof(int), PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if (shint == MAP_FAILED ) {
perror("Error on mmap on shint\n");
exit(1);
}
*shint = 0;
if (pthread_mutex_init(mutex, &mutexAttr) != 0) {printf("Error initi mutex"); exit(111);}
if (pthread_cond_init(condition, &condAttr) != 0) {printf("Error initi cond"); exit(111);}
while(1)
{
printf("Receiver waits on for signal from hello1.c \n");
pthread_mutex_lock(mutex);
while(shint == 0)
pthread_cond_wait(condition, mutex);
printf("Waiting"); sleep(1);
pthread_mutex_unlock(mutex);
printf("Signal received, wake up!!!!!!!!\n");
break;
//reset
pthread_mutex_lock(mutex);
shared_stuff->conditionSatisfied=0;
pthread_mutex_unlock(mutex);
}
return 0;
}