实验三进程通信.docx
- 文档编号:26314598
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:18
- 大小:112.64KB
实验三进程通信.docx
《实验三进程通信.docx》由会员分享,可在线阅读,更多相关《实验三进程通信.docx(18页珍藏版)》请在冰豆网上搜索。
实验三进程通信
实验三进程通信
一.实验学时与类型
学时:
2,课外学时:
自定
实验类型:
设计性实验
二.实验目的
了解Linux的软中断、管道、消息队列、共享存储区等进程间通信方式。
三.实验容
1.软中断通信机制
(1)请编写一个程序:
循环输出“howareyou?
〞,在按下Ctrl+C后中断显示,输出“Byebye!
〞后退出程序。
#include
#include
intk=1;
voidint_func(intsig)//软中断处理函数
{k=0;}
Intmain()
{signal(SIGINT,int_func);//预置软中断信号处理函数
While(k==1)
Printf(“howareyou?
\n〞);
Printf(“byebye!
〞);
}
(2)使用信号机制实现父子进程同步,父进程先输出A,然后子进程输出B。
#include
#include
intk=1;
voidfunc(intsig){k=0;}
main()
{intpid;
pid=fork();
if(pid>0)
{printf(“A\n〞);
kill(pid,12);
}
elseif(pid==0)
{signal(12,func);
while(k==1)
sleep
(1);
printf(“B\n〞);
}
}
2.管道机制
(1)父子进程通过管道传送一串字符。
要求:
子进程随机从键盘输入一串字符,通过管道发给父进程,父进程从管道中将消息读出并显示出来。
#include
#include
main()
{intpid,fd[2];
charoutpipe[50],inpipe[50];
pipe(fd);
pid=fork();
if(pid==0)
{
Printf(“pleaseinputsomemessage:
\n〞);
Fgets(inpipe,sizeof(inpipe),stdin);
write(fd[1],inpipe,50);
}
elseif(pid>0);
{wait(0);
Printf(“fathergetthismessage:
\n〞);
read(fd[0],outpipe,50);
printf(“%s\n〞,outpipe);
}
}
〔2〕父子进程通过管道互相发送字符串。
要求:
子进程向父进程通过管道发送〞Iamchild.〞,父进程回送〞Iamfather.〞,父子进程将各自收到的字符串显示在屏幕上。
#inlcude
#include
#include
main()
{intpid,fd[2];
charstr1[50],str2[50];
pipe(fd);
pid=fork();
if(pid==0)
{strcpy(str1,〞I’mchild〞);
write(fd[1],str1,strlen(str1));
Sleep
(1);
read(fd[0],str2,50);
printf(“Childreceived:
%s\n〞,str2);
}
elseif(pid>0)
{read(fd[0],str1,50);
printf(“Parentreceived:
%s\n〞,str1);
strcpy(str2,〞I’mfather.〞);
write(fd[1],str2,strlen(str2));
}
}
3.消息队列机制
(1)父进程及其子进程通过一条消息队列互相传送数据。
#include
#include
#include
#include
intmsgqid,qid;
structmsg
{longmtype;
charmtext[256];
}pmsg;
cancelqueue()
{msgctl(msgqid,IPC_RMID,0);
exit(0);}
main()
{intpid;
Pid=fork();
If(pid>0)
{msgqid=msgget(75,0777);
printf(“msgid:
%d\n〞,msgqid);
pmsg.mtype=1;
*((int*)pmsg.mtext)=getpid();
msgsnd(msgqid,&pmsg,sizeof(int),0);
msgrcv(msgqid,&pmsg,256,getpid(),0);
printf(“A:
receivemsgfrom%d\n",*((int*)pmsg.mtext));
}
Elseif(pid==0)
{signal(2,cancelqueue);
msgqid=msgget(75,0777|IPC_CREAT);
while
(1)
{msgrcv(msgqid,&pmsg,256,1,0);
qid=*(int*)pmsg.mtext;
printf(“B:
receivemsgfrom%d\n〞,qid);
pmsg.mtype=qid;
*((int*)pmsg.mtext)=getpid();
msgsnd(msgqid,&pmsg,sizeof(int),0);
}
}
}
(2)非父子进程之间实通过一条消息队列互相传递数据。
A进程:
#include
#include
#include
#include
structmsg
{longmtype;
charmtext[256];
}pmsg;
main()
{intmsgqid,pid;
msgqid=msgget(75,0777);
printf(“msgid:
%d\n〞,msgqid);
pmsg.mtype=1;
*((int*)pmsg.mtext)=getpid();
msgsnd(msgqid,&pmsg,sizeof(int),0);
msgrcv(msgqid,&pmsg,256,getpid(),0);
printf(“A:
receivemsgfrom%d\n〞,*((int*)pmsg.mtext));
}
B进程:
#include
#include
#include
#include
intmsgqid,pid;
structmsg
{longmtype;
charmtext[256];
}pmsg;
cancelqueue()
{msgctl(msgqid,IPC_RMID,0);
exit(0);}
main()
{signal(2,cancelqueue);
msgqid=msgget(75,0777|IPC_CREAT);
while
(1)
{msgrcv(msgqid,&pmsg,256,1,0);
pid=*(int*)pmsg.mtext;
printf(“B:
receivemsgfrom%d\n〞,pid);
pmsg.mtype=pid;
*((int*)pmsg.mtext)=getpid();
msgsnd(msgqid,&pmsg,sizeof(int),0);
}
}
4.共享存机制
(1)编程实现基于共享存的进程间通信。
要求:
进程A通过共享存将自己的进程号传递给进程B。
A:
#include
#include
main()
{intshmid;
int*va;
shmid=shmget(22,sizeof(*va),0666|IPC_CREAT);
va=(int*)shmat(shmid,0,0);
*va=getpid();
printf(“getA’spid:
%d\n〞,*va);
shmdt(va);
}
B:
#include
#include
main()
{intshmid;
int*va;
shmid=shmget(22,sizeof(*va),0666|IPC_CREAT);
va=(int*)shmat(shmid,0,0);
printf(“A’spidis:
%d\n〞,*va);
shmdt(va);
shmctl(shmid,IPC_RMID,0);
}
(2)假设要通过共享存实现进程A与进程B互送进程号,可怎样编程实现?
A:
#include
#include
main()
{intshmid;
int*va;
shmid=shmget(22,sizeof(*va),0666|IPC_CREAT);
va=(int*)shmat(shmid,0,0);
*va=getpid();
printf(“getA’spid:
%d\n〞,*va);
Sleep
(2);
printf(“B’spidis:
%d\n〞,*va)
shmdt(va)
}
B:
#include
#include
main()
{intshmid;
int*va;
shmid=shmget(22,sizeof(*va),0666|IPC_CREAT);
va=(int*)shmat(shmid,0,0);
printf(“A’spidis:
%s\n〞,*va);
*va=getpid();
printf(“getB’spid:
%d\n〞,*va);
shmdt(va);
shmctl(shmid,IPC_RMID,0);
}
5.SOCKET进程通信〔选做〕
编程实现基于SOCKET的进程间通信,通过网络实现进程之间数据通信。
要求:
分别编写效劳器端和客户端方程序,运行于不同终端,二者可相互进展通信。
Server:
#include
#include
#include
#include
#include
#include
#include
intmain()
{
intserver_sockfd=-1;
intclient_sockfd=-1;
intclient_len=0;
structsockaddr_inserver_addr;
structsockaddr_inclient_addr;
//创立流套接字
server_sockfd=socket(AF_INET,SOCK_STREAM,0);
//设置效劳器接收的连接地址和监听的端口
server_addr.sin_family=AF_INET;//指定网络套接字
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//承受所有IP地址的连接
server_addr.sin_port=htons(9736);//绑定到9736端口
//绑定〔命名〕套接字
bind(server_sockfd,(structsockaddr*)&server_addr,sizeof(server_addr));
//创立套接字队列,监听套接字
listen(server_sockfd,5);
//忽略子进程停顿或退出信号
signal(SIGCHLD,SIG_IGN);
while
(1)
{
charch='\0';
client_len=sizeof(client_addr);
printf("Serverwaiting\n");//承受连接,创立新的套接字
client_sockfd=accept(server_sockfd,(structsockaddr*)&client_addr,&client_len);
if(fork()==0)
{
//子进程中,读取客户端发过来的信息,处理信息,再发送给客户端
read(client_sockfd,&ch,1);
sleep(5);
ch++;
write(client_sockfd,&ch,1);
close(client_sockfd);
exit(0);
}
else
{
//父进程中,关闭套接字
close(client_sockfd);
}
}
}
Client:
#include
#include
#include
#include
#include
#include
#include
intmain()
{
intsockfd=-1;
intlen=0;
structsockaddr_inaddress;
intresult;
charch='A';//创立流套接字
sockfd=socket(AF_INET,SOCK_STREAM,0);//设置要连接的效劳器的信息
address.sin_family=AF_INET;//使用网络套接字
address.sin_addr.s_addr=inet_addr("127.0.0.1");//效劳器地址
address.sin_port=htons(9736);//效劳器所监听的端口
len=sizeof(address);
//连接到效劳器
result=connect(sockfd,(structsockaddr*)&address,len);
if(result==-1)
{
perror("ops:
client\n");
exit
(1);
}
//发送请求给效劳器
write(sockfd,&ch,1);
//从效劳器获取数据
read(sockfd,&ch,1);
printf("charformserver=%c\n",ch);
close(sockfd);
exit(0);
}
四.思考与总结
(1)请比照以下程序与实验1
(1)在按下Ctrl+C之后的运行现象。
intk=1;
intmain(void)
{
while(k==1)
printf(“howareyou?
\n〞);
printf(“Byebye!
\n〞);
}
(2)针对实验2
(2),你能否通过信号量机制来实现?
假设能,请给出相应代码及运行结果分析。
#include
#include
#include
#include
#include
#include
unionsemun
{
intval;
structsemid_ds*buf;
unsignedshort*array;
}arg;
//生成信号量
intsem_creat(key_tkey)
{
intsemid;
semid=semget(key,1,IPC_CREAT|0666);
if(-1==semid)
{
printf("createsemaphoreerror\n");
exit(-1);
}
sem.val=0;
semctl(semid,0,SETVAL,arg);
returnsemid;
}
//删除信号量
voiddel_sem(intsemid)
{
arg.val=0;
semctl(semid,0,IPC_RMID,arg);
}
//p
intp(intsemid)
{
structsembufsops={0,-1,IPC_NOWAIT};
return(semop(semid,&sops,1));
}
//v
intv(intsemid)
{
structsembufsops={0,+1,IPC_NOWAIT};
return(semop(semid,&sops,1));
}
intmain()
{
key_tkey;
intpid,semid;
charstr1[50];
structsemid_dsbuf;
key=ftok("/",0);
semid=sem_creat(key);
if(pid>0)
{
P(semid);
Va=(char*)shmat(shmid,0,0);
Printf(“fathergetthismessage:
%s\n〞,va);
Strcpy(va,〞I’mfather!
〞);
Printf(“fathergetthismessage:
%s\n〞,str1);
Shmat(va);
V(semid);
}
Elseif(pid==0)
{
P(semid);
Va=(char*)shmat(shmid,0,0);
Strcpy(va,〞I’mchild!
〞〕;
Sleep
(2);
Printf(“childgetthismessage:
%s\n〞,va);
Shmat(va);
V(semid);
}
Shmctl(shmid,IPC_RMID,0);
del_sem(semid);
return0;
//gcc-oshmshm.c-g
}
(3)请结合本次实验,说明信号、管道、消息队列、共享存这几种进程间通信机制的适用场合及其优缺点。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 进程 通信
![提示](https://static.bdocx.com/images/bang_tan.gif)