linux进程间通信方式

进程在内核的协调下进行相互间的通讯,主要包括三种方式:信号管道套接口三大类。

1)信号

2)管道

3)套接字:消息队列、信号灯和共享内存

信号

信号是Unix 系统中的最古老的进程间通讯方式。它们用来向一个或多个进程发送异步事件信号。信号可以从键盘中断中产生,另外进程对虚拟内存的非法存取等系统错误环境下也会有信号产生。信号还被shell 程序用来向其子进程发送任务控制命令。

系统中有一组被详细定义的信号类型,这些信号可以由核心或者系统中其它具有适当权限的进程产生,如下所示
  1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
  5) SIGTRAP 6) SIGIOT 7) SIGBUS 8) SIGFPE
  9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
  13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
  18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
  22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
  26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
  30) SIGPWR
  常用信号其一是引起进程终止执行的SIGSTOP 信号,另一个是引起进程退出的SIGKILL 信号。至于其它信号,进程可以选择处理它们的具体方式。进程可以阻塞信号,如若不阻塞,则可以在自行处理此信号和将其转交核心处理之间作出选择。如果由核心来处理此信号,它将使用对应此信号的缺省处理方法。比如当进程接收到SIGFPE(浮点数异常,这个最开始学习编程可能都遇到过)时,核心的缺省操作是引起core dump 和进程的退出。信号没有固有的相对优先级。如果在同一时刻对于一个进程产生了两个信号,则它们将可能以任意顺序到达进程并进行处理。

并不是系统中每个进程都可以向所有其它进程发送信号:只有核心和超级用户具有此权限。普通进程只能向具有相同uid 和gid 的进程或者在同一进程组中的进程发送信号。如果信号的处理过程被设置成缺省则由内核来应付它。SIGSTOP 信号的缺省处理过程是
将当前进程的状态改变成为Stopped 并运行调度管理器以选择一个新进程继续运行。SIGFPE的缺省处理过程则是引起core dump 并使进程退出。当然,进程可以定义其自身的信号处理过程。

关于信号的编程,可以参考UNIX环境高级编程一书。

管道(包括FIFO管道)

  一般的Linux shell 程序都允许重定向,例如:ps aux | grep oracle。

在Linux 中,管道是通过指向同一个临时VFS inode 的两个file 数据结构来实现的,此VFS inode 指向内存中的一个物理页面。每个file 数据结构指向不同的文件操作例程向量,一个是实现对管道的写,另一个从管道中读。这样就隐藏了读写管道和读写普通的文件时系统调用的差别。当写入进程对管道写时,字节被拷贝到共享数据页面中,当读取进程从管道中读时,字节从共享数据页面中拷贝出来。Linux 必须同步对管道的访问。它必须保证读者和写者以确定的步骤执行,为此需要使用锁、等待队列和信号等同步机制。
    当写者想对管道写入时,它使用标准的写库函数。表示打开文件和打开管道的描叙符用来对进程的file 数据结构集合进行索引。Linux 系统调用使用由管道file 数据结构指向的write 过程。这个write 过程用保存在表示管道的VFS inode 中的信息来管理写请求。如果没有足够的空间容纳对所有写入管道的数据,只要管道没有被读者加锁。则Linux为写者加锁,并把从写入进程地址空间中写入的字节拷贝到共享数据页面中去。如果管道被读者加锁或者没有足够空间存储数据,当前进程将在管道inode 的等待队列中睡眠,同时调度管理器开始执行以选择其它进程来执行。如果写入进程是可中断的,则当有足够的空间或者管道被解锁时,它将被读者唤醒。当数据被写入时,管道的VFS inode 被解锁,同时任何在此inode 的等待队列上睡眠的读者进程都将被唤醒。读出数据的过程与写类似。

