看论文看不下去了,正好有个师妹来问操作系统的实验。
大二没怎么认真做实验上机的我,竟然在大三的时候认真做了一遍!(难以置信)
实验内容
编写一个有关生产者和消费者的程序:每个生产者每次生产一个产品存入仓库,每个消费者每次从仓库中取出一个产品进行消费,仓库大小有限,每次只能有一个生产者或消费者访问仓库。要求:采用信号量机制。
实验原理
生产者消费者原理
生产者消费者模型如上图所示,一群生产者在生产消息,并将此消息提供给消费者去消费。它们中间设了具有M个缓存区的缓冲池,生产者每次可将生产的消息放入一个缓存区内,消费者每次可将一个缓存区内的消息拿出来消费。但这个过程有两个条件:任何一方操作一个缓冲区时不能有其它同时对该缓冲区进行操作;只有当缓冲区还有空余,生产者才能生产,只有当缓冲区至少有一个产品,消费者才能从中取出来消费。这里两个条件分别对应了互斥和同步。在此次实验中,有若干个生产者和若干个消费者。有多少个生产者,就有多少个生产者进程;有多少个消费者,就有多少个对应的消费者进程。生产者和消费者的个数作为命令行参数传入到程序中。即实现互斥又实现同步可以用信号量机制. 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。缓冲池作为临界资源,信号量的初始值为1,生产者与消费者进行生产或费时首先得获得临界资源。缓冲池空闲区域的个数,商品的个数也用信号量来定义,初始值分别为值为M和0。生产者要放产品到缓冲区时,除了要获得缓冲区这个临界资源,还要获得空闲的缓冲区区域;消费者要在缓冲区消费商品,除了要获得缓冲区这个临界资源,还要获得商品这个信号量。
Linux操作系统的代码实现
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#define N 4 // 消费者或者生产者的数目
#define M 20 // 缓冲数目
int in = 0; // 生产者放置产品的位置
int out = 0; // 消费者取产品的位置
char buff[M]; // 缓冲区
int producter_id = 0; //生产者id
int consumer_id = 0; //消费者id
pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲区。
/* 打印缓冲情况 */
void print()
{
int i;
pthread_mutex_lock(&mutex);
for(i = 0; i < M; i++)
{
printf("%c ", buff[i]);
//usleep(100);
}
puts("");
pthread_mutex_unlock(&mutex);
}
/* 生产者方法 */
void *producter()
{
int id = ++producter_id;
while(1)
{
// 用sleep的数量可以调节生产和消费的速度
sleep(2);
char data;
data=rand()%26+65;
in = in % M;
printf("生产者进程%d在%2d位置产生数据%c: ", id,in,data);
buff[in] = data;
print();
++in;
}
}
/* 消费者方法 */
void *consumer()
{
char data;
int id = ++consumer_id;
while(1)
{
// 用sleep的数量可以调节生产和消费的速度
sleep(1);
out = out % M;
data=buff[out];
printf("消费者进程%d在%2d位置消费数据%c: ",id, out,data);
buff[out] = '*';
print();
++out;
}
}
int main()
{
pthread_mutex_init(&mutex,NULL);
pthread_t p[N];
pthread_t c[N];
int i;
int ret[N];
for(i=0; i<M; i++)
buff[i]='*'; //'*'表示空,初始化缓冲区
srand((int)time(NULL));
// 创建N个生产者线程
for (i = 0; i < N; i++)
{
ret[i] = pthread_create(&p[i], NULL,(void*)producter, (void *)(&i));
if(ret[i] != 0)
{
printf("producter %d creation failed \n", i);
exit(1);
}
}
//创建N个消费者线程
for(i = 0; i < N; i++)
{
ret[i] = pthread_create(&c[i], NULL, (void*)consumer, NULL);
if(ret[i] != 0)
{
printf("consumer %d creation failed\n", i);
exit(1);
}
}
//销毁程
for(i = 0; i < N; i++)
{
pthread_join(p[i],NULL);
pthread_join(c[i],NULL);
}
pthread_mutex_destroy(&mutex);
exit(0);
}
gcc zfl.c -g -lpthread -o zfl.out
./zfl.out
注意事项
问题:出现“undefined reference to ‘pthread_create’”,所有关于线程的函数都会有此错误,导致无法编译通过。
问题的原因:pthread不是Linux下的默认的库,也就是在链接的时候,无法找到phread库中哥函数的入口地址,于是链接会失败。
解决:在gcc编译的时候,附加要加 -lpthread参数即可解决。
eg:gcc rwlock.c -g -lpthread
引用转自 Linux下undefined reference to ‘pthread_create’问题解决
引用中的内容转自 Linux下undefined reference to ‘pthread_create’问题解决