实验八 进程通信应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验八进程通信应用
实验目的
1. 掌握命名管道的原理和应用
2. 掌握文件映射共享内存的原理
3、掌握基于进程通信的程序设计方法
实验内容
1.(1)命令行下创建有名管道myfifo,ls –l查看,分别在两个终端运行cat < myfifo 和echo hello >myfifo分析执行情况,将cat在后台运行,echo在前台运行,执行情况如何?分析FIFO的打开规则。
(2)设计两个程序,要求用命名管道FIFO,实现文本文件复制功能,即实现copy file1 file2的功能,file1是已经存在的文件,file2可以不存在,如果存在就清空原来的内容,通过建立的有名管道实现file1的内容复制到file2。
一、 FIFO
1.有名管道的创建
#include
#include
int mkfifo(const char * pathname, mode_t mode)
该函数的第一个参数是一个普通的路径名,也就是创建后FIFO的名字。第二个参数与打开普通文件的open()函数中的mode 参数相同。
2. 有名管道的打开
有名管道创建成功后并没有打开,需要使用系统调用open( )将对应的文件打开。
open(const char*pathname,oflg)
其中,参数pathname是要打开的有名管道的路径名,oflg是文件打开时的存取方式。必须指定的互斥模式:
O_RDONLY, O_WRONLY, O_NONBLOCK
O_RDONLY:若无进程写方式打开FIFO,open阻塞
O_RDONLY |O_NONBLOCK:若无进程写方式打开FIFO,open立即返回
O_WRONLY:若无进程读方式打开FIFO,open阻塞
O_WRONLY| O_NONBLOCK:若无进程读方式打开FIFO,open返回ENXIO错误,-1
FIFO的打开规则:
(1)如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
(2)如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。
3.有名管道的读写
#include
ssize_t read(int fd, void *buf, size_t count);
返回值: 读到的字节数,若已到文件尾为0,若出错为-1
ssize_t write(int fd, const void *buf, size_t count);
返回值: 若成功为已写的字节数,若出错为-1
从FIFO中读取数据read
以阻塞方式打开的FIFO,read调用:
①当前FIFO内没有数据,read调用将一直阻塞。
②当前FIFO内有数据,但有其它进程在读这些数据
解除阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。
●以非阻塞方式打开的FIFO,read调用:
当前FIFO内没有数据,立即返回-1,当前errno值为EAGAIN,提醒以后再试。
向FIFO中写入数据write
●对于设置了阻塞标志的写操作:
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。
●对于没有设置阻塞标志的写操作:
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO 空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。
4.有名管道删除
有名管道和普通文件一样,存在于磁盘中。但是有名管道不能直接存储文件,其存储的通讯信息在通信的两个进程结束后自动丢失。与无名管道不同,通信的两个进程结束后,有名管道文件依然存在。需要使用系统调用unlink( )删除有名管道文件。
头文件:
#include
系统调用格式:
int unlink(const char *pathname);
unlink( )会删除参数pathname指定的文件。
二、 mmap
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上, 通过对这段内存的读取和修改, 实现对文件的读取和修改。
头文件:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);
返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).
参数:
addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.
length: 将文件的多大长度映射到内存.
prot: 映射区的保护方式, 可以是:
PROT_EXEC: 映射区可被执行.
PROT_READ: 映射区可被读取.
PROT_WRITE: 映射区可被写入.
PROT_NONE: 映射区不能存取.
flags: 映射区的特性, 可以是:
MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共