Linux 还支持命名管道(named pipe)也就是FIFO 管道,因为它总是按照先进先出的原则工作。第一个被写入的数据将首先从管道中读出来。和其它管道不一样,FIFO 管道不是临时对象,它们是文件系统中的实体并且可以通过mkfifo 命令来创建。进程只要拥有适当的权限就可以自由使用FIFO 管道。打开FIFO 管道的方式稍有不同。其它管道需要先创建(它的两个file 数据结构,VFSinode 和共享数据页面)而FIFO 管道已经存在,只需要由使用者打开与关闭。在写者进程打开它之前,Linux 必须让读者进程先打开此FIFO 管道;任何读者进程从中读取之前必须有写者进程向其写入数据。FIFO 管道的使用方法与普通管道基本相同,同时它们使用相同数据结构和操作。

套接口(消息队列、信号灯和共享内存)

  Linux 支持Unix 系统V(1983)版本中的三种进程间通讯机制。它们是消息队列、信号
灯以及共享内存。这些系统V IPC 机制使用共同的授权方法。只有通过系统调用将标志符传
递给内核之后,进程才能存取这些资源。

消息队列
 消息队列允许一个或者多个进程向它写入与读取消息。Linux 维护着一个msgque 消息队列链表,其中每个元素指向一个描叙消息队列的msqid_ds 结构。当创建新的消息队列时,系统将从系统内存中分配一个msqid_ds 结构,同时将其插入到数组中。

另外,Linux 保留有关队列修改时间信息,如上次系统向队列中写入的时间等。msqid_ds 包含两个等待队列:一个为队列写入进程使用而另一个由队列读取进程使用。由于Linux 严格限制可写入消息的个数和长度,队列中可能容纳不下这个消息。此时,此写入进程将被添加到这个消息队列的等待队列中,同时调用调度管理器选择新进程运行。当由消息从此队列中释放时,该进程将被唤醒。从队列中读的过程与此类似。

信号灯

信号灯最简单的形式是某个可以被多个进程检验和设置(test&set)的内存单元。这个检验与设置操作对每个进程而言是不可中断或者说是一个原子性操作;一旦启动谁也终止不了。检验与设置操作的结果是信号灯当前值加1,这个值可以是正数也可以是负数。根据这个操作的结果,进程可能可以一直睡眠到此信号灯的值被另一个进程更改为止。信号灯可用来实现临界区(critical region):某一时刻在此区域内的代码只能被一个进程执行。如果你有多个协作进程从一个数据文件中读取与写入记录。有时你可能需要这些文件访问遵循严格的访问次序。那么可在文件操作代码上使用一个初始值为1 的信号灯,它带有两个信号灯操作,一个检验并对信号灯值减1,而另一个检验并加1。第一个访问文件的进程将试图将信号灯值减1,如果获得成功则信号灯值变成了0。此进程于是开始使用这个数据文件,但是此时如果另一进程也想将信号灯值减1,则信号灯值将为-1,这次操作将会失败。它将挂起执行直到第一个进程完成对此数据文件的使用。此时这个等待进程将被唤醒,这次它对信号灯的操作将成功。

但是信号灯的使用可能产生一个严重的问题:死锁。当一个进程进入临界区时它改变了信号灯的值而离开临界区时由于运行失败或者被kill 而没有改回信号灯时,死锁将会发生。Linux 通过维护一组描叙信号灯数组变化的链表来防止该现象的发生。它的具体做法是让Linux 将把此信号灯设置为进程对其进行操作前的状态。这些状态值被保存在使用该信号灯数组进程的semid_ds 和task_struct 结构的sem_undo 结构中。

共享内存

共享内存允许一个或多个进程通过同时出现在它们虚拟地址空间中的内存来通讯。此虚拟内存的页面出现在每个共享进程页表中。但此页面并不一定位于所有共享进程虚拟内存的相同位置。和其它系统V IPC 对象的使用方法一样,对共享内存区域的访问是通过键和访问权限检验来控制的。一旦内存被共享,则再不会检验进程对对象的使用方式。它依赖于其它机制,如系统V 信号灯,来同步对共享内存的访问。

时间: 2024-11-05 13:10:07

linux进程间通信方式的相关文章

linux进程间通信方式及比较

进程间的通信方式: 1.管道(pipe)及有名管道(named pipe): 管道可用于具有亲缘关系进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信. 2.信号(signal): 信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致得. 3.消息队列(message queue): 消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可

