我试图通过在队列中推送和弹出字符来解决生产者和消费者的问题。有两个主文件producer.c和consumer.c。它们都在开始时初始化了共享内存空间。Producer将首先运行,并初始化共享指针(static struct shared*sharedptr)中的变量。其中之一是队列(struct queue*buffer)。
生产者从文件中读取字符,然后一次一个地放入(推送)队列,而消费者则一次一个地从队列中读取、打印和取出字符(pop)。
问题是:producer在获取队列指针(memptr->buffer)和推入字符方面没有问题。但是,生产者不能访问队列,尽管它应该具有指向该队列的相同指针。
当我使用以下if语句进行测试时,当检查缓冲区是否为空时,它将正确打印:

if(memptr -> buffer == NULL)
    printf("Buffer is empty.\n");
else printf("Buffer is not empty.\n");

当我用这个测试时,分割错误发生了:
if(memptr -> buffer == NULL)
    printf("Buffer is empty.\n");
else if (memptr -> buffer -> tail == NULL){
    printf("Tail is NULL. Something went wrong.\n");
    exit(1);
}

我想它是在接近尾巴的时候发生的。它甚至不评估尾部是否为空;它只是发送segfault。当我使用common.c中所有与队列相关的函数(如下所示)进行测试时,并没有发生这种情况,而且producer运行良好。
指针怎么了?使用者可以访问(struct shared*)memptr中的其他变量,但不能访问buffer->tail。这对我来说毫无意义。
我在Mac上编译程序:
cc -c common.c

cc -o producer -Wall producer.c common.o

cc -o consumer -Wall consumer.c common.o

这是我所有的密码:
普通.h:
#define MEMSIZE 200
#define BUFFSIZE 5
#define MAXCOUNT 10

struct shared {
    /* synchronization variables */
    int choosing[MAXCOUNT + 1];
    int ticket[MAXCOUNT + 1];
    /* queue variables */
    struct Queue *buffer;
    int endOfFile;
    int in;     //variable that keeps track of bytes coming in
    int out;    //variable that keeps track of bytes coming in
    int count;  //count variable for producers
    FILE *file;
};

struct Link {
    char value;
    struct Link *next;
    struct Link *prev;
} Link;

struct Queue {
    int size;
    struct Link *head;
    struct Link *tail;
} Queue;

void mutexInit(struct shared *memptr);
void getMutex(short pid);
void releaseMutex(short pid);
void firstInit();
int max(int array[], int maxIndex);

struct Queue *initQueue();
struct Queue *push(char ch, struct Queue *q);
struct Queue *pop(struct Queue *q);
void printQueue(struct Queue *q);
char getBuffer(struct Queue *q);

通用c:
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

#include <limits.h>

#include "common.h"

#define FALSE 0
#define TRUE 1

static struct shared *sharedptr;

void mutexInit(struct shared *memptr){
    sharedptr = memptr;
}

void firstInit(){
    //initialize all variables to initial state
    int i;

    for(i = 0; i < 11; i++) {
        sharedptr -> choosing[i] = 0;
        sharedptr -> ticket [i] = 0;
    }
    sharedptr -> buffer = initQueue();
    sharedptr -> endOfFile = FALSE;
    sharedptr -> in = 0;
    sharedptr -> out = 0;
    sharedptr -> count = 1;
    sharedptr -> file = fopen("/Users/BenjaminHsu/Documents/ELEC 377/lab3/Queue/lab3.txt", "r");
    if(sharedptr -> file == NULL){
        printf("Can't find file.\n");
            exit(0);
    }
}

void getMutex(short pid){
    // this should not return until it has mutual exclusion.
    // Note that many versions of this will probobly be running at the same time.
    int j;

    sharedptr -> choosing[pid] = TRUE;
    sharedptr -> ticket[pid] = max(sharedptr -> ticket, sharedptr -> count + 1) + 1;
    sharedptr -> choosing[pid] = FALSE;
    for (j = 0; j < sharedptr -> count + 1; j++){
        while(sharedptr -> choosing[j] == TRUE);
        while(sharedptr -> ticket[j] != FALSE && ((sharedptr -> ticket[j] <= sharedptr -> ticket[pid])     && j < pid));
    }
}

void releaseMutex(short pid){
    // set the mutex back to initial state so that somebody else can claim it
    sharedptr -> ticket[pid] = 0;
}

int max(int array[], int maxIndex){
    int max = array[0];
    int i;

    if(maxIndex == 0)
        return max;
    for(i = 1; i < maxIndex; i++){
        if(array[i] > max)
            max = array[i];
    }
    return max;
}

struct Queue *initQueue(){
    struct Queue *q = (struct Queue*)malloc(sizeof(struct Queue));
    q -> size = 0;
    q -> head = NULL;
    q -> tail = NULL;
    return q;
}

struct Queue *push(char ch, struct Queue *q){
struct Link *temp = (struct Link*)malloc(sizeof(struct Link));

if(q != NULL) {
    temp -> value = ch;
    temp -> next = q -> head;
    temp -> prev = NULL;
    if(q -> size == 0){
        q -> head = temp;
        q -> tail = temp;
    } else {
        q -> head -> prev = temp;
        q -> head = temp;
    }
        q -> size++;
    } else {
        printf("The queue is NULL.\n");
        exit(0);
    }
    return q;
}

