Linux下的进程通信方式(IPC)——管道通信

Unix IPC: 管道、命名管道(FIFO)

     管道

1、概念

管道是单向的(半双工)、先进先出、无结构的字节流,它把一个进程的输出和另一个进程的输入连接在一起。

写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。

管道提供了简单的流控制机制。进程试图读一个空管道时,在数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中读走数据之前,写进程将一直阻塞。

2、管道的特点

(1)单向数据通信,具有固定的读端和写端

(2)只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程之间)

(3)管道所传输的是无格式的字节流,要求管道输入方与输出方事先约定好数据格式

(4)管道的生命周期随进程,进程退出,文件会被操作系统回收

(5)LINUX把管道看作是一种文件,采用文件管理的方法对管道进行管理,对于它的读写也可以使

用普通的read()和write()等函数。但是它不是普通的文件,并不属于其他任何文件系统,只

存在于内核的内存空间中。

3、管道创建与关闭

>管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds[0]和fds[1]

>fds[0]固定用于读管道,fds[1]固定用于写管道

>管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符

4、管道创建函数

              所需头文件 #include<unistd.h>
      函数原型  int pipe(int fd[2])

函数传入值

fd[2]用于保存管道的两个文件描述符,之后就可以直接操作这两个文件描述符

函数返回值

成功:0
出错:-1

5、管道读写说明

> 使用管道进行父子进程间通信的步骤:

>创建管道:父进程调用pipe()函数创建一个管道

>此时,管道的读端和写端都在一个进程之中,这种管道是没有多大用的。

>父进程通过fork()函数创建一子进程

>子进程会继承父进程所创建的管道,这时,父子进程中管道的文件描述符对应关系如图所示。

>确定管道的传输方向:在父、子进程中根据需要的传输方向关闭无关的读端或写端文件描述符

>通信:在写进程中调用write()函数,在读进程中调用read()函数

>关闭管道:调用close()关闭管道相关的文件描述符。

>关闭了父进程的写端fd[1]和子进程的读端fd[0],这样就可以建立一条“子进程写入父进程读取”

的通道。

> 也可以关闭父进程的读端fd[0]和子进程的写端fd[1],这样就可以建立一条“父进程写入子进程读

取”的通道。

>父进程还可以创建多个子进程,各个子进程都继承了相应的fd[0]和fd[1],这时,只需要关闭相应

端 口就可以建立起各子进程(兄弟进程)之间的通道。

6、使用管道需要注意的4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志)

(1)如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数为0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回 0,就像读到文件末尾一样。

(2) 如果所有指向管道写端的文件描述符都没关闭(管道写端的引用计数大于0),而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

(3)如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数为0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。

(4)如果所有指向管道读端的文件描述符都没关闭(管道读端的引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

7、匿名管道的局限性

>只支持单向数据流

>只能用于具有亲缘关系的进程之间通信,没有名字

>缓冲区有限,管道只存在于主存中,大小为一个页面

>所传送的是无格式字节流

  命名管道

1、概念

       FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信,值得注意的是,FIFO总是按照先进先出的的原则工作,第一个被写入的数据将首先从管道中读出。

2、 命名管道的创建和使用

创建:

Linux有两种方式创建命名管道:

(1)在shell下交互地建立一个命名管道

可使用mknod或mkfifo命令

(2)在程序中使用系统函数建立命名管道

创建命名管道的系统函数有两个:mknod和mkfifo, 函数原型如下:

这两个函数都能创建一个真实存在于文件系统中的文件,filename指定了文件名,mode指定了文件的读取权限。尽量使用mkfifo(简单、规范)

mkfifo作用是在文件系统中创建一个文件,该文件提供FIFO功能,即命名管道。对文件系统来说,匿名管道不可见,它的作用仅限于在父进程和子进程两个进程间通信,而命名管道是一个可见文件,因此它可用于任何两个进程间通信,不管两个进程间是不是父子进程,也不管两个进程间有没有关系。

使用方法:

命名管道的使用方法与管道的使用方法基本相同,只是使用命名管道时,必须先调用open()将其打开。因为命名管道是存在于硬盘上的文件,而管道是存在于内存中的特殊文件。

注意:调用open打开命名管道的进程可能会被阻塞。但如果同时用读写方式(O_RDWR)打开,则一定不会阻塞,如果以只读方式(O_RDONLY)打开,则调用open函数的进程将会被阻塞直到有写方打开管道;同时以写方式(O_WRONLY)打开也会阻塞直到有读方打开管道。

时间: 2024-10-06 01:15:00

Linux下的进程通信方式(IPC)——管道通信的相关文章

linux下查找进程及终止进程操作的相关命令

使用linux操作系统,难免遇到一些软件"卡壳"的问题,这时就需要使用linux下强大的kill命令来结束相关进程.这在linux系统下是极其容易的事情,你只需要kill xxx即可,这里xxx代表与此软件运行相关的进程PID号.首先,我们需要使用linux下另外一个命令ps查找与进程相关的PID号:ps aux | grep program_filter_word1)ps a 显示现行终端机下的所有程序,包括其他用户的程序.2)ps -A 显示所有程序.3)ps c 列出程序时,显示

