Linux进程间通信

时间:2021-05-09 19:08:29

一、进程间通信概述进程通信有如下一些目的:

A、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间

B、共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。

C、通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。

D、资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。

E、进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。Linux 进程间通信(IPC)以下以几部分发展而来:早期UNIX进程间通信、基于System V进程间通信、基于Socket进程间通信和POSIX进程间通信。UNIX进程间通信方式包括:管道、FIFO、信号。System V进程间通信方式包括:System V消息队列、System V信号灯、System V共享内存、POSIX进程间通信包括:posix消息队列、posix信号灯、posix共享内存。

现在linux使用的进程间通信方式:

(1)管道(pipe)和有名管道(FIFO)

(2)信号(signal)

(3)消息队列

(4)共享内存

(5)信号量

(6)套接字(socket)

二、管道通信

普通的Linux shell都允许重定向,而重定向使用的就是管道。例如:ps | grep vsftpd .管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的道端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。管道主要用于不同进程间通信。

管道创建与关闭创建:

一个简单的管道,可以使用系统调用pipe()。它接受一个参数,也就是一个包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。

管道的读写:

管道主要用于不同进程间通信。实际上,通常先创建一个管道,再通过fork函数创建一个子进程。

管道读写注意事项:可以通过打开两个管道来创建一个双向的管道。但需要在子理程中正确地设置文件描述符。必须在系统调用fork()中调用pipe(),否则子进程将不会继承文件描述符。当使用半双工管道时,任何关联的进程都必须共享一个相关的祖先进程。因为管道存在于系统内核之中,所以任何不在创建管道的进程的祖先进程之中的进程都将无法寻址它。而在命名管道中却不是这样。

三、信号

信号概述信号是软件中断。信号(signal)机制是Unix系统中最为古老的进程之间的能信机制。它用于在一个或多个进程之间传递异步信号。很多条件可以产生一个信号。

A、当用户按某些终端键时,产生信号。在终端上按DELETE键通常产生中断信号(SIGINT)。这是停止一个已失去控制程序的方法。

B、硬件异常产生信号:除数为0、无效的存储访问等等。这些条件通常由硬件检测到,并将其通知内核。然后内核为该条件发生时正在运行的进程产生适当的信号。例如,对于执行一个无效存储访问的进程产生一个SIGSEGV。

C、进程用kill(2)函数可将信号发送给另一个进程或进程组。自然,有些限制:接收信号进和发送信号进程的所有都必须相同,或发送信号进程的的所有者必须是超级用户。

D、用户可用Kill(ID 值)命令将信号发送给其它进程。此程序是Kill函数的界面。常用此命令终止一个失控的后台进程。

E、当检测到某种软件条件已经发生,并将其通知有关进程时也产生信号。这里并不是指硬件产生条件(如被0除),而是软件条件。例如SIGURG(在网络连接上传来非规定波特率的数据)、SIGPIPE(在管道的读进程已终止后一个进程写此管道),以及SIGALRM(进程所设置的闹钟时间已经超时)。

内核为进程生产信号,来响应不同的事件,这些事件就是信号源。主要信号源如下:(1)异常:进程运行过程中出现异常

(2)其它进程:一个进程可以向另一个或一组进程发送信号;

(3)终端中断:Ctrl-c,Ctro-\等;

(4)作业控制:前台、后台进程的管理;

(5)分配额:CPU超时或文件大小突破限制;

(6)通知:通知进程某事件发生,如I/O就绪等;

(7)报警:计时器到期;

常用的信号:SIGHUP:从终端上发出的结束信号;SIGINT:来自键盘的中断信号(Ctrl+c)SIGQUIT:来自键盘的退出信号;SIGFPE:浮点异常信号(例如浮点运算溢出);SIGKILL:该信号结束接收信号的进程;SIGALRM:进程的定时器到期时,发送该信号;SIGTERM:kill命令生出的信号;SIGCHLD:标识子进程停止或结束的信号;SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止扫行信号

可以要求系统在某个信号出现时按照下列三种方式中的一种进行操作。

(1)忽略此信号。大多数信号都可使用这种方式进行处理,但有两种信号却决不能被忽略。它们是:SIGKILL和SIGSTOP。这两种信号不能被忽略的,原因是:它们向超级用户提供一种使进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号(例如非法存储访问或除以0),则进程的行为是示定义的。

(2)捕捉信号。为了做到这一点要通知内核在某种信号发生时,调用一个用户函数。在用户函数中,可执行用户希望对这种事件进行的处理。如果捕捉到SIGCHLD信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用waitpid以取得该子进程的进程ID以及它的终止状态。

(3)执行系统默认动作。对大多数信号的系统默认动作是终止该进程。每一个信号都有一个缺省动作,它是当进程没有给这个信号指定处理程序时,内核对信号的处理。有5种缺省的动作:

(1)异常终止(abort):在进程的当前目录下,把进程的地址空间内容、寄存器内容保存到一个叫做core的文件中,而后终止进程。

(2)退出(exit):不产生core文件,直接终止进程。

(3)忽略(ignore):忽略该信号。

(4)停止(stop):挂起该进程。

(5)继续(contiune):如果进程被挂起,刚恢复进程的动行。否则,忽略信号。