在C中使用信号量的有界缓冲区

时间:2016-10-30 19:53:02

标签: c multithreading semaphore

以下是我到目前为止的代码。该程序使用两个进程(生产者和使用者)共享的缓冲区。生产者从文件中读取字符并将它们放在缓冲区中。消费者从缓冲区中读取每个项目并将字符打印到屏幕上。我运行该程序,但它似乎已经遇到无限循环或阻止它终止的东西。什么都没有打印到屏幕上,我没有看到导致这种情况的原因。

#define _REENTRANT
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>
typedef int bufferItem;
#define BUFFER_SIZE 5

pthread_mutex_t mutex;
sem_t full;
sem_t empty;
int counter;
bufferItem buffer[BUFFER_SIZE];

//--------------------------------------------
// insert function used by producer thread
//--------------------------------------------
void insertItem(bufferItem item) {

  if (counter < BUFFER_SIZE) {
    buffer[counter] = item;
    counter++;
    return;
  } else
    printf("Error inserting item");
}

//--------------------------------------------
// remove function used by consumer thread
//---------------------------------------------
bufferItem removeItem() {

  if (counter > 0) {
    bufferItem itemRem;
    itemRem = buffer[counter - 1];
    counter--;
    return itemRem;
  } else
    return -1;
}

//---------------------------------------------
// producer prototype
//---------------------------------------------
void *thread1() {

  char newChar;
  FILE *fp;
  fp = fopen("mytest.dat", "r");

  while (1 && fscanf(fp, "%c", &newChar) != EOF) {

    // produce an item
    bufferItem currentChar = newChar;

    sem_wait(&empty);
    pthread_mutex_lock(&mutex);

    insertItem(currentChar);

    pthread_mutex_unlock(&mutex);
    sem_post(&full);
  }
  close(fp);
}

//---------------------------------------------
// consumer thread prototype
//----------------------------------------------
void *thread2() {
  while (1) {
    sem_wait(&full);
    pthread_mutex_lock(&mutex);

    bufferItem itemPrint = removeItem();

    pthread_mutex_unlock(&mutex);
    sem_post(&empty);
    printf("%d", itemPrint);

    sleep(1);
  }
}

//-------------------------------------------
// MAIN
//-------------------------------------------
main() {

  int r = 0;
  int i;
  sem_t sem1;
  int shmid;              /* shared memory ID */
  pthread_t tid1[1];      /* process id for thread 1 */
  pthread_t tid2[1];      /* process id for thread 2 */
  pthread_attr_t attr[1]; /* attribute pointer array */
  pthread_mutex_init(&mutex, NULL);
  sem_init(&full, 0, 0);
  sem_init(&empty, 0, BUFFER_SIZE);
  counter = 0;

  fflush(stdout);
  /* Required to schedule thread independently.*/
  pthread_attr_init(&attr[0]);
  pthread_attr_setscope(&attr[0], PTHREAD_SCOPE_SYSTEM);
  /* end to schedule thread independently */

  /* Create the threads */
  pthread_create(&tid1[0], &attr[0], &thread1, NULL);
  pthread_create(&tid2[0], &attr[0], &thread2, NULL);

  /* Wait for the threads to finish */
  pthread_join(tid1[0], NULL);
  pthread_join(tid2[0], NULL);

  printf("------------------------------------------------\n");
  printf("\t\t  End of simulation\n");

  exit(0);
}

2 个答案:

答案 0 :(得分:1)

现在我不能说为什么它不起作用,我无法尝试你的代码因为我在Windows上。但首先你应该尝试做每一个可能的错误检查。检查你的fopen,pthread_create,pthread_join等......

(我认为它不会改变任何东西,但是让你的程序更安全是一种很好的做法)

我将打开我的linux,所以稍等一下:)

编辑:哈哈!它实际上是在开始工作! 你有两个解决方案:

printf("%d\n", itemPrint);

printf("%d", itemPrint);
fflush(stdout);

printf方法在打印前缓冲。它仅在以下情况下打印:

  • 遇到'\ n'
  • printf缓冲区已满
  • stdout已刷新

如果你这样做,你也会遇到printf的问题: ./your_program | cat -e(允许你看到不可打印的字符),我真的不知道为什么。

答案 1 :(得分:1)

  1. 它应该是来自stdio的“fclose”而不是“close”系统调用,它使文件描述符不是文件指针。

  2. 生产者运行良好,只是输出全部被缓冲,因为你没有在格式字符串中包含换行符。刷新它或添加换行符,你会看到输出

  3. 消费者无法终止---在生产者返回完整信号量后它将无限期地阻止

  4. 出于好奇,这是什么平台和编译器? GCC不会在没有修改的情况下编译它。