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

The bounded buffer using semaphores in C

以下是我目前的代码。该程序使用两个进程(生产者和消费者)之间共享的缓冲区。生产者从文件中读取字符并将它们放入缓冲区。消费者从缓冲区中读取每个项目并将字符打印到屏幕上。我 运行 程序,但它似乎 运行 进入无限循环或阻止它终止的东西。屏幕上没有打印任何内容,我也不知道是什么原因造成的。

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

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

(我不认为它会改变任何东西,但让你的程序更安全是个好习惯)

我会打开我的linux,请稍等:)

编辑:哈哈!它实际上从一开始就在工作! 您有 2 个解决方案:

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

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

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

  • 遇到'\n'
  • printf 缓冲区已满
  • 标准输出被刷新

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

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

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

  3. 消费者无法终止---它会在生产者 returns 完全信号量

  4. 之后无限期地阻塞

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