IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux IPC-管道和FIFO -> 正文阅读

[系统运维]linux IPC-管道和FIFO

目录

1、管道

1.1、pipe()函数

1.2、popen()函数

1.3、pclose()函数

1.4、system函数

1.5、popen与system区别

2、FIFO(有名管道)

2.1、mkfifo()函数

2.2、FIFO与NFS的关系

3、管道和FIFO的额外属性

4、管道和FIFO限制

4.1、查看限制

5、字节流I/O模型


1、管道

管道没有名字,只能由有亲缘关系的进程使用。

注:从技术上上讲,自从可以在进程间传递描述符后,管道也能用于无亲缘关系的进程间。然而现实中,管道通常用于具有共同祖先的进程间。

宏S_ISFIFO可用于确定一个描述符或文件是是不是FIFO.它的唯一参数是stat结构的st_mode成员,计算结果或者为真(非零值),或者为假(0),对于管道来说,这个stat结构是fstat函数填写的。对于FIFO来说,这个结构是由fstat或stat函数填写的。

管道是半双工的即单向的,只提供一个方向的数据流。当需要双向数据流时,必须创建两个管道,每个方向一个。步骤如下:

1)创建管道1(fd1[0]和fd1[1])和管道2(fd2[0]和fd2[1])

2) fork

3)父进程关闭管道1的读出端

4)父进程关闭管道2的写入端

5)子进程关闭管道1的写入端

6)子进程关闭管道2的读出端

1.1、pipe()函数

#include <unistd.h>
int pipe(int fd[2])

参数 fd:fd[0]读,fd[1]写

1.2、popen()函数

popen在调用进程和所指定的命令之间创建一个管道。

#include <stdio.h>

FILE *popen(const char *command,const char *type);

参数?command:一个shell命令行。

参数?type:类型

r调用进程读进command的标准输出
w调用进程写到command的标准输入

返回值:一个标准I/O FILE指针,该指针或者用于输入,或者用于输出,取决于type。

注:popen不对标准错误输出作任何特殊的处理-只有标准输出才被重定向到由它创建的管道

1.3、pclose()函数

关闭由popen()创建的I/O流,等待其中的命令终止,然后返回shell的终止状态。

#include <stdio.h>

int pclose(FILE *stream);

参数?stream:popen()创建的I/O流

返回值:失败返回-1,并设置错误码。

1.4、system函数

使用 system函数可以很方便地在程序当中执行任意 shell 命令。system函数其内部的是通过调用 fork()、execl()以及 waitpid()这三个函数来实现它的功能, 首先 system函数会调用 fork函数创建一个子进程来运行 shell(可以把这个子进程成为 shell 进程) ,并通过 shell 执行参数command 所指定的命令。

函数原型如下:

#include <stdlib.h>

int system(const char *command);

参数 command:指向需要执行的 shell 命令,以字符串的形式提供,
返回值:

1) 当参数 command 为 NULL, 如果 shell 可用则返回一个非 0 值,若不可用则返回 0;针对一些非UNIX 系统,该系统上可能是没有 shell ,这样就会导致 shell 不可能;

2)如果 command 参数不为NULL,则返回值从以下的各种情况所决定。
a、?如果无法创建子进程或无法获取子进程的终止状态,那么 system()返回-1
b、如果子进程不能执行 shell,则 system()的返回值就好像是子进程通过调用_exit(127)终止了;
c、如果所有的系统调用都成功, system()函数会返回执行 command 的 shell 进程的终止状态。
?

1.5、popen与system区别

1)popen是不堵塞的,也就是说不会等待子进程的结束并杀死子进程,即不会管理进程。这样就需要我们手动的去杀死或忽略子进程等操作。 system是堵塞的,会自动对进程进行管理,无需我们再去对进程进行管理。

2)popen会将执行的结果返回到buf中。另外,system不会返回执行的结果,只是会返回执行是否成功。

注:linux尽量避免使用system。

2、FIFO(有名管道)

不同于管道的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程访问同一个FIFO。

注:对管道或FIFO的write总是往末尾添加数据,对它们的read则总是从开头返回数据。如果对管道或FIFO调用lseek,那就返回ESPIPE错误。

2.1、mkfifo()函数

要打开一个已存在的FIFO或创建一个新的FIFO,应先调用mkfifo,再检查它是否返回EEXIST错误,若返回错误则改为调用open。

注:mkfifo隐含指定O_CREAT|O_EXCL.如果不希望创建一个新的FIFO,那就改为调用open而不是mkefifo。

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname,mode_t mode)

