1、1*实践教学*兰州理工大学计算机与通信学院2011 年秋季学期操作系统原理课程设计题 目: 进程的管道通信实验专业班级: 09 软件工程(1)班姓 名: 刘旭 学 号: 09240201 指导教师: 王旭阳 成 绩: _2目 录摘 要 .3正 文 .4一问题描述 .4二. 设计目的 .4三. 设计要求 .5四. 详细设计 .51程序流程图 62算法设计 7五. 结果分析 .9设计总结 .10参考文献 .11致 谢 .12附件 源程序代码 133摘 要管道通信是发送进程和接收进程之间通过一个通道交流信息,管道是单向的,发送进程视管道为输出文件,即向管道写入数据,接收进程视管道为输入文件,即从中读
2、取数据。先写入的必定先读出,即管道通信的工作是单向的并以先进先出为顺序。管道通信的实质是一个共享文件,数据以自然字符流的方式写入和读出。在 Linux 系统中,进程在执行系统调用 pipe()之后便创建了一个无名管道。在管道通信实验中,可用父进程创建一个无名管道,子进程向其中写入信息,父进程从其中读取信息并显示。关键词:父进程,子进程,管道,通信,文件4正 文一问题描述:(1).了解 UNIX 的命令及使用格式,熟悉 UNIX/LINUX 的常用基本命令,练习并掌握 UNIX 提供的 vi 编辑器来编译 C 程序,学会利用 gcc、gdb 编译、调试C 程序。(2).编写程序实现进程的管道通信
3、。用系统调用 pipe( )建立一管道,二个子进程 P1 和 P2 分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收 P1,后P2) 。二.设计目的:通过该题目的设计过程,熟悉 UNIX/LINUX 支持的管道通信方式,了解该系统下进程管道通信机制,掌握进程管道通信程常用的系统函数,能够编写代码实现父子进程的管道通信。练习并掌握 UNIX/LINUX 提供的 vi 编辑器来编译 C 程序,学会利用gcc、gdb 编译、调试 C 程序。5三.设计要求:
4、编写程序实现进程的管道通信。用系统调用 pipe( )建立一管道,二个子进程 P1 和 P2 分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收 P1,后P2) 。四. 详细设计:1程序流程图函数的调用关系图:61 2 2fd1 Child proces 1 is endigmesage ! OutPipe 1fdfd 1fd1OutPipefd1fd1 Child proces 2 is endigmesage ! OutPipeOutPipefd1
5、fd11fd0InPipe 2fd0InPipeInPipe272算法设计各模块的伪码算法该函数使用头文件如下:#include #include #include #include 1. pipe() 函数调用格式:int fd2;pipe(fd)功能: 建匿名管道,fd0为读端,fd1为写端。2fork() 函数调用格式:pid_t pid1,pid2;pid1=fork();pid2=fork();功能:fork()函数创建子进程。注:此函数被调用一次但返回两次,子进程中返回 0 值,而父进程中返回子进程 ID;调用 fork()函数,父、子进程的执行次序不确定。3.sprintf()
6、函数调用格式:char outpipe50;char string = “hello”;sprintf(outpipe,string);功能: 把字符串 string 的内容写入到字符数组 outpipe 中。 4.write() 函数调用格式:write(fd1,outpipe,nbyte);功能: 把 nbyte 个字节的数据,从 outpipe 所指向的缓冲区写到由 fd 所8指向的系统文件中。写入内容时,关闭读取端,锁定写入端,写入完成,解除锁定。5.read() 函数调用格式:read(fd0,inpipe,nbyte);功能: 从 fd0端读取 nbyte 个字节的数据,并把数据写
7、入到 inpipe 中。6.lockf() 函数调用格式:lockf(fd1,1,0);功能: 锁定管道写端,保证写入数据的完整性。lockf(fd1,0,0);功能: 解锁管道写端。7.wait() 函数调用格式:wait(NULL);功能: 在用 fork()创建一个子进程的时候,若先进入父进程,则使其等待,直到子进程把信息写入管道,再执行父进程。8.sleep() 函数调用格式:sleep(num);功能: 使进程休眠 num 秒。9.exit() 函数调用格式:exit(0);功能: 子进程执行写入数据操作完成,退出,并向系统返回 0 值。9五. 结果分析最终所得结果如下图所示:10设
8、计总结通过这次课程设计,我对操作系统的进程管道通信有了进一步的了解,同时熟悉了在 linux 环境下 c 语言的编译和调试,以及 linux 系统有关进程管道通信的函数。更为重要的是,将所学的课本理论知识运用到实践当中,实现了理论与实践相结合,提高了解决实际问题的能力。从开始借阅书籍,上网查找相关资料,到设计程序,短短两周很快就过去了。在这次课程设计的过程中,我遇到了很多困难,通过自己的不断努力,同学的帮助,和老师的细心指导,进程的管道通信实验基本完成。其功能基本符合课程设计任务的要求。在此次实践设计中我遇到了很多困难,这说明对理论知识还需要深入地理解。动手实践编写程序,调试程序则是更为重要的
9、。所以在平时学习课本知识的同时,需要亲自实践编写代码实现理论的知识,提高自己的实际动手能力,并加深对理论知识的理解。最后,通过该题目的设计过程,我熟悉 Linux 操作系统、gcc、vim 编辑器、makefile、gdb 以及 linux 下进程的管道通信,进一步理解了操作系统中进程管道通信的原理,并学会如何在 linux 操作系统中实现进程的管道通信。11参考文献1. 汤子瀛,哲凤屏.计算机操作系统.西安电子科技大学学出版社.2. 王清,李光明.计算机操作系统.冶金工业出版社.3. 孙钟秀等.操作系统教程. 高等教育出版社4. 曾明. Linux 操作系统应用教程. 陕西科学技术出版社.
10、5. 张丽芬,刘利雄.操作系统实验教程. 清华大学出版社.6. 孟静.操作系统教程原理和实例分析. 高等教育出版社7. 周长林.计算机操作系统教程. 高等教育出版社8. 张尧学.计算机操作系统教程.清华大学出版社9. 任满杰.操作系统原理 实用 教程.电子工业出版社12致 谢这次课程设计使我学到了很多实用知识,真正做到了理论与实践相结合,得到了操作系统方面的综合训练,提高了解决实际问题的能力。这次课程设计也使我明白了,学习知识不仅仅是停留在书本上那么简单,编写代码,调试程序,更是一种有效地学习知识的方法。只有理论与实践相结合才在以后的学习与工作中走的更高走的更远。在此,感谢王旭阳老师孜孜不倦的
11、指导同学无私的帮助。13附录:源程序代码 #include #include #include #include int main()pid_t pid1,pid2;int fd2;char outpipe50,inpipe50;if(pipe(fd)0) /* 创建匿名管道,fd0为读端,fd1为写端 */printf(“Pipe create error!n“);exit(-1);/* This is the child process 1 */* fork 函数被调用一次但返回两次,子进程中返回 0 值,而父进程中返回子进程 ID;*/14/* 但调用 fork()父子进程的执行次序不确
12、定.*/* 如果创建子进程失败,则退出 */if(pid1=fork() = -1) /* 创建子进程 1 */printf(“Error in fork().n“);exit(-1);/* 执行子进程 1,向管道写入信息 */if(pid1=0)lockf(fd1,1,0); /* 锁定管道写端,保证写入数据的完整性 */sprintf(outpipe,“child 1 is sending a message!“);write(fd1,outpipe,35); /* 子进程向管道中写入信息 */lockf(fd1,0,0); /* 解锁管道写端 */exit(0); /* 子进程 1 退出
13、 */else /* 若先进入父进程,则使其等待,直到子进程 1 把信息写入管道 */* 即:先让子进程 1 把信息写入管道,后让子进程 2 把信息写入管道 */15wait(NULL);/* This is the child process 2 */* 如果创建子进程失败,则退出 */if(pid2=fork() = -1)printf(“Error in fork().n“);exit(-1);/* 执行子进程 2 */if(pid2=0)lockf(fd1,1,0); /* 锁定管道写端,保证写入数据的完整性 */sprintf(outpipe,“Child 2 is sending
14、a message!“);write(fd1,outpipe,34);lockf(fd1,0,0);/* 解锁管道写端 */exit(0); /* 子进程 2 退出 */elsewait(0); /* 若先执行父进程,则等待,直到子进程 2 写入信息*/16sleep(1); /* 休眠 1 秒 */read(fd0,inpipe,35); /* 从管道中读取信息,此信息由子进程1 写入 */printf(“%sn“,inpipe); /* 打印输出信息*/sleep(1);read(fd0,inpipe,35); /* 从管道中读取信息,此信息由子进程2 写入 */printf(“%sn“,inpipe);return 0;