struct Queue *pop(struct Queue *q){
    if(q != NULL) {
        if(q -> size == 0){
            printf("nothing to pop.\n");
        } else if(q -> size == 1){
            q -> head = NULL;
            q -> tail = NULL;
        } else {
            q -> tail -> prev -> next = NULL;
            q -> tail = q -> tail -> prev;
        }
        q -> size--;
    } else {
        printf("The queue is NULL.\n");
        exit(0);
    }

    return q;
}

char getBuffer(struct Queue *q) {
    if(q -> tail != NULL)
        return (char)q -> tail -> value;
    else {
        printf("Buffer is empty.\n");
        exit(1);
    }
}

void printQueue(struct Queue *q){

    struct Link *temp;
    if(q != NULL){
        if(q -> size > 0){
            temp = q -> head;
            while(temp -> next != NULL){
                printf("%c->", temp -> value);
                temp = temp -> next;
            }
            printf("%c\n", temp -> value);
        } else
            printf("Queue is NULL.\n");
    } else
        printf("Queue is empty.\n");
}

制作人c
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <errno.h>

#include "common.h"

#define FALSE 0
#define TRUE 1

#define MYPID 1

int main (int argc, char *argv[]){

    // initialize the shared memory, load in the initial array's, spawn the worker
    // processes.
    key_t   key;
    struct shared *memptr;
    int shmid;
    int c;
    int pid;
    char ch;


    /*   Shared memory init     */
    key = ftok(".", 'S');
    if((shmid = shmget(key, MEMSIZE, IPC_CREAT|0666)) == -1 ){
        if( (shmid = shmget(key, MEMSIZE, 0)) == -1){
            printf("Error allocating shared memory. \n");
            exit(1);
        }
    }

    // now map the region..
    if((int)(memptr = (struct shared *) shmat(shmid, 0, 0)) == -1){
        printf("Couldn't map the memory into our process space.\n");
        exit(1);
    }

    mutexInit(memptr);

    //_______________________________
    memptr -> count = 0; //temp code to assume and test with one producer only
    //_______________________________


    if(memptr -> count == 0)
        firstInit(memptr);
    else if (memptr -> count >= MAXCOUNT) {
        printf("Exceed maximum limit for number of producers");
        exit(0);
    } else {
        memptr -> count++;
    }

    pid = memptr -> count;

    printf("pid:%d", pid);
    printf("eof: %d", memptr -> endOfFile);

    while(memptr -> endOfFile == FALSE) {
        if((memptr -> in - memptr -> out) < BUFFSIZE){
            ch = fgetc(memptr -> file); //read one character from the text file

            if(ch == EOF){
                memptr -> endOfFile = TRUE;
                break;
            }

            getMutex(pid); //wait for mutex
            memptr -> buffer = push(ch, memptr -> buffer); //write the character into the buffer
            printQueue(memptr -> buffer);
            releaseMutex(pid);

            //______________________________________
            printf("%c", getBuffer(memptr -> buffer));  //a test to see if producer
                                                        //can access buffer ->tail
            //______________________________________

            //increment the in variable
            memptr -> in++;
        }
    }

    memptr -> count--;

    return 0;
}

消费者c:
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <errno.h>

#include "common.h"

#define FALSE 0
#define TRUE 1

#define MYPID 0

int main (int argc, char *argv[]){
    // initialize the shared memory, load in the initial array's, spawn the worker
    // processes.
    key_t   key;
    struct shared *memptr;
    int shmid;
    char ch;


    /*   Shared memory init     */
    key = ftok(".", 'S');
    if((shmid = shmget(key, MEMSIZE, IPC_CREAT|0666)) == -1 ){
        if( (shmid = shmget(key, MEMSIZE, 0)) == -1){
            printf("Error allocating shared memory. \n");
            exit(1);
        }
    }

    // now map the region..
    if((int)(memptr = (struct shared *) shmat(shmid, 0, 0)) == -1){
        printf("Couldn't map the memory into our process space.\n");
        exit(1);
    }

    mutexInit(memptr);

    do{
        if(memptr -> out < memptr -> in){ //compare the in and out to see if the buffer is empty
            if(memptr -> buffer == NULL)
                printf("Buffer is empty.\n");
            else if (memptr -> buffer -> tail == NULL){
                printf("Tail is NULL. Something went wrong.\n");
                exit(1);
            }

            ch = getBuffer(memptr -> buffer); //read a character from the buffer and print
            //wait for mutex
            getMutex(MYPID);
            printf("%c", memptr -> buffer -> tail -> value);
            memptr -> buffer = pop(memptr -> buffer);
            releaseMutex(MYPID);
            //release mutex

            memptr -> out++;
        }
    } while((memptr -> endOfFile == FALSE) || (memptr -> count != 0));

    return 0;
}

最佳答案

这里有一个问题:您使用参数shmat0(shmaddr)调用NULL。这告诉系统在它想要的任何地址映射共享内存段。无法保证映射的地址在两个进程中都是相同的!如果两个进程中使用不同的基址,则一个(生产者)编写的指针对另一个(消费者)无效。

10-07 15:47