实验二_进程间通信

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验二 进程间通信
一、实验目的 在本实验中,通过对文件映射对象的了解,来加深对 Windows 2000 线程同步的理解. 回顾系统进程、线程的有关概念,加深对 Windows 2000 线程间通讯的理解;了解文件映射 对象;通过分析实验程序,了解线程如何通过文件映射对象发送数据;了解在进程中如何使 用文件映射对象. 二、背景知识 1. 共享内存: Windows 2000 提供了一种在文件中处理数据的方法, 名为内存映射文件, 也称为文件映射.文件映射对象是在虚拟内存中分配的永久或临时文件对象区域 (如果可能 的话,可大到整个文件) ,可将其看作是二进制的数据块.使用这类对象,可获得直接在内 存中访问文件内容的能力. 文件映射对象提供了强大的扫描文件中数据的能力,而不必移动文件指针.对于多线程 的读写操作来说, 这一点特别有用, 因为每个线程都可能想要把读取指针移动到不同的位置 去——为了防止这种情况,就需要使用某种线程同步机制保护文件. 在 CreateFileMapping() API 中,一个新的文件映射对象需要有一个永久的文件对象 (由 CreateFile() 所创建) .该函数使用标准的安全性和命名参数,还有用于允许操作 (如只读) 的保护标志以及映射的最大容量.随后可根据来自 OpenFileMapping() API 的其他线程或进程 使用该映射——这与事件和互斥体的打开进程是非常类似的. 内存映射文件对象的另一个强大的应用是可请求系统创建一个运行映射的临时文件.该 临时文件提供一个临时的区域, 用于线程或进程互相发送大量数据, 而不必创建或保护磁盘 上的文件.利用向创建函数中发送 INVALID_HANDLE_VALUE 来代替真正的文件句柄,就 可创建这一临时的内存映射文件; 指令内核使用系统页式文件来建立支持映射的最大容量的 临时数据区. 为了利用文件映射对象,进程必须将对文件的查看映射到它的内存空间中.也就是说, 应该将文件映射对象想象为进程的第一步,在这一步中,当查看实际上允许访问的数据时, 附加有共享数据的安全性和命名方式.为了获得指向内存区域的指针需要调用 MapViewOfFile() API,此调用使用文件映射对象的句柄作为其主要参数.此外还有所需的访 问等级 (如读-写) 和开始查看时文件内的偏移和要查看的容量.该函数返回一个指向进程内 的内存的指针,此指针可有多种编程方面的应用 (但不能超过访问权限) . 当结束文件映射查看时,必须用接受到的指针调用 UnmapViewOfFlie() API,然后再根 据映射对象调用 CloseHandle() API,从而将其清除。
三、实验内容 1. 编译运行项目 Lab5.1\SHAREMEM.DSW,观察运行结果,并阅读和分析实验程序.

2. Lab5.2 目录下的示例程序:ProcessA.exe,ProcessB.exe 用三种方法实现了进程通信. (1)进程 A 中输入一些字符,点“利用 SendMessage 发送消息”按钮可将消息发到进程 B. (2)在进程 A 中输入一些字符,点“写数据到内存映像文件”按钮,然后在进程 B 中点“从 内存映像文件读数据” 按钮可收到消息. (3)先在进程 B 中点“创建管道并接收数据” 按钮,然后在进程 A 中输入一些字符,点“写 数据到管道文件”按钮可将消息发到进程 B(重复第 3 步每次可发一条消息). 消息传递数据通信可参考 SendMessage.txt,共享内存通信可参考 MemFile.txt,管道 通信可参考 Pipe.txt. 3.编写程序利用 WM_COPYDATA 消息机制,实现线程间的通信.
进程间通信之管道
每个进程各自有不同的用户地址空间, 任何一个进程的全局变量在另一个进程中 都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区, 进程 1 把数据从用户空间拷到内核缓冲区,进程 2 再从内核缓冲区把数据读走, 内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。 如下图所示。
图 3.1 进程间通信

3.1 管道
管道是一种最基本的 IPC 机制,由 pipe 函数创建:
#include
int pipe(int filedes[2]);
调用 pipe 函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读 端一个写端, 然后通过 filedes 参数传出给用户程序两个文件描述符, filedes[0] 指向管道的读端,filedes[1]指向管道的写端(很好记,就像 0 是标准输入 1 是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,通过 read(filedes[0]);或者 write(filedes[1]);向这个文件读写数据其实是在读 写内核缓冲区。pipe 函数调用成功返回 0,调用失败返回-1。 开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。

图 3.2 管道
1. 父进程调用 pipe 开辟管道, 得到两个文件描述符指向管道的两端。 2. 父进程调用 fork 创建子进程,那么子进程也有两个文件描述符指 向同一管道。 3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里 写,子进程可以从管道里读,管道是用环形队列实现的,数据从写 端流入从读端流出,这样就实现了进程间通信。

例、管道
#include #include #define MAXLINE 80
int main(void) { int n; int fd[2]; pid_t pid; char line[MAXLINE];
if (pipe(fd) < 0) { perror("pipe"); exit(1); } if ((pid = fork()) < 0) { perror("fork"); exit(1); } if (pid > 0) { /* parent */ close(fd[0]); write(fd[1], "hello world\n", 12); wait(NULL);

相关文档
最新文档