在 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
(让你看到不可打印的字符),我真的不知道为什么。
它应该是来自 stdio 的 "fclose" 而不是 "close" 系统调用,它接受文件描述符而不是文件指针。
生产者运行正常,只是输出全部被缓冲,因为您没有在格式字符串中包含换行符。刷新它或添加一个换行符,你会看到输出
消费者无法终止---它会在生产者 returns 完全信号量
之后无限期地阻塞
出于好奇,这是什么平台和编译器? GCC 不会在不修改的情况下编译它。
以下是我目前的代码。该程序使用两个进程(生产者和消费者)之间共享的缓冲区。生产者从文件中读取字符并将它们放入缓冲区。消费者从缓冲区中读取每个项目并将字符打印到屏幕上。我 运行 程序,但它似乎 运行 进入无限循环或阻止它终止的东西。屏幕上没有打印任何内容,我也不知道是什么原因造成的。
#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
(让你看到不可打印的字符),我真的不知道为什么。
它应该是来自 stdio 的 "fclose" 而不是 "close" 系统调用,它接受文件描述符而不是文件指针。
生产者运行正常,只是输出全部被缓冲,因为您没有在格式字符串中包含换行符。刷新它或添加一个换行符,你会看到输出
消费者无法终止---它会在生产者 returns 完全信号量
之后无限期地阻塞
出于好奇,这是什么平台和编译器? GCC 不会在不修改的情况下编译它。