一、实验目的
学习使用Linux的系统调用和pthread线程库编写程序,进一步理解、掌握操作系统进程、线程概念,利用信号量解决进程同步与互斥。
二、实验内容
1. Fibonacci序列是0, 1, 1, 2, 3, 5, 8, .... ,通常它可以表示为:
f ib0 = 0
f ib1 = 1
f ibn = f ibn−1 + f ibn−2
编写一个C程序,使用系统调用fork()创建两个子进程P1和P2。他们的任务如下:
1) 子进程P1打印自己的pid,然后使用exec(族)系统调用显示当前目录下文件和子目录的详细信息。
2) 子进程P2中生成Fibonacci序列,序列的个数在程序命令行中作为参数传入,例如,参数为7,则子进程P2生成的Fibonacci序列为0、1、2、3、5、8、13。通过某种进程通信机制(共享内存、管道、消息等IPC机制),子进程P2把生成的Fibonacci序列发送给父进程,并由父进程输出(打印)Fibonacci序列。在父子进程通信的过程中必须实现同步,以使在子进程完成生成序列之前,父进程不会输出Fibonacci序列。使用wait()系统调用可以实现各进程的同步。执行必要的错误检查以保证不会接受命令行参数传递来的负值。
2. 编写程序实现生产者-消费者问题。使用linux的Pthread线程库,创建2个生产者线程和2个消费者线程。生产者线程计算当前的时间,把时间、第几次计算时间的序号(循环次数)和线程ID作为一个消息,把消息放入缓冲区,消费者线程从缓冲区读出一个消息并显示消息。缓冲区大小为5个,每个生产者线程生产10个消息,每个消费者线程消费10个消息,即生产和消费分别为20次。
生产者及消费者线程之间需要实现同步和互斥,Pthread线程库的信号量机制可以完成这一任务。
三、源代码
(1)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
//定义管道的最大值
#define MAXLINE 80
//�波那次函数
int fibonaci(int n)
{
if(n==0) return 0;
else if(n==1) return 1;
else
return fibonaci(n-2)+fibonaci(n-1);
}
//main主函数
void main(int argc,char* argv[])
{
pid_t pid1; //子进程p1的id
pid_t pid2; //子进程p2的id
int fd[2];
int k=0;
int line[MAXLINE];
for(k;k<MAXLINE;k++)
line[k]=-1;
pipe(fd);
pid1=fork();
if(pid1<0)
{
printf("error fork\n");
exit(1);
}
else if(pid1==0) //子进程1
{
//显示当前目录的文件信息
printf("The current content is as follows:\n");
execlp("/bin/ls","ls",NULL);
}
else //父进程
{
//继续产生子进程2
pid2=fork();
if(pid2<0)
{
printf("error fork\n");
exit(0);
}
else if(pid2==0) //子进程2
{
int number=atoi(argv[1]); //通过命令行参数得到斐波那契数组的参数
if(number<0)number=-number; //error correct
//调用fibonaci函数
while(number>=1)
{
line[number]=fibonaci(number-1);
number=number-1;
}
//把数组写入到管道
close(fd[0]);
write(fd[1],line,MAXLINE);
}
else
{
wait(NULL); //wait for pid1
wait(NULL); //wait for pid2
close(fd[1]);
read(fd[0],line,MAXLINE);
printf("The fibonaci array is as follows:\n ");
int m=1;
while(line[m]!=-1)
{
printf("%d ",line[m]);
m=m+1;
}
printf("\n");
}
}
close(fd[0]);
close(fd[1]);
//return 0;
}
(2)
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <time.h>
#include <malloc.h>
#include <stdlib.h>
sem_t sem1,sem2; //信号量
pthread_mutex_t mutex1,mutex2; //互斥量
//定义缓冲区结构
struct container_buffer
{
//线程号
pid_t id;
//读取序号
int number;
//时间
time_t mytime;
}*p,*r,*w; //定义3个结构指针
/*函数write1,2,用于生产者计算当前的时间,把时间、第几次计算时间的序号
(循环次数)和线程ID作为一个消息,把消息放入缓冲区
*/
void *write1(void *arg)
{
//生产10个消息
int i=1;
for(i;i<=10;i++)
{
//if(w==p+5)w=p;
sem_wait(&sem1); //缓冲减1
pthread_mutex_lock(&mutex1); //加锁
w->number=i;
w->id=pthread_self();
time(&(w->mytime));
w++;
sem_post(&sem2); //可读加1
pthread_mutex_unlock(&mutex1); //解锁
sleep(1+(int)(5*rand()/(RAND_MAX+1.0))); //随机睡觉x秒,1<=x<=5
}
}
void *write2(void *arg)
{
//生产10个消息
int j=1;
for(j;j<=10;j++)
{
//if(w==p+5)w=p;
sem_wait(&sem1);
pthread_mutex_lock(&mutex1);
w->number=j;
w->id=pthread_self();
time(&(w->mytime));
w++;
sem_post(&sem2);
pthread_mutex_unlock(&mutex1);
sleep(1+(int)(5*rand()/(RAND_MAX+1.0)));
}
}
/*函数read1,2,用于消费者从缓冲区读出一个消息并显示消息
*/
void *read1(void *arg)
{
//消费10个消息
int k=1;
for(k;k<=10;k++)
{
//if(r==p+5)r=p;
sem_wait(&sem2); //可读减1
pthread_mutex_lock(&mutex2); //加锁
printf("消费者1第%d次读取消息---, id=%u, time is: %s\n",r->number,(unsigned)(r->id),ctime(&(r->mytime)));
r++;
sem_post(&sem1); //缓冲加1
pthread_mutex_unlock(&mutex2); //解锁
sleep(1+(int)(5*rand()/(RAND_MAX+1.0))); ////随机睡觉x秒,1<=x<=5
}
}
void *read2(void *arg)
{
//消费10个消息
int l=1;
for(l;l<=10;l++)
{
//if(r==p+5)r=p;
sem_wait(&sem2);
pthread_mutex_lock(&mutex2);
printf("消费者2第%d次读取消息---, id=%u, time is: %s\n",r->number,(unsigned)(r->id),ctime(&(r->mytime)));
r++;
sem_post(&sem1);
pthread_mutex_unlock(&mutex2);
sleep(1+(int)(5*rand()/(RAND_MAX+1.0)));
}
}
void main()
{
pthread_t pro1,pro2;//生产者
pthread_t cum1,cum2;//消费者
sem_init(&sem1,0,5); //创建初始值为5的信号量
sem_init(&sem2,0,0); //创建初始值为0的信号量
pthread_mutex_init(&mutex1,NULL);
pthread_mutex_init(&mutex2,NULL);
p=(struct container_buffer*)malloc(20*sizeof(struct container_buffer)); //申请20个结构内存空间
r=p;
w=p;
//创建2个生产者线程和2个消费者线程
pthread_create(&pro1,NULL,write1,NULL);
pthread_create(&pro2,NULL,write2,NULL);
pthread_create(&cum1,NULL,read1,NULL);
pthread_create(&cum2,NULL,read2,NULL);
//互斥量销毁
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
//线程挂起
pthread_join(pro1,NULL);
pthread_join(pro2,NULL);
pthread_join(cum1,NULL);
pthread_join(cum2,NULL);
//释放内存
free(p);
return;
}
本文出自 “晓伟的sky” 博客,请务必保留此出处http://zjuedward.blog.51cto.com/1445231/456050