【发布时间】:2018-02-07 19:34:01
【问题描述】:
我正在尝试使用互斥锁和共享缓冲区来解决生产者消费者问题,但在访问共享缓冲区结构中的值时遇到问题,特别是 char 数组。当我在一个终端中调用 producer.c 文件并使用
打印值(输入是字母表的 txt 文件)时printf("%c", newBuff->bytes[newBuff->rear]);
字符确实显示为正常,但是当我在 consumer.c 中做同样的事情时,但使用
printf("%c", newBuff->bytes[newBuff->front]);
这些值显示为空白。 newBuff->front 值为零,所以它应该打印字母 a。当我在 consumer.c 中访问我的结构中的其他值时,例如 front、count 或 back,它们是正确的。共享内存创建和附件也可以正常工作,所以我认为问题是我没有将 char 值正确存储在数组中,或者我试图错误地访问它们。在下面的代码中,我将 printf 放在 producer.c 的循环中,然后放在 consumer.c 的循环之外,因此我知道在消费者开始提取数据之前存在一个值。
Consumer.c
typedef struct buffer{
pthread_mutex_t lock;
pthread_cond_t shout;
int front;
int rear;
int count;
int endOfFile;
char bytes[1024];
} buffer;
int main(int argc, char const *argv[]) {
int i=0;
FILE *file = fopen(argv[1], "w");
if (argc != 2){
printf("You must enter in a file name\n");
}
int shmid, swapCount=0;
char swapBytes[] = "";
char path[] = "~";
key_t key = ftok(path, 7);
buffer* newBuff;
if ((shmid = shmget(key, SIZE, 0666 | IPC_CREAT | IPC_EXCL)) != -1) {
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("successful creation\n");
newBuff->front = 0;
newBuff->count = 0;
newBuff->endOfFile = 0;
pthread_mutexattr_t attr;
pthread_condattr_t condAttr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&newBuff->lock, &attr);
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&newBuff->shout, &condAttr);
} //shared memory creation
else if ((shmid = shmget(key, 0, 0)) != -1){
printf("%d\n", shmid);
printf("successful attachment\n" );
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("%c\n", newBuff->count);
}
else{
printf("oops\n");
exit(0);
}
pthread_mutex_lock(&newBuff->lock);
printf("%c\n", newBuff->bytes[newBuff->front]);
while (newBuff->endOfFile != 1)
{
while (newBuff->count == 0){
pthread_cond_signal(&newBuff->shout);
pthread_cond_wait(&newBuff->shout, &newBuff->lock);
}
newBuff->front = ((newBuff->front + 1)%SIZE);
newBuff->count--;
}
pthread_mutex_unlock(&newBuff->lock);
shmdt(&newBuff);
//pthread_mutexattr_destroy(&attr);
//pthread_condattr_destroy(&condAttr);*/
return 0;
}
Producer.c
typedef struct buffer{
pthread_mutex_t lock;
pthread_cond_t shout;
int front;
int rear;
int count;
int endOfFile;
char bytes[1024];
} buffer;
int main(int argc, char const *argv[]) {
FILE *file = fopen(argv[1], "r");
if (argc != 2){
printf("You must enter in a file dumbass\n");
}
int shmid;
char path[] = "~";
key_t key = ftok(path, 7);
buffer* newBuff;
printf("dfasdfasdf\n");
if ((shmid = shmget(key, SIZE, 0666 | IPC_CREAT | IPC_EXCL)) != -1) {
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("successful creation\n");
newBuff->front = 0;
newBuff->count = 0;
newBuff->endOfFile=0;
pthread_mutexattr_t attr;
pthread_condattr_t condAttr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&newBuff->lock, &attr);
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&newBuff->shout, &condAttr);
} //shared memory creation
else if ((shmid = shmget(key, 0, 0)) != -1){
printf("successful attachment\n" );
newBuff = (buffer*) shmat(shmid, 0, 0);
}
else{
printf("oops\n");
exit(0);
}
printf("%d\n", shmid);
pthread_mutex_lock(&newBuff->lock);
while (fscanf(file, "%c", &newBuff->bytes[newBuff->rear]) != EOF) //read in file
{
printf("%c\n", newBuff->bytes[newBuff->rear]);
while (newBuff->count >= SIZE){ //buffer is full
//("%c\n", newBuff->bytes[newBuff->rear]);
pthread_cond_signal(&newBuff->shout);
pthread_cond_wait(&newBuff->shout, &newBuff->lock);
}
//printf("%c\n", newBuff->bytes[newBuff->rear]);
newBuff->rear = ((newBuff->front + 1)%SIZE);
newBuff->count++;
}
newBuff->endOfFile = 1;
pthread_cond_signal(&newBuff->shout);
pthread_mutex_unlock(&newBuff->lock);
shmdt(&newBuff);
//pthread_mutexattr_destroy(&attr);
//pthread_condattr_destroy(&condAttr);
return 0;
}
【问题讨论】:
-
在某些时候,要么你的格式被破坏,要么你有一个函数之外的代码。请解决这个问题。另外,请删除重现问题所不需要的内容。我还建议您删除蛮力强制转换,它们通常仅用于隐藏问题,例如将 int 转换为指针时。
-
注意路径必须存在于对
ftok的调用中,这是一个要求。并且使用~是错误的,因为它仅由 shell 扩展。所以使用您选择的真实路径名。这可能不是您的问题的原因,但它是一个要求... -
调用
shmget(key, 0, 0)也是错误的,大小为0。您应该使用SIZE常量(据我所知)。 -
除非你需要引用结构的 name,(据我所知,你不需要)然后你不需要它,一般来说,你应避免使用与
name相同的符号创建type,即您创建了一个带有符号buffer的新类型,以及具有相同符号的名称。用typedef struct {...}buffer;替换你所拥有的 -
我认为这是一种风格考虑,@rykker。当然没有必要声明一个带有标签的结构类型,并声明相同的标识符作为该类型的别名,就像 OP 所做的那样,但它本质上并不是有害的,并且一些编码风格调用为它。