您好,欢迎来到爱站旅游。
搜索
您的当前位置:首页实验4进程间通信:管道

实验4进程间通信:管道

来源:爱站旅游
实验六、七 进程间通信:管道

一、 实验目的

1.了解 UNIX 管道的相关函数。 2.了解UNIX 管道的建立与使用。 3.能编写简单管道程序。 二、 实验预备知识 1.什么是管道

我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。我们通常是把一个进程的输出连接或“管接”(经过管道来连接)到另一个进程的输入。

2.进程管道

(1)popen函数

popen函数允许一个程序把另外一个程序当做一个新的进程来启动,并能对它发送数据或者接收数据。

格式:#include File *popen()表示这个函数的返回值类型FILE *popen(“command”,”open_mode”) 为文件指针。 其中,command参数是待操作的命令 当操作不成功时,返回值为空指针 open_mode参数的值有r和w两种:

r为读操作,表示是读入command参数提供的命令执行结果后,输出。

w为写操作,表示是向command参数提供的命令进行写操作,即为其提供输入信息,然后将这个命令的执行结果输出。有向命令提供输入信息时,使用的是fwrite函数,其格式:fwrite(信息源,信息源类型长度,信息源的长度,写入对象)。如:想把buffer这个已定义的数组变量中的信息写入popen函数,作为popen函数中command参数提供的命令的输入信息,且buffer为字符型数组,则可表示为:首先,将popen函数的结果赋给一个变量write_fp:

write_fp=popen(“od –c”, “w”);

然后,用fwrite函数指定popen的写操作的信息来源:

fwrite(buffer, sizeof(char) , strlen(buffer),write_fp); (2)pclose函数

格式:#include

int pclose(文件指针)

功能:当用popen启动的命令完成了操作的时候,我们可用pclose关闭与之关联的文件流。Pclose调用只有在popen启动的进程结束之后才能返回。如果在调用pclose的时候它仍在运行,pclose将等待该进程的结束。

如:上例中已将od –c命令运行。现要结束该命令,则用: pclose(write_fp); (3)pipe函数

通过它在两个程序之间传递数据时不需要启动一个shell来解释给定的命令,降低了程序的运行成本;我们对数据读、写操作的控制也加强了。

格式:#include

int pipe(int file_descriptor[2]);

功能:int file_descriptor[2]是一个由两个整数类型的文件描述符组成的数组(的指针)。它在数组里填上两个新的文件描述符后返回0。如果操作失败,则返回-1,并设置errno指示失败的原因。

那两个返回的文件描述符通过一种特殊的方式连接起来。写到

file_descriptor[1](即管道描述符[1])的所有数据都可按照先进先出的顺序从file_descriptor[0] (即管道描述符[0])读出来。

将信息写入管道:write(管道写入端口,要写入的信息,信息长度); 其返回值是写入信息的长度。 将管道中信息读出:read(管道读出端口,信息读出后存放地址,信息长度); 其返回值是读出信息的长度。

(4)fork函数 (此为实验七的内容) 格式:pid_t fork();

功能:创建一个新进程。若创建成功,会返回进程号;否则返回-1。 如:创建新进程

fork_result=fork(); 判断创建是否成功: if (fork_result==-1){ „„ }

判断是否在子进程: if (fork_result==0){ „„ }

还是在父进程: else { „„ }

三、 实验内容

1. 在UNIX中编写c语言程序。 2. 管道函数的使用。 3. 管道的建立。

4. 通过创建新进程来实现管道。(此为实验七的内容) od它可把用户从键盘输入的字符串(包括控制四、 命令是一个八进制输出程序。实验步骤 1. 字符:回车换行)转换成单个字符后在屏幕上输出。如:用popen和pclose函数建立一个管道 od –c 就是将用户输入的信息在屏幕上输出:一行16个字符。 (1) 新建一个C语言程序:a1.c $vi a1.c

程序目的:把数据经管道送往另一个程序 (该程序我们选用od命令) 文件a1.c的内容: #include

头文件 #include

其中,stdil.h文件提供了一个常数BUFSIZ,用于#include

指定的缓冲区长度

int main() 定义一个文件指针,以接收popen函数的值 {

定义一个数组(其实就是在内存中开辟一个缓冲区),用于存FILE *write_fp;

放要输出的数据 char buffer[BUFSIZ+1]; 若od –c执行成功 sprintf(buffer, “Once upon a time, there was …\\n”); 将Once upon a time, tere was …\\n入缓冲区 write_fp=popen(“od –c”, “w”); 执行od –c命令,并改变其输入 if(write_fp!=NULL) {

fwrite(buffer,sizeof(char),strlen(buffer),write_fp); 指定buffer缓冲区中的值为od –c的输入 pclose(write_fp); exit(EXIT_SUCCESS); 结束文件流 }

管道操作成功,退出 exit(EXIT_FAILURE); 管道操作失败,退出 }

