第3次实验14281147王飞.docx
- 文档编号:6075104
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:19
- 大小:339.21KB
第3次实验14281147王飞.docx
《第3次实验14281147王飞.docx》由会员分享,可在线阅读,更多相关《第3次实验14281147王飞.docx(19页珍藏版)》请在冰豆网上搜索。
第3次实验14281147王飞
实验三进程通信
1.实验目的
●了解Linux消息传递机制。
●掌握使用命名管道FIFO进行进程间的通信。
●掌握使用消息队列message进行进程间的通信。
●掌握Linux线程控制基本操作。
●掌握使用互斥锁和条件变量实现线程同步问题。
2.实验内容
1)创建两个进程。
要求两个进程分别作为“生产者”和“消费者”,由生产者生产1-100数字,通过命名管道传递给消费者进程,并由消费者屏幕输出。
通过实验验证命名管道同步方式(生产者发送时阻塞或者非阻塞,消费者阻塞或者非阻塞)
实验中,发送方通过一个循环的将1-100这100个数字送入命名管道,如下图所示
接收方通过一个循环不断接收管道中的数据直到接收不到数据为止,如下图所示
整体的程序如附fifoCP.c所示,Linux环境下,控制台运行,结果如下
发送方部分截图
接收方部分截图
在发送方的while循环中添加一个sleep(100)语句,如下图所示
再次执行程序,得到结果如下
程序运行到以上部分,会停滞100s,然后执行,在这100s内,程序没有任何输出,说明消费者是阻塞式的。
删除上边修改的代码,然后在消费者端连接管道之前,添加一个sleep(100)语句,然后,执行程序,得到的结果是,在sleep(100)执行结束,消费者连接上管道之后,生产者才开始发送数据,之前一直处于阻塞状态,因此生产者端也是阻塞式的。
2)创建两个进程,通过消息传递机制通信。
进程A接受用户的键盘输入,并通过消息通信传递给进程B。
进程B根据收到的命令如下处理,如果是“exit”则退出,否则将收到的命令串原样屏幕输出。
为了方便展示,程序分成了两个部分,如附send.c和receive.c所示
执行send.c程序,并输入hello,myfriend
启动receive.c程序,结果如下
Send端输入exit,结果如下(左侧receive端,右侧send端)
3)采用线程的互斥锁和条件变量,实现最多允许10个读者同时读的读者写者线程同步问题。
基本思路如下:
整个程序需要两把锁,一把锁是mutex,表示当前是读者还是写者对内容有操作的权力,还有一个是rmutex表示读者中哪一个对内容有操作的权力。
最多允许10个读者同时进行读操作,当已经有十个读者在读的时候,新的读者申请读的时候,利用条件变量count_nonfull使正在申请读的读者暂时放弃,直到正在读的读者数少于10人为止。
具体代码如附录signalRW.c所示,总共创建了12个线程,一个写者进程,11个读者进程,写者对变量text修改50次,每个读者对变量text读5次,上机运行程序,部分结果截图如下图所示
4)采用java管程实现生产者消费者线程并通过实验验证正确性。
思路分析:
生产者消费者各是一个线程,生产者生产出来的产品放入缓存队列等待消费,消费者从缓存队列中取出产品消费。
在缓存队列已满的情况下,生产者将不能继续放入产品,直到有产品被消费,缓存队列出现空位,然后通知生产者可以继续生产产品。
在缓存队列中没有产品的情况下,消费者不能进行消费,直到缓存队列有产品放入,之后通知消费者可以继续进行消费。
程序如附java管程所示,缓冲区大小为6,总共要生产20个产品,消费20个产品,执行程序,得到的结果如下
附:
fifoCP.c
#include
#include
#include
#include
#include
#include
#include
#defineFIFO_SERVER"FIFO4"
intmain(){
intp1,p2;
intfd;
intreal_num;
charbuf[8];
while((p1=fork())==-1);
if(p1==0){
printf("producerwascreatedwithpid=%d\n",getpid());
if((mkfifo(FIFO_SERVER,O_CREAT|O_EXCL|0666)<0)&&(errno!
=EEXIST)){
printf("cannotcreatefifoserver\n");
}
else{
fd=open(FIFO_SERVER,O_WRONLY);
intk=0;
while(k++<100){
sprintf(buf,"%-4d",k);
real_num=write(fd,buf,4);
if(real_num==-1){
printf("writetofifoerror;trylater\n");
}
else
printf("produce%d\n",k);
}
printf("数据发送完成\n");
}
exit
(1);
}
else{
printf("consumerwascreatedwithpid=%d\n",getpid());
fd=open(FIFO_SERVER,O_RDONLY);
while
(1){
real_num=read(fd,buf,4);
if(real_num==0)
{
break;
}
elseif(real_num==-1)
{
printf("readerror\n");
}
else
printf("consume%s\n",buf);
}
printf("数据接收完成\n");
wait(0);
}
return0;
}
Send.c
#include
#include
#include
#include
#include
#include
#definemax100
structhaha{
longmtype;
chardata[max];
};
intmain(){
charmsg[100];
key_tkey;
if((key=ftok("/tmp",'g'))<0){//这里文件夹必须存在,有t属性并且上级目录也要有t属性
printf("Gettingkeyerror!
\n");
return-1;
}
intmgsid;
if((mgsid=msgget(key,IPC_CREAT|0666))==-1){//key值随便写一个数也能用
printf("mgsqueuecreateerror\n");
return-1;
}
printf("Sendingthemessage......\n");
structhahahehe;
hehe.mtype=3366;
intk=0;
while
(1){
printf("输入要发送的消息:
");
gets(msg);
strcpy(hehe.data,msg);
if(msgsnd(mgsid,&hehe,sizeof(hehe.data),0)<0){//此处注意长度
printf("Sendingerror\n");
exit
(1);
}
else{
printf("Sendingcomplete!
\n");
if(strcmp(msg,"exit")==0){
printf("结束通信\n");
break;
}
}
}
return0;
}
Receive.c
#include
#include
#include
#include
#include
#include
#definemax100
structhaha{
longmtype;
chardata[max];
};
intmain(){
intpid;
charmsg[100];
key_tkey;
if((key=ftok("/tmp",'g'))<0){//这里文件夹必须存在,有t属性并且上级目录也要有t属性
printf("Gettingkeyerror!
\n");
return-1;
}
intmgsid;
if((mgsid=msgget(key,IPC_CREAT|0666))==-1){//key值随便写一个数也能用
printf("mgsqueuecreateerror\n");
return-1;
}
printf("Receivingthemessage......\n");
structhahagaga;
while
(1){
intr=msgrcv(mgsid,&gaga,max,3366,0);
if(r<0){
printf("Receivingerror\n");
exit
(1);
}
else{
printf("Receivingcomplete!
\n");
printf("Thesendersays:
%s\n",gaga.data);
if(strcmp(gaga.data,"exit")==0)
break;
}
}
printf("结束通信\n");
return0;
}
SignalRW.c
#include
#include
#include
inttext;
intnum=0;
pthread_mutex_tmutex,rmutex;
pthread_cond_tcount_nonfull;
void*writer(void*arg)
{
intk=50;
while(k-->0){
pthread_mutex_lock(&mutex);
text=k;
printf("写入%d\n",text);
pthread_mutex_unlock(&mutex);
}
returnNULL;
}
void*reader(void*arg)
{
intk=5;
while(k-->0){
if(num==0)
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&rmutex);
while(num==10){
pthread_cond_wait(&count_nonfull,&rmutex);
};
num++;
printf("%d加入,读者数:
%d\n",pthread_self(),num);
pthread_mutex_unlock(&rmutex);
printf("%d:
读出%d\n",pthread_self(),text);
sleep
(1);
pthread_mutex_lock(&rmutex);
num--;
if(num==9)
pthread_cond_signal(&count_nonfull);
printf("%d退出,读者数:
%d\n",pthread_self(),num);
if(num==0)
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&rmutex);
}
returnNULL;
}
intmain()
{
pthread_ttid1,tid2,tid3,tid4,tid5,tid6,tid7,tid8,tid9,tid10,tid11,tid12;
pthread_mutex_init(&mutex,NULL);
pthread_mutex_init(&rmutex,NULL);
pthread_create(&tid1,NULL,writer,NULL);
pthread_create(&tid2,NULL,reader,NULL);
pthread_create(&tid3,NULL,reader,NULL);
pthread_create(&tid4,NULL,reader,NULL);
pthread_create(&tid5,NULL,reader,NULL);
pthread_create(&tid6,NULL,reader,NULL);
pthread_create(&tid7,NULL,reader,NULL);
pthread_create(&tid8,NULL,reader,NULL);
pthread_create(&tid9,NULL,reader,NULL);
pthread_create(&tid10,NULL,reader,NULL);
pthread_create(&tid11,NULL,reader,NULL);
pthread_create(&tid12,NULL,reader,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
pthread_join(tid4,NULL);
pthread_join(tid5,NULL);
pthread_join(tid6,NULL);
pthread_join(tid7,NULL);
pthread_join(tid8,NULL);
pthread_join(tid9,NULL);
pthread_join(tid10,NULL);
pthread_join(tid11,NULL);
pthread_join(tid12,NULL);
pthread_mutex_destroy(&rmutex);
pthread_mutex_destroy(&mutex);
return0;
}
Java管程
classConsumerimplementsRunnable//模仿消费者进程
{
synQueuess;
Consumer(synQueuess)
{
this.ss=ss;
}
publicvoidrun()
{
for(inti=0;i<20;i++)//设定消费者总共要消费20个产品
{
productw=ss.pop();
System.out.println("产品"+w.id+"被消费");
}
}
}
classProducerimplementsRunnable//模仿生产者进程
{
synQueuess;
Producer(synQueuess)
{
this.ss=ss;
}
publicvoidrun()
{
for(inti=0;i<20;i++)//设定生产者总共要生产20个产品
{
productwt=newproduct(i);
ss.push(wt);
System.out.println("产品"+i+"被生产出来了");
}
}
}
publicclassConsAndPros{
publicstaticvoidmain(String[]args)
{
synQueuess=newsynQueue();//开辟一个缓冲队列,用于存储生产出来的的产品
newThread(newProducer(ss)).start();//创建并启动生产者线程
newThread(newConsumer(ss)).start();//创建并启动消费者线程
}
}
classproduct//产品类,用于模拟生产出来的产品
{
intid;//产品编号
product(intid)
{
this.id=id;
}
}
classsynQueue//缓存队列
{
inttop=0;//下一个等待被消费的产品的存放位置
intbottom=0;//下一个即将被消费的产品的位置
product[]arrWT=newproduct[6];//该数组用于存储产品,数组大小为6
publicsynchronizedvoidpush(productwt)//将生产出来的产品放入缓冲队列中
{
while((top+1)%6==bottom)//当缓冲队列已满时,暂停产品的生产,等待缓冲区出现空位
{
try{
this.wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
this.notify();
arrWT[top]=wt;
top=(top+1)%6;//指向下一个产品存放位置
}
publicsynchronizedproductpop()
{
while(bottom==top)//缓冲区产品数量为0时,消费者等待,直到有产品被加入到缓冲区中
{
try{
this.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
this.notify();
intn=bottom;
bottom=(bottom+1)%6;//指向下一个被消费的产品
returnarrWT[n];//返回被消费的产品
}
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 14281147 王飞