linux 进程间通信方式

管道: 它包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信消息队列: 用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中用来保存消息的队列,它在系统内核中是以消息链表的形式出现.消息链表中节点的结构用msg声明.共享内存: 共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制.通常由一个进程创建一块共享内存区,其余进程对这块内存区进行 读写.得到共享内存有两种方式:映射/dev/mem

进程间通信方式

1.进程间通信方式 (1)windows进程间通信方式 1.文件映射: 2.共享内存(是文件映射的一种特殊情况): 3.邮件槽(mailslot)(点对点消息队列); 4.匿名管道: 5.命名管道: 6.剪贴板: 7.动态数据交换: 8.对象链接与嵌入: 9.远程过程调用: 10.动态链接库: 11.socket: 12.WM_COPYDATA. (2)linux进程间通信方式 1.管道 2.信号量 3.共享内存 4.消息队列 5.套接字 6.信号 (3)windows和linux共有的进程间通

嵌入式 Linux进程间通信(五)——进程间通信简介

嵌入式 Linux进程间通信(五)--进程间通信简介 一.进程间通信简介 Linux的进程通信方式基本上是从Unix平台上的进程通信方式继承而来的.在Unix发展过程中,贝尔实验室和BSD(加州大学伯克利分校的伯克利软件发布中心)是Unix发展的主要贡献者,但两者在进程间通信方面的侧重点有所不同.贝尔实验室对Unix早期的进程间通信方式进行了系统的改进和扩充,形成了 "system V IPC",通信进程局限在本地计算机内:BSD则跳过了进程通信局限在本地计算机的限制,形成了可以在计算

【转】进程间通信方式总结(windows 和linux)

平时看的书很多,了解的也很多,但不喜欢总结,这不昨天面试的时候被问到了进程间通信的方式,因为没有认真总结过,所以昨天答得不是特别好.现在将linux和windows的进程间通信方式好好总结一下. windows的进程间的通信方式有1.文件映射:2. 共享内存(是文件映射的一种特殊情况):3.邮件槽(mailslot)(点对点消息队列); 4.匿名管道:5:命名管道: 6. 剪贴板:7.动态数据交换:8.对象链接与嵌入:9.远程过程调用:10.动态链接库:11.socket:12.WM_COPYD

Linux进程间通信的几种方式总结--linux内核剖析(七)

进程间通信概述 进程通信的目的 传输数据 一个进程须要将它的数据发送给还有一个进程.发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程须要向还有一个或一组进程发送消息.通知它(它们)发生了某种事件(如进程终止时要通知父进程). 资源共享 多个进程之间共享相同的资源.为了作到这一点,须要内核提供锁和同步机制. 进程控制 有些进程希望全然控制还有一个进程的执行(如Debug进程),此时控制进程希望能够拦截还有一个进程的全部陷入和异常,并能够

Linux进程间通信的各种方式及其比较

进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区.但是,系统空间却是"公共场所",所以内核显然可以提供这样的条件.除此以外,那就是双方都可以访问的外设了.在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过"注册表"或其它数据库中的某些表项和记录交换信息.广义上这也是进程间通信的手段,但是一般都不把这算作"进程间通信&

linux 进程间通信的3种高级方式及优缺点

由于不同的进程运行在各自不同的内存空间中.一方对于变量的修改另一方是无法感知的.因此.进程之间的信息传递不可能通过变量或其它数据结构直接进行,只能通进程间通信来完成. 根据进程通信时信息量大小的不同,可以将进程通信划分为两大类型:控制信息的通信和大批数据信息的通信.前者称为低级通信,后者称为高级通信. 低级通信主要用于进程之间的同步.互斥.终止.挂起等等控制信息的传递. 高级通信主要用于进程间数据块的交换和共享 常见的高级通信有管道(PIPE).消息队列(MESSAGE).共享内存(SHARED

Linux进程间通信总结

Linux进程间通信总结 1. 管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: (1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: (2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): (3)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. (4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出