#系统编程----管道、命名管道

一、无名管道

1.1无名管道概述

管道(pipe)又称无名管道。
无名管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符。
任何一个进程在创建的时候,系统都会给他分配4G的虚拟内存,分为3G的用户空间和1G的内核空间,内核空间是所有进程公有的,无名管道就是创建在内核空间的,多进程知道同一个无名管道的空间,就可以利用它来进行通信。

#系统编程----管道、命名管道_第1张图片

无名管道虽然是在内核空间创建的,但是会给当前用户进程两个文件描述符,一个负责执行读操作,一个负责写操作。

管道是最古老的UNIX IPC方式,其特点是:

1、半双工,数据在同一时刻只能在一个方向上流动。

2、写入管道中的数据遵循先入先出的规则。

3、管道所传送的数据是无格式的,这要求管道的读写方式必须事先约定好数据的格式,比如说多少个字节算一个消息等。

4、管道不是普通的文件,不属于某个文件系统,其中只存在于内存中。

5、数据只能一端进一端出。

6、管道在内存中对应的一个缓冲区,不同的系统其大小不一定相同。

7、从管道读取数据是一次性操作,数据一点别读走,他就从管道中被抛弃,释放空间以便写更多的数据。

8、管道没有名字,只能存在具有公共祖先的进程之间使用

1.2无名管道的创建 -- pipe函数

#系统编程----管道、命名管道_第2张图片

案例:

#系统编程----管道、命名管道_第3张图片

#系统编程----管道、命名管道_第4张图片

结果:

#系统编程----管道、命名管道_第5张图片

1.3无名管道实现进程件的通信

案例:

#系统编程----管道、命名管道_第6张图片

结果:

注意:

         利用无名管道实现进程的通信,都是父进程创建无名管道,然后再创建子进程,子进程继承父进程的文件描述符,然后父子进程通过读写无名管道实现通信。

1.4通过fcntl函数设置文件的阻塞特性

设置为阻塞:

        fcntl(fd, F_SETFL, 0);

设置为非阻塞:

        fcntl(fd, F_SETFL, O_NONBLOCK);        

非阻塞:
        如果是阻塞,管道中没有数据,read会一直等待,直到有数据才会继续运行,否则一 直等待 如果是非阻塞,read函数运行时,会先看一下管道中是否有数据,如果有数据,则正常运行读取数据,如果管道中没有数据,则read函数会立即返回,继续下面的代码运行。
案例:
#系统编程----管道、命名管道_第7张图片
#系统编程----管道、命名管道_第8张图片
结果:

#系统编程----管道、命名管道_第9张图片

二、文件描述符概述

文件描述符是非负数的,是文件的标识。

用户使用文件描述符(file descriptor)来访问文件。

每个进程间都有一张文件描述符的表,进程刚刚被创建时,标准输入、标准输出、标准错误输出。

设备文件被打开,对应的文件描述符0、1、2记录在表中。

在进程中打开其文件时,系统会返回文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中。

注意:
Linux中一个进程最多只能打开NR_OPEN_DEFAULT (即1024)个文件,故当文件不再使用时应及时调用close函数关闭文件。

三、文件描述符的复制

3.1dup函数

#系统编程----管道、命名管道_第10张图片

3.1.1案例1:使用dup函数赋值文件描述符

#系统编程----管道、命名管道_第11张图片

执行结果:

3.1.2案例2:实现输出重定向的功能

#系统编程----管道、命名管道_第12张图片

执行结果:

3.13案例3:实现输出重定向后,又想标准输出,如何实现

#系统编程----管道、命名管道_第13张图片

执行结果:

#系统编程----管道、命名管道_第14张图片

四、有名管道

4.1有名管道的概述

命名管道(FIFO)和管道(pipe)基本相同,但有一些明显的不一样。

它的特点是:

1、半双工,数据在同一时刻只能在一个方向上流动。

2、写入FIFO中的数据遵循先入先出的规则。

3、FIFO所传送的数据是无格式的,这要求FIFO的读出方式与写入方式必须实现商量好格式。

4、FIFO在文件系统中作为一个特殊的文件而存在并且在文件系统中可见,所以有名管道可以实现不相关进程间的通信,但FIFO中的内容却放在内存中。

5、管道在内存中存在对应一个缓冲区。不同的系统其大小不一定相同。

6、从FIFO读数据是一次性操作,数据一旦被读他就从FIFO中被抛弃,释放空间以便写更多的数据。

7、当时用FIFO的进程退出后,FIFO文件将继续保存文件在系统中以便以后使用

8、FIFO有名字,不相关的进程可以通过打开命名管道进行通信

4.2有名管道的创建

方法一:用shell命令mkfifo创建有名管道:

方法二:使用函数mkfifo

#系统编程----管道、命名管道_第15张图片

#系统编程----管道、命名管道_第16张图片

结果:

#系统编程----管道、命名管道_第17张图片

4.3有名管道的基本读写

由于有名管道在本地创建了一个管道文件,所以系统调用的IO函数基本都可以对有名管道进行操作,但是不能使用lseek修改管道文件的偏移量。

注意:有名管道创建的本地的文件知识起到标识作用,真正的有名管道实现进程间的通信还是在内核空间开辟内存,所以本地产生的文件知识一个标识,没有其他的作用,对本地管道文件的操作实质就是对内核空间的操作。

#系统编程----管道、命名管道_第18张图片

#系统编程----管道、命名管道_第19张图片

4.4有名管道实现进程间通信

由于有命管道在本地创建了一个管道文件,所以不想干的进程间也可以实现通信

4.4.1send

#系统编程----管道、命名管道_第20张图片

#系统编程----管道、命名管道_第21张图片

4.4.2recv

#系统编程----管道、命名管道_第22张图片

#系统编程----管道、命名管道_第23张图片

执行结果:

你可能感兴趣的:(linux,运维,服务器)