进程间通信

管道

管道是一种2个进程进行单向通信的机制。

通过管道通信的2个进程,1个进程向管道写数据,另外1个进程从管道的另一端读数据。写入的数据每次都添加在管道缓冲区的末尾,读数据的时候都是从缓冲区的头部读出数据.

管道是1个特殊的文件,这个文件只存在于内存中。创建管道时,系统为管道分配一个页面作为数据缓冲区。

对于一些简单的进程间通信,管道还是可以完全胜任的

管道的局限:

  • 没有名字
  • 缓冲区大小受限制
  • 所传的是无格式的字节流
  • 只能用于父子进程或者兄弟进程的通信
  • 数据只能由1个进程流向另一个进程,如果要进行全双工,需要建立2个管道

1.创建管道

#include #include 
int pipe(int fd[2])//调用成功返回0,并且数组中将包含2个新的文件描述符,有错误发生返回-1
  • 管道两端分别用描述符fd[0]表示管道读端,fd[1]表示管道写端。反着用会出错。

  • 如果读进程不读走管道缓冲区的数据,写操作阻塞等待。

  • 如果写进程没有往缓冲区写数据,读操作阻塞等待。

文件描述符
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向[内核](https://baike.baidu.com/item/内核)为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于[UNIX](https://baike.baidu.com/item/UNIX)、[Linux](文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向[内核](https://baike.baidu.com/item/内核)为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于[UNIX](https://baike.baidu.com/item/UNIX)、[Linux](https://baike.baidu.com/item/Linux)这样的操作系统。

习惯上,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2。尽管这种习惯并非[Unix](https://baike.baidu.com/item/Unix)内核的特性,但是因为一些 shell 和很多应用程序都使用这种习惯,因此,如果内核不遵循这种习惯的话,很多应用程序将不能使用。

POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个[符号常量](https://baike.baidu.com/item/符号常量)的定义位于头文件 unistd.h。

文件描述符的有效范围是 0 到 OPEN_MAX。一般来说,每个进程最多可以打开 64 个文件(0 — 63)

2.管道的一般用法

3.dup()和dup2()函数:复制文件描述符

#include #include 
int dup(int oldfd);
int dup2(int oldfd,int newfd);

dup()和dup2()函数成功时均返回1个oldfd文件描述符的父辈,失败则返回-1.

  • dup函数返回的文件描述符是当前可用文件描述符中的最小数值:

    dup(fd[0])返回0:表示将fd[0]复制到返回的描述符dup(fd[0])返回0:表示将fd[0]复制到返回的描述符0
  • dup2函数可利用参数newfd指定想返回的文件描述符.

4.管道的应用实例

管道的一种常见用法:在父进程创建子进程后向子进程传递参数,

有名管道

消息队列

1.基本概念

消息队列是存放在内核中的消息链表,每个消息队列由消息队列标识。只有OS重启或者显示的删除1个消息队列时,该消息队列才会被真正删除.

操作消息队列时,需要用到一些数据结构,熟悉这些数据结构是掌握消息队列的关键。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!