C 缓冲区有界的生产者/消费者
有没有人能检查一下我的密码,告诉我我是否在正确的轨道上。。我好像有点迷路了。。如果你看到我的错误,请告诉我 我试图做的是使用我自己的信号量以及GCD来解决有界缓冲区问题 提前谢谢 语义C 缓冲区有界的生产者/消费者,c,semaphore,grand-central-dispatch,consumer,C,Semaphore,Grand Central Dispatch,Consumer,有没有人能检查一下我的密码,告诉我我是否在正确的轨道上。。我好像有点迷路了。。如果你看到我的错误,请告诉我 我试图做的是使用我自己的信号量以及GCD来解决有界缓冲区问题 提前谢谢 语义 void procure( Semaphore *semaphore ) { pthread_mutex_lock(semaphore->mutex1); while(semaphore->value <= 0) pthread
void procure( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
while(semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
void init ( Semaphore *semaphore ){
semaphore->value = 1;
pthread_mutex_t myMutex;
semaphore->mutex1 = &myMutex;
pthread_mutex_init( semaphore->mutex1, NULL);
}
void destroy ( Semaphore *semaphore ) {
pthread_mutex_destroy(semaphore->mutex1);
}
void获取(信号量*信号量){
pthread_mutex_lock(信号量->mutex1);
while(信号量->值条件,信号量->mutex1);
信号量->值--;
pthread_mutex_unlock(信号量->mutex1);
}
无效清空(信号量*信号量){
pthread_mutex_lock(信号量->mutex1);
信号量->值++;
pthread_cond_信号(&信号量->条件);
pthread_mutex_unlock(信号量->mutex1);
}
void init(信号量*信号量){
信号量->值=1;
pthread_mutex_t myMutex;
信号量->互斥1=&myMutex;
pthread_mutex_init(信号量->mutex1,NULL);
}
无效销毁(信号量*信号量){
pthread_mutex_destroy(信号量->mutex1);
}
和main.c
struct variables {
Semaphore *sem;
};
struct variables vars;
void constructer (int *buffer, int *in, int *out) {
init(vars.sem);
}
void deconstructer () {
destroy(vars.sem);
}
int rand_num_gen() {
uint_fast16_t buffer;
int file;
int *rand;
file = open("/dev/random", O_RDONLY);
while( 1 ) {
read(file, &buffer, sizeof(buffer));
printf("16 bit number: %hu\n", buffer );
*rand = (int) buffer;
close(file);
break;
}
return *rand;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(vars.sem);
value = buffer[*out];
vacate(vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int *in, *out, *buffer;
constructer(buffer, in, out);
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer,
^{
int i;
do
{
put_buffer( buffer, in, out );
dispatch_async(consumer,
^{
get_buffer( buffer, in, out );
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
}
while (i < RUN_LENGTH);
});
dispatch_main();
deconstructer();
exit (0);
}
struct变量{
信号量*sem;
};
结构变量变量;
void构造函数(int*buffer、int*in、int*out){
init(vars.sem);
}
空洞解构器(){
破坏(vars.sem);
}
国际货币基金组织{
uint_fast16_t缓冲器;
int文件;
国际*兰特;
文件=打开(“/dev/random”,仅限O_RDONLY);
而(1){
读取(文件和缓冲区,大小(缓冲区));
printf(“16位数字:%hu\n”,缓冲区);
*rand=(int)缓冲区;
关闭(文件);
打破
}
返回*兰特;
}
无效输出缓冲区(int*buffer,int*in,int*out){
缓冲区[*in]=rand_num_gen();//生产
采购(vars.sem);//在这里等
*in=(*in+1)%BUF_尺寸;
腾空(vars.sem);
}
void get_buffer(int*buffer,int*in,int*out){
int值;
采购(vars.sem);
值=缓冲区[*out];
腾空(vars.sem);
*out=(*out+1)%BUF_尺寸;
}
内部主(空){
int*in、*out、*buffer;
构造器(缓冲区、输入、输出);
调度队列\t生产者、消费者;
producer=dispatch\u queue\u create(“put\u buffer”,NULL);
消费者=调度队列创建(“获取缓冲区”,NULL);
调度异步(生产者,
^{
int i;
做
{
输入缓冲区(缓冲区、输入、输出);
调度异步(用户,
^{
获取缓冲区(缓冲区、输入、输出);
如果(i==运行长度)退出(退出成功);
});
}
而(i<行程长度);
});
调度_main();
解构器();
出口(0);
}
您的代码有一个bug。在init
函数中,将局部变量的地址分配给semaphore->mutex1
,当函数返回该地址时,该地址将无效。以后您仍然使用此地址,因此这会导致未定义的行为
必须直接在信号量中为互斥体分配内存(无指针),或通过malloc
分配内存
更新:
你的程序有如此多的bug,因此你应该选择一个更容易的主题来学习关于内存管理的基本概念,如何分配、使用和引用缓冲区,如何进行正确的错误处理,等等。下面是一个稍微编辑过的代码版本。它仍然不起作用,但可能有一些你应该遵循的想法
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void procure(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
while (semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
struct variables {
mutex_t sem_mutex;
Semaphore sem;
};
struct variables vars;
void constructor(int *buffer, int *in, int *out) {
vars.sem.value = 1;
vars.sem.mutex1 = &vars.sem_mutex;
pthread_mutex_init(vars.sem.mutex1, NULL);
}
void deconstructor() {
pthread_mutex_destroy(&semaphore->mutex1);
}
int rand_num_gen() {
const char *randomfile = "/dev/random";
unsigned char buffer[2]; // Changed: always treat files as byte sequences.
FILE *f = fopen(randomfile, "rb");
// Changed: using stdio instead of raw POSIX file access,
// since the API is much simpler; you don't have to care
// about interrupting signals or partial reads.
if (f == NULL) { // Added: error handling
fprintf(stderr, "E: cannot open %s\n", randomfile);
exit(EXIT_FAILURE);
}
if (fread(buffer, 1, 2, f) != 2) { // Added: error handling
fprintf(stderr, "E: cannot read from %s\n", randomfile);
exit(EXIT_FAILURE);
}
fclose(f);
int number = (buffer[0] << CHAR_BIT) | buffer[1];
// Changed: be independent of the endianness of the system.
// This doesn't matter for random number generators but is
// still an important coding style.
printf("DEBUG: random number: %x\n", (unsigned int) number);
return number;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(&vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(&vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(&vars.sem);
value = buffer[*out];
vacate(&vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int inindex = 0, outindex = 0;
int buffer[BUF_SIZE];
constructor(buffer, &inindex, &outindex);
// Changed: provided an actual buffer and actual variables
// for the indices into the buffer.
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer, ^{
int i;
do {
put_buffer(buffer, &inindex, &outindex);
dispatch_async(consumer, ^{
get_buffer(buffer, &inindex, &outindex);
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
} while (i < RUN_LENGTH);
});
dispatch_main();
deconstructor();
exit (0);
}
#包括
#包括
#包括
#包括
无效获取(信号量*信号量){
pthread_mutex_lock(信号量->mutex1);
while(信号量->值条件,信号量->mutex1);
信号量->值--;
pthread_mutex_unlock(信号量->mutex1);
}
无效清空(信号量*信号量){
pthread_mutex_lock(信号量->mutex1);
信号量->值++;
pthread_cond_信号(&信号量->条件);
pthread_mutex_unlock(信号量->mutex1);
}
结构变量{
互斥锁;
信号量扫描电镜;
};
结构变量变量;
无效构造函数(int*buffer、int*in、int*out){
vars.sem.value=1;
vars.sem.mutex1=&vars.sem_mutex;
pthread_mutex_init(vars.sem.mutex1,NULL);
}
空解构器(){
pthread_mutex_destroy(&semaphore->mutex1);
}
国际货币基金组织{
const char*randomfile=“/dev/random”;
无符号字符缓冲区[2];//已更改:始终将文件视为字节序列。
文件*f=fopen(随机文件,“rb”);
//更改:使用stdio而不是原始POSIX文件访问,
//因为API要简单得多,所以您不必在意
//关于中断信号或部分读取。
如果(f==NULL){//添加:错误处理
fprintf(stderr,“E:无法打开%s\n”,随机文件);
退出(退出失败);
}
if(fread(buffer,1,2,f)!=2){//添加:错误处理
fprintf(stderr,“E:无法从%s读取\n”,随机文件);
退出(退出失败);
}
fclose(f);
int number=(buffer[0]我在这里接收到错误的访问buffer[*in]=rand_num_gen();
如何修复它?那是哪种语言?C没有lambda(^
)运算符。我没有调用构造函数和解构器函数。我修复了它,但看不到任何区别。您从未初始化in
变量。我想您希望将in
和out
声明为int-in=0,out=0;并将它们的地址传递给您的函数。