实验五进程间通信.docx
《实验五进程间通信.docx》由会员分享,可在线阅读,更多相关《实验五进程间通信.docx(27页珍藏版)》请在冰豆网上搜索。
实验五进程间通信
实验五进程间通信
UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。
本实验的目的是了解和熟悉LINUX支持的信号机制、管道机制、消息队列通信机制及共享存储区机制。
5.1信号机制实验
(一)
【实验目的】
1.了解什么是信号。
2.熟悉LINUX系统中进程之间软中断通信的基本原理。
【实验原理】
利用signal来实现发送信号和接受信号的原理
【实验内容】
1.编写一段程序,使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止:
Childprocess1iskilledbyparent!
Childprocess2iskilledbyparent!
父进程等待两个子进程终止后,输出以下信息后终止:
Parentprocessiskilled!
<参考程序>
#include
#include
#include
intwait_mark;
voidwaiting(),stop();
voidmain()
{intp1,p2;
signal(SIGINT,stop);
while((p1=fork())==-1);
if(p1>0)/*在父进程中*/
{
while((p2=fork())==-1);
If(p2>0)/*在父进程中*/
{
wait_mark=1;
waiting(0);
kill(p1,10);
kill(p2,12);
wait();
wait();
printf(“parentprocessiskilled!
\n”);
exit(0);
}
else/*在子进程2中*/
{
wait_mark=1;
signal(12,stop);
waiting();
lockf(1,1,0);
printf(“childprocess2iskilledbyparent!
\n”);
lockf(1,0,0);
exit(0);
}
}
else/*在子进程1中*/
{
wait_mark=1;
signal(10,stop);
waiting();
lockf(1,1,0);
printf(“childprocess1iskilledbyparent!
\n”);
lockf(1,0,0);
exit(0);
}
}
voidwaiting()
{
while(wait_mark!
=0);
}
voidstop()
{
wait_mark=0;
}
实验要求:
运行程序并分析结果。
如果把signal(SIGINT,stop)放在
号和
号位置,结果会怎样并分析原因。
该程序段前面部分用了两个wait(0),为什么?
该程序段中每个进程退出时都用了语句exit(0),为什么?
5.2信号机制实验
(二)
【实验目的】
学习signal的函数的使用
【实验原理】
利用signal的函数的机制来实习我们发送截获信号的功能
【实验内容】
修改上面的程序,增加语句signal(SIGINT,SIG_IGN)和语句signal(SIGQUIT,SIG_IGN),再观察程序执行时屏幕上出现的现象,并分析其原因。
<参考程序>
#include
#include
#include
intpid1,pid2;
intEndFlag=0;
pf1=0;
pf2=0;
voidIntDelete()
{
kill(pid1,10);
kill(pid2,12);
EndFlag=1;
}
voidInt1()
{
printf(“childprocess1iskilledbyparent!
\n”);
exit(0);
}
voidInt2()
{
printf(“childprocess2iskilledbyparent!
\n”);
exit(0);
}
main()
{
intexitcode;
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
while((pid1=fork())==-1);
if(pid1==0)
{
signal(SIGUSR1,Int1);
signal(SIGINT,SIG_IGN);
pause();
exit(0);
}
else
{
while((pid2=fork())==-1);
if(pid2==0)
{
signal(SIGUSR2,Int2);
signal(SIGINT,SIG_IGN);
pause();
exit(0);
}
else
{
signal(SIGINT,IntDelete);
waitpid(-1,&exitcode,0);/*等待任何子进程中断或结束*/
printf(“parentprocessiskilled\n”);
exit(0);
}
}
}
实验要求:
运行程序并分析结果。
司机售票员问题(选做题)
编程用fork()创建一个子进程代表售票员,司机在父进程中,再用系统调用signal()让父进程(司机)捕捉来自子进程(售票员)发出的中断信号,让子进程(售票员)捕捉来自(司机)发出的中断信号,以实现进程间的同步运行。
5.3管道通信实验
(一)
【实验目的】
1、了解什么是管道
2、熟悉UNIX/LINUX支持的管道通信方式
【实验内容】
编写程序实现进程的管道通信。
用系统调用pipe()建立一管道,二个子进程P1和P2分别向管道各写一句话:
Child1issendingamessage!
Child2issendingamessage!
父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
参考程序
#include
#include
#include
intpid1,pid2;
main()
{
intfd[2];
charoutpipe[100],inpipe[100];
pipe(fd); /*创建一个管道*/
while((pid1=fork())==-1);
if(pid1==0)
{
lockf(fd[1],1,0);
sprintf(outpipe,"child1processissendingmessage!
");
/*把串放入数组outpipe中*/
write(fd[1],outpipe,50); /*向管道写长为50字节的串*/
sleep(5); /*自我阻塞5秒*/
lockf(fd[1],0,0);
exit(0);
}
else
{
while((pid2=fork())==-1);
if(pid2==0)
{ lockf(fd[1],1,0); /*互斥*/
sprintf(outpipe,"child2processissendingmessage!
");
write(fd[1],outpipe,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{ wait(0); /*同步*/
read(fd[0],inpipe,50); /*从管道中读长为50字节的串*/
printf("%s/n",inpipe);
wait(0);
read(fd[0],inpipe,50);
printf("%s/n",inpipe);
exit(0);
}
}
}
五、运行结果
延迟5秒后显示
child1processissendingmessage!
再延迟5秒
child2processissendingmessage!
5.4管道通信实验
(二)
【实验目的】
1、掌握有名管道的创建和读写方式
2、熟悉UNIX/LINUX支持的有名管道通信方式
【实验内容】
1.创建有名管道
2.本进程执行循环等待数据被写入到管道中并读有名管道
3.打开有名管道并写数据到名管道
参考代码:
//read_fifo.c
#include
#include
#include
#include
#include
#include
#include
#defineBUFFER_SIZE1024
intmain(intargc,char**argv)
{
intfd;
if(argc<2)
{
fprintf(stdout,"Usage:
%s\n",argv[0]);
exit
(1);
}
//intopen(constchar*path,intoflag,...);
if((fd=open(argv[1],O_RDONLY))<0)
{
fprintf(stderr,"openfifo%sforreadingfailed:
%s\n",argv[1],strerror(errno));
exit
(1);
}
fprintf(stdout,"openfifo%sforreadingsuccessed.\n",argv[0]);
charbuffer[BUFFER_SIZE];
ssize_tn;
while
(1)
{
again:
//ssize_tread(intfd,void*buf,size_tcount);
if((n=read(fd,buffer,BUFFER_SIZE))<0)
{
if(errno==EINTR)
{
gotoagain;
}
else
{
fprintf(stderr,"readfailedon%s:
%s\n",argv[1],strerror(errno));
exit
(1);
}
}
elseif(n==0)
{
fprintf(stderr,"peerclosedfifo.\n");
break;
}
else
{
buffer[n]='\0';
fprintf(stdout,"read%dbytesfromfifo:
%s\n",n,buffer);
}
}
return0;
}
//write_fifo.c
#include
#include
#include
#include
#include
#include
#include
#include
#defineBUFFER_SIZE1024
voidsignal_handler(ints);
intmain(intargc,char**argv)
{
intfd;
if(argc<2)
{
fprintf(stdout,"Usage:
%s\n",argv[0]);
exit
(1);
}
signal(SIGPIPE,signal_handler);
//intopen(constchar*path,intoflag,...);
if((fd=open(argv[1],O_WRONLY))<0)
{
fprintf(stderr,"openfifo%sforwrittingfailed:
%s\n",argv[1],strerror(errno));
exit
(1);
}
fprintf(stdout,"openfifo%sforwrittingsuccessed.\n",argv[0]);
charbuffer[BUFFER_SIZE];
ssize_tn;
//char*fgets(char*s,intsize,FILE*stream);
while(fgets(buffer,BUFFER_SIZE,stdin))
{
again:
//ssize_twrite(intfd,constvoid*buf,size_tcount);
if((n=write(fd,buffer,strlen(buffer)))<0)
{
if(errno==EINTR)
{
gotoagain;
}
else
{
fprintf(stderr,"write()failedonfifo:
%s\n",strerror(errno));
//FIXME:
break;
}
}
}
return0;
}
voidsignal_handler(ints)
{
fprintf(stdout,"Caughtsignal%d\n",s);
}
//create_fifo.c
#include
#include
#include
#include
#include
intmain(intargc,char**argv)
{
if(argc<2)
{
fprintf(stdout,"Usage:
%s\n",argv[0]);
exit
(1);
}
//intmkfifo(constchar*path,mode_tmode);
if(mkfifo(argv[1],0644)<0)
{
fprintf(stderr,"mkfifo()failed:
%s\n",strerror(errno));
exit
(1);
}
return0;
}
5.5共享内存通信实验
【实验目的】
1、掌握共享内存的创建和读写方式
2、熟悉UNIX/LINUX支持的共享内存通信方式
【实验内容】
1.创建共享内存
2.写入到共享内存
3.读数据从共享内存
代码参考:
//write.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMAPPED_FILENAME"/tmp/test.mmap.1"
intmain(intargc,char**argv)
{
intfd;
if(argc<2)
{
fprintf(stdout,"Usage:
%s\n",argv[0]);
exit
(1);
}
//XXX:
step1,openfile,getafd
//intopen(constchar*pathname,intflags,mode_tmode);
if((fd=open(argv[1],O_RDWR|O_CREAT|O_EXCL,0644))<0)
{
if(errno==EEXIST)
{
fprintf(stderr,"Fatalerror:
Thetargetmappedfileexisted,exit.\n");
}
else
{
fprintf(stderr,"Error:
openfilefailed:
(errno=%d)%s\n",errno,strerror(errno));
}
exit
(1);
}
off_toffset;
offset=1024;
//XXX:
step2,createaholefile
//off_tlseek(intfildes,off_toffset,intwhence);
if(lseek(fd,offset,SEEK_SET)==(off_t)-1)
{
fprintf(stderr,"lseek()failed:
%s\n",strerror(errno));
//FIXME:
unlinkthefile
close(fd);
exit
(1);
}
ssize_tn;
//ssize_twrite(intfd,constvoid*buf,size_tcount);
if((n=write(fd,"",1))<0)
{
fprintf(stderr,"write()failed:
%s\n",strerror(errno));
exit
(1);
}
/*
*Onsuccess,mmapreturnsapointertothemappedarea.Onerror,thevalueMAP_FAILED(thatis,(void*)-1)isreturned,anderrnoissetappropriately.Onsuccess,munmapreturns0,onfailure-1,anderrnoisset(probablytoEINVAL).
*/
/*
PROT_EXECPagesmaybeexecuted.
PROT_READPagesmayberead.
PROT_WRITEPagesmaybewritten.
PROT_NONEPagesmaynotbeaccessed.
*/
void*p;
//XXX:
step3,mmap(),getapointer
//void*mmap(void*start,size_tlength,intprot,intflags,intfd,off_toffset);
if((p=mmap(NULL,1024,PROT_WRITE,MAP_SHARED,fd,0))==MAP_FAILED)
{
fprintf(stderr,"mmap()failed:
%s\n",strerror(errno));
close(fd);
exit
(1);
}
close(fd);
fprintf(stdout,"mappedfiletomemory,size=%d\n",1024);
//XXX:
step4,read/writeonsharedmemory
char*banner="helloworld.";
//void*memcpy(void*dest,constvoid*src,size_tn);
memcpy(p+256,banner,strlen(banner));
//XXX:
step5,munmap();
//intmunmap(void*start,size_tlength);
pause();
//close(fd);
return0;
}
//read.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMAPPED_FILENAME"/tmp/test.mmap.1"
#defineBUFFER_SIZE1024
intmain(intargc,char**argv)
{
intfd;
if(argc<2)
{
fprintf(stdout,"Usage:
%s\n",argv[0]);
exit
(1);
}
//XXX:
step1,openfile,getafd
//intopen(constchar*pathname,intflags,mode_tmode);
if((fd=open(argv[1],O_RDWR))<0)
{
fprintf(stderr,"Error:
openfile