linux课程实践—管道通信(C语言).doc_第1页
linux课程实践—管道通信(C语言).doc_第2页
linux课程实践—管道通信(C语言).doc_第3页
linux课程实践—管道通信(C语言).doc_第4页
linux课程实践—管道通信(C语言).doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux课程实践linux下管道通信的实现(C语言实现) 班级:08电本班 姓名:张家瑞 学号:49号 指导老师:兰建平Linux环境中管道通信的实现 摘要Linux系统提供了丰富的进程通信手段,如信号、信号灯、管道、共享内存、消息队列等,能有效地完成多个进程间的信息共享和数据交换。本文主要设计了Linux环境中的管道通信,并给出了利用该技术制作程序运行进程通信的实例。 关键词管道;进程通信;IPC;Motif;进程条1引言 Linux系统提供了丰富的进程通信手段,如信号、信号灯、管道、共享内存、消息队列等,能有效地完成多个进程间的信息共享和数据交换。管道作为最早的进程间通信机制之一,可以在进程之间提供简单的数据交换和通信功能。2管道技术简介2.1管道的概念及特点 管道分为无名管道和有名管道两种。无名管道可用于具有亲缘关系进程间的通信,如父子进程、兄弟进程。有名管道克服了管道没有名字的限制,允许无亲缘关系进程间的通信。本文应用的是无名管道通信机制。 管道具有以下特点: (1)管道是半双工的,数据只能单向流动;需要相互通信时,就要建立两个管道。 (2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程,有名管道则突破了这一限制)。 (3)单独构成一种独立的文件系统,并且只存在于内存中。 (4)数据的读出和写入都是单向的:一个进程向管道中写的数据被管道另一端的进程读出。写入的数据每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。2.2管道的创建 #include int pipe(int fd2) 该函数是Linux的一个系统调用,其创建的管道两端处于一个进程中间。要用其实现父子进程之间的通信则需要在由pipe()创建管道后,再由系统调用fork创建一个新的子进程,然后通过管道在这两个进程间传送数据,实现进程间的通信(同样,不是父子关系和两个进程,只要两个进程中存在亲缘关系具有共同的祖先,都可以采用管道方式来进行通信)。2.3管道的读写 Pipe函数有一个参数fd2,是用于管道两端的描述字。管道一端只能用于读,由描述字fd0表示,即管道读端;另一端则只能用于写,由描述字fd1表示,即管道写端。既不能从管道写端读取数据,也不能向管道读端写入数据。I/O函数close、read、write等都可以用于对管道进行操作。从管道中读取数据时,如果管道的写端不存在,则认为已经读到了数据末尾,读函数返回的读出字节数为0;若管道写端存在,如果请求的字节数目大于管道中现有的数据字节数,则返回管道中现有数据字节数;否则返回请求的字节数。向管道中写入数据时,只要管道缓冲区有空闲区域,写进程就会试图向管道中写入数据。如果读数据的进程不读走管道缓冲区中的数据,那么将导致写操作的阻塞。这是管道通信的一个弊端。3 Gcc的使用Gcc编译器能将C、C+语言源程序、汇程式化序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。Gcc的执行过程虽然我们称Gcc是C语言的编译器,但使用gcc由C语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。 命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。 接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。 当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。4 实现步骤4.1 管道的创建管道是一种最基本的IPC机制,由pipe函数创建:#include int pipe(int filedes2);调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes0指向管道的读端,filedes1指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,通过read(filedes0);或者write(filedes1);向这个文件读写数据其实是在读写内核缓冲区。pipe函数调用成功返回0,调用失败返回-1。开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。1. 父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。 4.2 源程序的编写所使用的头文件:#include#include#include#include#include#include创建管道函数:int main() pid_t result; int r_num; int pipe_fd2; char buf_r200; memset(buf_r,0,sizeof(buf_r); if(pipe(pipe_fd)0) printf(创建管道失败); return -1; 创建子进程函数:if(result0) printf(子进程从管道读取%d个字符,读取的字符串是:%sn,r_num,buf_r); close(pipe_fd0); exit(0); else close(pipe_fd0);创建父进程函数:if(write(pipe_fd1,*Hello world !*,17)!=-1) printf(父进程向管道写入*Hello world !*n); if(write(pipe_fd1, *Welcome !*,15)!=-1) printf(父进程向管道写入*Hello world !*n); close(pipe_fd1); waitpid(result,NULL,0); exit(0); 5 运行结果: 5.1 编译源程序www.c Gcc Wall www.c o www5.2 执行源程序www ./www5.3 运行结果C语言编译环境在终端下编译www.c文件成为可执行文件www命令为:gcc Wall www.c o www执行程序www,运行结果如下:父进程向管道中输入*Hello world!*与*Welcome!*子进程从管道中读出32个字符,分别为*Hello world!*,*Welcome!*。6 实验源程序:#include#include#include#include#include#includeint main() pid_t result; int r_num; int pipe_fd2; char buf_r200; memset(buf_r,0,sizeof(buf_r); if(pipe(pipe_fd)0) printf(创建管道失败); return -1; result=fork(); if(result0) printf(子进程从管道读取%d个字符,读取的字符串是:%sn,r_num,buf_r); close(pipe_fd0); exit(0); else close(pipe_fd0); if(write(pipe_fd1,*Hello wo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论