参数 pathname:一个普通的路径名。

参数 mode:指定文件权限位,类似于open的第二个参数。

返回值:成功返回0,出错返回-1,并设置错误码。

注:FIFO不能打开来既读又写,因为它是半双工的。

2.2、FIFO与NFS的关系

FIFO是一种只能在单台主机上使用的IPC形式。尽管在文件系统中有名字,它们也只能用在本地文件系统上,而不能用在通过NFS安装的文件系统上。

有些系统允许在通过NFS安装的文件系统上创建FIFO,但是数据无法在这样的两个系统间通过这些FIFO传递。这种情况下,FIFO只是用作同一主机上客户和服务器之间位于文件系统中的集结点。即使在不同主机上的某两个进程都能通过NFS打开同一个FIFO,它们也不能通过该FIFO从一个进程向另一个进程发送数据。

3、管道和FIFO的额外属性

当对一个管道或FIFO的最终close发送时,该管道或FIFO的任何残余数据都被丢弃。

当前操作当前管道或FIFO的打开操作阻塞非阻塞
open FIFO读FIFO打开来写成功返回成功返回
FIFO不是打开来写阻塞到FIFO打开来写为止成功返回
open FIFO写FIFO打开来读成功返回成功返回
FIFO不是打开来读阻塞到FIFO打开来读为止返回ENXIO错误
从空管道或空FIFO read管道或FIFO打开来写阻塞到管道或FIFO中有数据或者管道管道或FIFO不在为写打开着为止返回EAGAIN错误
管道或FIFO不是打开来写read返回0(文件结束符)read返回0(文件结束符)
往管道或FIFO write管道或FIFO打开来读见下文见下文
管道或FIFO不是打开来读产生SIGPIPE产生SIGPIPE
从非空管道或非空FIFO read/如果请求读出的数据量多于管道或FIFO中当前可用数据量,那么只返回这些可用的数据

1)如果请求写入的数据的字节数小于或等于PIPE_BUF,那么write操作保证是原子的如果请求写入的数据字节数大于PIPE_BUF,那么write操作不能保证是原子的

2)O_NONBLOCK标志的设置对write操作的原子性没有影响--原子性完全是由所请求字节是否小于等于PIPE_BUF决定的。当设置为非阻塞时,来自write的返回值取决于待写的字节数以及该管道或FIFO中当前可用空间的大小。

待写入小于或等于PIPE_BUF如果该管道或FIFO中有足以存放所请求字节数的空间那么所有字节都写入
如果该管道或FIFO中没有足以存放所请求字节数的空间那么立刻返回一个EAGAIN错误(原子性)
待写入大于PIPE_BUF如果该管道或FIFO中至少有1字节空间那么内核写入该管道或FIFO能容纳数目的数据字节,该数目作为来自write的返回值。
如果该管道或FIFO已满,那么立刻返回一个EAGAIN错误

3)如果向一个没有为读打开着的管道或FIFO写入,那么内核将产生一个SIGPIPE信号。

1如果调用进程既没有捕获也没有忽略该SIGPIPE信号,所采取的默认行为是终止进程
2如果调用进程忽略该SIGPIPE信号,或者捕获了该信号并从其信号处理程序中返回,那么write返回一个EPIPE错误。

4、管道和FIFO限制

OPEN_MAX一个进程在任意时刻打开的最大描述符(Posix要求至少为16)
PIPE_BUF可原子地写往一个管道或FIFO的最大数据量(Posix要求至少为512)

4.1、查看限制

1)ulimit?

2)?getcon

名称获取方式Ubuntu测试值
获取OPEN_MAXgetconf OPEN_MAX1024
获取PIPE_BUFgetconf PIPE_BUF /4096

3)运行时获取

获取OPEN_MAXsysconf(_SC_OPEN_MAX)
获取PIPE_BUFpathconf("/",_PC_PIPE_BUF)

5、字节流I/O模型

管道和FIFO都使用字节流I/O模型,这种模型不存在记录边界。

1)带内特殊终止序列。这种技巧一般要求数据中任何出现分隔符处都作转义处理

2)显示长度。这种技巧的优势之一是不再需要通过转义出现在数据中的分隔符因为接收者不必扫描整个数据以寻找每个记录的结束位置。

3)每次连接一个记录:应用通过关闭与其对端的连接来指示一个记录的结束。这要求为每个记录创建一个新连接。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:39:24  更:2021-09-13 09:41:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 16:56:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码