2014-11-01 2 views
1

대기열 안팎으로 문자를 밀어 넣고 팝핑하여 생산자 소비자 문제를 프로그래밍하려고합니다. main.c 파일에는 producer.c와 consumer.c의 두 가지 파일이 있습니다. 둘 다 처음에 초기화 된 공유 메모리 공간을 가지고 있습니다. 생산자가 먼저 실행되고 공유 포인터의 변수를 초기화합니다 (static struct shared * sharedptr). 그 중 하나는 큐 (struct Queue * buffer)입니다.C - 공유 메모리를 처리 할 때 분할 오류가 발생했습니다.

프로듀서는 파일에서 문자를 읽고 한 번에 하나씩 큐를 넣고 소비자는 한 번에 하나씩 큐에서 읽거나, 인쇄하고, 문자를 꺼내 (팝)합니다.

문제는 다음과 같습니다. 생산자는 대기열 포인터 (memptr -> buffer)를 가져 와서 문자를 넣는 데 문제가 없습니다. 그러나 생산자는 대기열에 대한 포인터가 같아야하지만 대기열에 액세스 할 수 없습니다. 나는이 테스트 때

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); 
} 

나는 그것이 가정 나는이 if 문에서 테스트 할 때 버퍼가 NULL 인 경우 검사 할 때

그것은 제대로 인쇄 그것이 꼬리에 접근하고있을 때 일어난다. 꼬리가 NULL인지 평가하지도 않습니다. 방금 segfault를 보냈습니다. common.c에있는 모든 큐 관련 함수를 테스트 할 때 (아래에 제공됨), 프로듀서가 잘 실행되는 경우에는 발생하지 않았습니다.

포인터가 어떻게됩니까? 소비자는 (struct shared *) memptr의 다른 변수에 액세스 할 수 있지만 buffer-> tail은 액세스 할 수 없습니다. 그것은 나에게 어떤 의미가 없습니다.

내 Mac에서 프로그램을 컴파일 :

common.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); 

common.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"); 
} 

cc -c common.c 

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

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

여기 내가 가진 모든 코드입니다

producer.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; 
} 

consumer.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; 
} 

답변

1

는 여기에 한 가지 문제 : 당신은 있었던 파라미터 shmaddr 제로 (NULL)와 shmat를 호출하고 있습니다. 이것은 공유 메모리 세그먼트를 원하는 주소로 매핑하도록 시스템에 지시합니다. 두 프로세스에서 매핑 된 주소가 동일하다는 보장은 없습니다! 두 프로세스에서 서로 다른 기본 주소가 사용되면 하나 (작성자)가 작성한 포인터는 다른 (소비자)에게 유효하지 않습니다.

1

공유 메모리에 포인터 (struct Queue *bufferFILE *file)를 사용할 수 없습니다. Producer에 malloc()이 있으면 해당 프로세스에서만 해당 포인터의 데이터에 액세스 할 수 있습니다.

당신이 할 수있는 일은 *buffer*file에 대한 두 개의 추가 공유 메모리를 만들고 *memptr 안에 첨부하십시오. 그러나 일반적으로 포인터는 실제로 공유 메모리에서 사용하기위한 것이 아닙니다.

자세한 내용은이 질문에서 답변을 확인할 수 있습니다 : Pointers inside shared memory segment.

관련 문제