Linux下的进程与线程(二)—— 信号

Linux进程之间的通信: 本文主要讨论信号问题. 在Linux下的进程与线程(一)中提到,调度器可以用中断的方式调度进程. 然而,进程是怎么知道自己需要被调度了呢?是内核通过向进程发送信号,进程才得以知道的. Linux系统的进程之间是通过信号来通信的. 程序员在Shell上显式地发送信号使用的是kill命令,原型如下: kill -sigid [-]pid 其中, sigid指示的是信号的id,pid前若有-,则pid代表的为进程组id,否则pid代表的为进程id kill函数也有相同的作用

linux下对进程按照内存使用情况进行排序

linux下对进程按照内存使用情况进行排序的命令为:ps aux --sort -rss 详细解说参见 http://alvinalexander.com/linux/unix-linux-process-memory-sort-ps-command-cpu

linux下查看进程路径

在linux下查看进程大家都会想到用 ps -ef|grep XXX可是看到的不是全路径,怎么看全路径呢?每个进程启动之后在 /proc下面有一个于pid对应的路径例如:ps -ef|grep python显示:oracle    4431  4366  0 18:56 pts/2    00:00:00 python Server.py4431就是进程号到/proc/4431下,ls -l 会看到:总用量 0-r--r--r--    1 oracle   oinstall        0

Linux下的进程控制块—task_struct

Linux下的进程控制块 进程:程序的执行就是进程.也可以把进程看成一个独立的程序,在内存中有其对应的代码空间和数据空间,一个进程所拥有的数据和代码只属于自己.进程是资源分配的基本单位,也是调度运行的基本单位. 进程控制块(PCB)(系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程.系统利用PCB来控制 和管理进程,所以PCB是系统感知进程存在的唯一标志.进程与PCB是一 一对应的).是进程存在和运行的唯一标志,在Linux中用task_struct这个

linux下查看进程占用端口和端口占用进程命令

Linux下查看进程占用端口: 查看程序对应进程号:ps –ef|grep 进程名 REDHAT :查看进程号所占用的端口号:netstat –nltp|grep 进程号 ubuntu:查看进程占用端口号:netstat -anp|grep pid Linux下查看端口号所使用的进程号: 使用lsof命令: lsof –i:端口号

在 Linux 下查看进程运行时间的命令

对于一个 Linux 系统的新手,该如何在我的 Ubuntu 服务器上查看一个进程(或者,根据进程 id 去查看)已经运行了多久呢?下面兄弟连Linux培训分享给大家好方法. ···你需要使用 ps 命令来查看关于一组正在运行的进程的信息.ps 命令提供了如下的两种格式化选项. etime 显示了自从该进程启动以来,经历过的时间,格式为 [[DD-]hh:]mm:ss. etimes 显示了自该进程启动以来,经历过的时间,以秒的形式. 如何查看一个进程已经运行的时间? 你需要在 ps 命令之后添

Linux下java进程CPU占用率高分析方法

Linux下java进程CPU占用率高分析方法 在工作当中,肯定会遇到由代码所导致的高CPU耗用以及内存溢出的情况.这种情况发生时,我们怎么去找出原因并解决. 一般解决方法是通过top命令找出消耗资源高的线程id,利用strace命令查看该线程所有系统调用 1. 通过top命令找到可疑进程PID top - 09:37:18 up 70 days, 16:29, 2 users, load average: 1.13, 1.04, 0.97 Tasks: 105 total, 1 running

linux下的进程管理(进程的基本了解及查看pstree,ps,pgrep命令)

Linux下的进程管理 1.什么是进程?程序是静态的文件进程是运行中的程序的一个副本进程存在生命周期(准备期,运行期,终止期)2.进程状态 状态 定义 R(TASK_RUNNING) . 可执行状态(RUNNING,READY)running:正在被处理 ready: 在排队, cpu处理进程个数有限 S(TASK_INTERRUPTIBLE) 可唤醒状态 :在cpu上使用的时间超时,此时被打入休眠状态,随着程序的调用会被唤醒 D(TASK_UNINTERRUPTIBLE) 不可唤醒状态 T(T