实验八 进程通信应用

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共

相关文档
最新文档