lab5 Linux进程及并发程序设计 2Word下载.docx
- 文档编号:8567958
- 上传时间:2023-05-11
- 格式:DOCX
- 页数:19
- 大小:391.84KB
lab5 Linux进程及并发程序设计 2Word下载.docx
《lab5 Linux进程及并发程序设计 2Word下载.docx》由会员分享,可在线阅读,更多相关《lab5 Linux进程及并发程序设计 2Word下载.docx(19页珍藏版)》请在冰点文库上搜索。
while((p=fork())==-1);
//创建子进程直到成功为止
if(p==0)//返回值=0表示子进程返回
{
printf("
TheChildisrunning\n"
);
}
else//返回值>
0表示父进程返回
{
printf("
TheParentisrunning\n"
}
2.存放在Linux中的bingfa.c文档中:
3.使用gcc命令对bingfa.c进行编译:
4.多次使用./a.out执行该命令,查看结果:
输出:
TheParentisrunning
TheChildisrunning
或者
5.运行结果分析:
通过实验结果可看出,这是一个并发程序,子进程和父进程在不同的情况下先后出现的顺序可能不同,具有随机性。
(2)编写一个并发程序(子先父后)
#include<
stdlib.h>
if(p==0)//返回值=0表示子进程返回
exit(0);
//在子进程结束时调用exit(0),使子进程自我终止,并发终止信号给其父进程;
else//返回值>
wait(0);
//父进程等待子进程终止,再执行下方程序
2.存放在Linux中的Childfirst.c文档中:
3.使用gcc命令对Childfirst.c进行编译:
从运行结果可看出此程序实现了父等子的功能,始终是子进程先执行。
从代码上看,是用wait(0)和exit(0)实现的,在子进程(p=0)运行后使用exit(0)终止进程,在父进程(p>
0)内容程序执行前加上wait(0),使父进程接收到子进程结束的信号后才执行内容程序,从而实现了后执行父进程的效果。
(3)编写一个管道应用程序(父提供给子字符串)
sys/types.h>
unistd.h>
//printf函数的头文件
stdlib.h>
//exit函数的头文件
#defineLINESIZE1024
intmain(void)
{
intn,fd[2];
pid_tpid;
charline[LINESIZE];
if(pipe(fd)<
0)//调用pipe()函数建立管道;
{
pipeerror"
//建立不成功则返回“pipeerror"
,并退出;
exit
(1);
}
if((pid=fork())<
0)//创建进程,创建不成功则返回"
forkerror"
并退出
elseif(pid>
0)//父进程的fork()返回
close(fd[0]);
//关闭管道读指针;
I'
mfather~\n"
//声明它是父进程
write(fd[1],"
putthestringintothepipe.\n"
29);
//将"
写入管道
close(fd[1]);
//关闭管道写指针;
else//父进程的fork()返回
//关闭管道写指针;
mson~\n"
//声明它是子进程
n=read(fd[0],line,LINESIZE);
//读取输入的信息,存放到字符串line中
string:
%s\n"
line);
//输出”string:
“和输入的信息
exit(0);
//退出程序;
2.存放在Linux中的father_to_son.c文档中:
3.使用gcc命令对father_to_son.c进行编译:
4.使用./a.out执行该命令,查看结果:
mfather~
mson~
putthestringintothepipe.
5.运行结果及程序思路分析:
通过pipe()函数建立管道;
用close(fd[0])关闭父进程管道读指针,利用write(fd[1],"
字符串内容"
字符串长度);
写入字符串,最后关闭管道写指针;
用close(fd[1])关闭子进程管道写指针,利用read(fd[0],"
读取管道中字符串,最后关闭管道读指针;
实现父进程向子进程传递字符串的功能;
(四)调试运行3.10并发程序并进行分析
1.程序源代码如下:
【father1.c】:
【child1.c】:
【pipeline.c】:
2.执行程序:
输入:
cc-ochild1child1.c
cc-ofather1father1.c
ccpipeline.c
./a.out
_Parentisusingpipewrite.
child,child.
3.代码与运行结果分析:
main()
staticcharstring[]="
Parentisusingpipewrite."
;
intlen;
len=sizeof(string);
write(1,string,len);
写入字符串len中
printf("
parent,parent,parent\n\n\n"
//输出显示是parent进程在执行
exit(0);
charoutput[30];
read(0,output,30);
//读output中的内容
_%s\nchild,child.\n"
output);
//输出output中的内容加上child,child声明是子进程
return(0);
#defineSTD_INPUT0//定义标准输入设备描述符
#defineSTD_OUTPUT1//定义标准输出设备描述符
intfd[2];
staticcharprocess1[]="
father1"
process2[]="
child1"
pipe(fd);
//定义管道,返回文件描述符fd[0],fd[1]
pipeline(process1,process2);
//调用自定义函数pipeline();
exit
(1);
//程序结束
pipeline(process1,process2)
char*process1,*process2;
inti;
while((i=fork())==-1);
//创建进程,创建失败则反复创建,直到创建成功
if(i)//父进程的fork()返回
{
close(fd[0]);
//关闭管道读端
close(STD_OUTPUT);
//关闭标准输出描述符1(原来是写到显示器的指针)
dup(fd[1]);
//指定标准输出描述符1为管道写指针,语句后调用printf函数,那么内容并不会输出到显示器,而是写入了管道中。
close(fd[1]);
//关闭原始管道写指针
execl(process1,process1,0);
//用程序father1覆盖当前程序
——fatherfailed.\n"
//execl()执行失败时才执行这一行
else
//关闭管道写端
close(STD_INPUT);
//关闭标准输出描述符0
dup(fd[0]);
//指定标准输入描述符0为管道读指针,语句后调用scanf函数,那么不会从键盘读取内容,而是从管道中读取。
//关闭原始管道读指针
execl(process2,process2,0);
//用程序child1覆盖当前程序
——childfailed.\n"
exit
(2);
4.运行结果分析:
输出结果为:
_Parentisusingpipewrite.child,child.
Pipeline.c中调用了dup(fd[1]);
指定标准输出描述符1为管道写指针,语句后调用printf函数,那么内容并不会输出到显示器,而是写入了管道中。
而从结果可看出,父进程通过管道传给了子进程“Parentisusingpipewrite.”(从而才会前面有_,后面有child,child),同时pipeline.c中使用execl(process1,process1,0);
用父进程覆盖原进程,如果没有发挥dup(fd[1])的作用(将printf中的内容“parent,parent,parent”写入管道中),也应在界面中打印出来。
所以我进行了以下几个测试:
(1)测试printf是否因write而没有输入到管道中(注释掉write行)
输出了:
_parent,parent,parent(3行)child,child
出现了“_”和“child,child”,说明dup(fd[1])的作用实现了,prinf的内容的确输入到管道中。
说明是write导致的。
(2)测试是否由于write和printf的顺序导致无法写入(调换位置)
仍然无法输出,说明不是顺序问题;
(3)测试是否发送接收字符串的问题(是否结束符\0的问题)
修改发送字符串长度:
后面出现的pa说明的确是字符串长度的问题;
接下来修改接收字符串长度:
成功实现prinf内容输入管道并从子进程同时读取出用write和prinf写入的内容。
分析字符串长度为何会导致这种问题:
通过上网了解到,用sizeof计算变量的空间大小时,它会把数组末尾的\0符号也计算进去,在你往管道内输入后,读取时遇见'
\0'
符号就会认为字符串结束,就不再读取prinf中的内容,而prinf中的内容,不管与write命令的顺序如何,都只会把内容输入到管道中write的部分。
从而,整个程序利用execl();
实现father1和child1在同一程序中实现,father1通过管道通信传给了child1字符串;
同时利用close(fd[])的方式实现进程的互斥。
使用dup(fd[])实现将外部输入输出设备的信息置于管道中,进行读取。
(五)编写一个管道应用程序(父接收键盘输入传给子进程)
signal.h>
stdarg.h>
fgets(line,sizeof(line),stdin);
//获得键盘输入,存放在字符串line中
if((pid=fork())<
0)
//关闭管道读指针
//声明它是父进程
write(fd[1],line,sizeof(line));
//将line中的内容(即键盘输入)写入管道中
//关闭管道写指针
else//子进程的fork()返回
//声明它是子进程
//退出程序;
2.存放在Linux中的key_father.c文档中:
3.使用gcc命令对key_father.c进行编译:
I’mYidan!
!
yeyeye
Yeyeye
yes!
通过fgets(字符数组名,字符数字长度,stdin)获取键盘输入;
通过pipe()函数建立管道;
用close(fd[0])关闭父进程管道读指针,利用write(fd[1],要写入的字符串,字符串长度);
用close(fd[1])关闭子进程管道写指针,利用read(fd[0],要写入的字符串字符串长度);
与实验三直接在代码中加入字符串的区别在于用fgets(字符数组名,字符数字长度,stdin)获取键盘输入,并将其存放在该字符数组中,在进行传递字符时,直接使用字符数组名进行传递。
4.实验总结与反思
通过这次实验了解到wait();
exit();
fget(;
stdin);
pipe(fd[2]);
close(fd[0]);
dup(files);
等句子在进程间通信的使用,知道通信间的一些逻辑关系,学会如何改变父子进程执行顺序的先后、如何实现父子进程间信息的传递,受益匪浅。
关于每个程序的分析已附在每个程序代码注释和运行结果分析。
同时,实验过程多与别人讨论,多输入不同的数据,稍微改动程序进行尝试,都会使自己从更多的角度来看待问题,解决问题,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- lab5 Linux进程及并发程序设计 Linux 进程 并发 程序设计