保存退出$wq

(2) 用gcc命令将文件编译链接,生成目标文件a1.out $gcc –o a1.out a1.c

(3) 运行目标文件a1.out $./a1.out

查看运行结果,并将其记录到实验报告中。 2. 用pipe函数建立一个管道

(1) 新建一个C语言程序a2.c $vi a2.c 程序目的:用pipe函数建立一个管道。其中,从file_pipes[1]端口将some_data数组中的信息写入管道,从file_pipes[0]端口读出管道中的信息。 a2.c文件内容: #include #include #include #include 定义一个变量,用于接收write()和read()函数的值

int main() {

定义一个数组,用于做管道描述符 int data_processed; int file_pipes[2]; 定义一个数组,用于保存向管道中写入的信息 const char some_data[]=“123”; 在内存中开辟出一个缓冲区给buffer,建立管道 char buffer[BUFSIZ+1]; 定义一个数组buffer(用于保存从管道取出的信息)

memset(buffer,’\\0’,sizeof(buffer)); 将some_data中的值写入管道 若管道创建成功 if(pipe(file_pipes)==0) {

data_processed=write(file_pipes[1],some_data,strlen(some_data)); printf(“Wrote %d bytes\\n”, data_processed); 输出写入管道的信息长度 data_processed=read(file_pipes[0],buffer,BUFSIZ); printf(“Read %d bytes: %s\\n”, data_processed,buffer); 将管道中的信息读出到buffer中 exit(EXIT_SUCCESS); 退出,操作成功 输出从管道中读出的信息 }

exit(EXIT_FAILURE); }

退出,操作失败 保存退出$wq

(2) 用gcc命令将文件编译链接,生成目标文件a2.out $gcc –o a2.out a2.c

(3) 运行目标文件a2.out $./a2.out

查看运行结果,并将其记录到实验报告中。

3. 用fork函数创建管道 (此为实验七的内容)

(1) 新建一个C语言程序a3.c $vi a3.c

程序目的:先在内存中开辟出一段缓冲区,建立一个管道。再用fork函数创建一个新进程。若在子进程中,就读出管道中的信息;若在父进程中,就向管道写入信息。 a2.c文件内容: #include #include #include #include

int main()

定义一个变量,用于接收write()和read()函数的值 {

int data_processed; 定义一个数组,用于做管道描述符 定义一个变量, int file_pipes[2]; 用于存放fork()函 const char some_data[]=“123”; 定义一个数组,用于保存向管道中写入的信息 数返回的进程号 char buffer[BUFSIZ+1]; 定义一个数组buffer(用于保存从管道取出的信息) pid_t fork_result;

memset(buffer,’\\0’,sizeof(buffer));

在内存中开辟出一个缓冲区给buffer,建立管道

若管道创建成功 if(pipe(file_pipes)==0) {

创建一个新进程 fork_result=fork(); if(fork_result= =-1) { 若进程创建失败 fprintf(stderr, “Fork failure”); exit(EXIT_FAILURE); 返回,操作失败 }

我们对fork的工作情况已经比较了解了,所以如果fork_result等于0,就说明我们是在子进程里,如下所示:

if(fork_result==0) {

data_processed=read(file_pipes[0],buffer,BUFSIZ);

printf(“Read %d bytes: %s\\n”, data_processed,buffer); 将管道中的信息读出到buffer中 exit(EXIT_SUCCESS); 输出从管道中读出的信息 退出,操作成功 }

否则,我们就是在父进程里,如下所示:

将some_data中的信息写入管道 }

保存退出$wq

(2) 用gcc命令将文件编译链接,生成目标文件a2.out $gcc –o a2.out a2.c

(3) 运行目标文件a2.out $./a2.out

查看运行结果,并将其记录到实验报告中。

各部分时间安排:(共100分钟) 1. 上传、下载 (共10分钟) 2. 预备知识的学习(20分钟) 3. 动手实验

(1) 程序解读(各15分钟)

(2) 登录后录入程序 (各10分钟),建议手动录入,以便熟练掌握。 (3) 调试,记录运行结果并思考调试中出错的原因(各5分钟)

剩余10分钟用作延时(速度较慢的同学)

else {

data_processed=write(file_pipes[1],some_data,strlen(some_data)); printf(“Wrote %d bytes\\n”, data_processed);

输出写入管道的信息长度 }

exit(EXIT_SUCCESS); 退出,操作成功

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- azee.cn 版权所有 赣ICP备2024042794号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务