进程间通信 | 管道通信Ⅰ

学术   科技   2023-05-08 07:30   北京  

介绍

    管道可以用来两个进程之间传递数据,如ps -ef|grep “bash”,其中| 就是管道,作用就是将ps命令的结果写入管道文件,然后grep在从管道文件中读出该数据进行过滤。也就是连接一个读进程和一个写进程,以实现他们通信的一个共享文件。

    管道特性:不能能在创建时就确定确定数据流向(操作系统无法确定谁读谁写),而是在使用的时候确定,因此操作系统会提供两个描述符供使用,一个读一个写,这样的确定方向就是将对应的一段关闭掉即可,这样方向的控制权就交给了用户。

相关函数介绍

pipe()

pipe函数可用于创建一个管道,以实现进程间的通信。

头文件:

#include<unistd.h>

函数定义:

int pipe(int fd[2]);

函数说明:

    pipe函数定义中的fd参数是一个大小为2的一个数组类型的指针。该函数成功时返回0,并将一对打开的文件描述符值组填入fd参数指向的数。失败时返回 -1并设置errno

    通过pipe函数创建的这两个文件描述符fd[0] fd[1] 分别构成管道的两端往 写端文件描述符fd[1] 写入的数据可以从 读端文件描述符fd[0]读出。并且fd[1] 一端只能进行写操作,fd[0] 一端只能进行读操作,不能反过来使用,即只能实现单向传播。要实现双向数据传输,可以使用两个管道

    【阻塞与非阻塞】默认情况下,这一对文件描述符都是阻塞的。此时,如果我们用read系统调用来读取一个空的管道,则read将被阻塞,直到管道内有数据可读;如果我们用write系统调用往一个写满的管道中写数据,则write也将被阻塞,直到管道有足够的空闲空间可用(read读取数据后管道中将清除读走的数据)。当然,用户可自行将 fd[0] fd[1] 设置为非阻塞的。

    【不写无法读,不读无法写】如果管道的写端文件描述符 fd[1] 的引用计数减少至0,即没有任何进程需要往管道中写入数据,则对该管道的读端文件描述符 fd[0] read操作将返回0(管道内不存在数据的情况),即读到了文件结束标记(EOFEnd Of File);反之,如果管道的读端文件描述符 fd[0] 的引用计数减少至0,即没有任何进程需要从管道读取数据,则针对该管道的写端文件描述符 fd[1] write操作将失败,并引发SIGPIPE信号(往读端被关闭的管道或socket连接中写数据)

    【管道自身有容量限制】管道内部传输的数据是字节流,这和TCP字节流的概念相同。但它们又存在细微的差别。应用层程序能往一个TCP连接中写入多少字节的数据,取决于对方接受窗口的大小和本端的拥塞窗口的大小。而管道的话本身拥有一个容量限制,它规定如果管道的写端应用程序不将管道中数据读走的话,该管道最多还能被写入多少字节的数据。管道容量的大小默认是65536字节。我们也可以使用fcntl函数来修改管道容量。

mkfifo()

    该函数用于建立实名管道

头文件:

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

函数定义:

int mkfifo(const char * pathname,mode_t mode);

函数说明

    mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此 umask值也会影响到FIFO文件的权限。mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开 FIFO文件时,O_NONBLOCK(非阻塞模式)会有影响:

    1、当使用O_NONBLOCK时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。

    2、没有使用O_NONBLOCK时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。

返回值

    若成功则返回0,否则返回-1,错误原因存于errno中。

errno错误代码

    EACCESS 参数pathname所指定的目录路径无可执行的权限

    EEXIST 参数pathname所指定的文件已存在。

    ENAMETOOLONG 参数pathname的路径名称太长。

    ENOENT 参数pathname包含的目录不存在

    ENOSPC 文件系统的剩余空间不足

    ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。

    EROFS 参数pathname指定的文件存在于只读文件系统内。

unlink()

头文件:

#include <unistd.h>

定义函数:

int unlink(const char * pathname);

函数说明:

    unlink()会删除参数 pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数 pathname 为一符号连接, 则此连接会被删除。

返回值:

成功则返回0, 失败返回-1, 错误原因存于errno

控制工程研习
好好学习,天天向上
 最新文章