首页 > 代码库 > 1-4_基本概念_进程间通信及同步

1-4_基本概念_进程间通信及同步

内存映射

  调用系统函数mmap()的进程,会在其虚拟地址空间中创建一个新的内存映射。

  映射分为两类:

  1、文件映射:将文件的部分区域映射入调用进程的虚拟内存。映射一旦完成,对文件映射内容的访问则转化为对相应内存区域的字节操作。映射页面会按需自动从文件中加载。

  2、相映成趣的是并无文件与之对应的匿名映射,其映射页面的内容会被初始化为0。

  有某一进程所映射的内存可以与其他进程的映射共享。达成共享的方式有二:

  其一是两个进程都对某一文件的相同部分加以映射

  其二是由fork()创建的子进程自父进程处继承映射。

  当两个或多个进程共享的页面相同时,进程之一对页面内容的改动是否为其他进程所见呢?这取决于创建映射时所传入的标志参数。若传入标志参数为私有,则某进程对映射内容的修改对于其他进程是不可见的,而且这些改动也不会真的落实到文件上;若传入标志为共享,对映射内容的修改就会为其他进程所见,并且这些修改也会造成对文件的改动。

  内存映射用途很多,其中包括:以可执行文件的相应段来初始化进程的文本段、内存(内容填充为0)分配、文件I/O(即映射内存I/O)以及进程间通信(通过共享映射)。

进程间通信(IPC)机制

  读写磁盘文件中的信息是进程间通信的方法之一。可是,对许多程序来说,这种方法既慢又缺乏灵活性。因此,Linux提供了丰富的进程间通信(IPC)机制。

  信号(signal),用来表示事件的发生。

  管道(亦即shell用户所熟悉的“|”操作符)和FIFO,用于在进程间传递数据。

  套接字(socket),供同一台主机或是联网的不同主机上所运行的进程之间传递数据。

  文件锁定,为防止其他进程读取或更新文件内容,允许某进程对文件的部分区域加以锁定。

  消息队列,用于在进程间交换消息(数据包)。

  信号量(semaphore),用来同步进程动作。

  共享内存,允许两个及两个以上进程共享一块内存。当某进程改变了共享内存的内容时,其他所有进程会立即了解到这一变化。

信号

  尽管将信号视为IPC的方法之一,但其在其他方面的广泛应用则更为普遍。

  人们往往将信号称为“软件中断”。进程收到信号,就意味着某一事件或异常情况的发生。信号的类型很多,每一种分别标识不同的事件或情况。采用不同的整数来标识各种信号类型,并以SIGxxxx形式的符号名加以定义。

  内核、其他进程(只要具有相应的权限)或进程自身均可向进程发送信号。

  发生下列情况之一时,内核可向进程发送信号:

  用户键入中断字符(通常为Control-c)

  进程的子进程之一已经终止。

  由进程设定的定时器(告警时钟)已经到期。

  进程尝试访问无效的内存地址。

  在shell中,可使用kill命令向进程发送信号。在程序内部,系统调用kill()可提供相同功能。

  收到信号时,进程会根据信号采取如下动作之一:

  忽略信号。

  被信号“杀死”

  先挂起,之后再被专门信号唤醒。

  就大多数信号类型而言,程序可选择不采取默认的信号动作,而是忽略信号(当信号的默认处理行为并非忽略此信号时,会派上用场)或建立自己的信号处理器。

  信号处理器是由程序员定义的函数,会在进程收到信号时自动调用,根据信号的产生条件执行相应动作。

  信号从产生直至送达至进程期间,一直处于挂起状态。通常,系统会在接收进程下次调度时,将处于挂起状态的信号同时送达。如果接收进程正在运行,则会立即将信号送达。然而,程序可以将信号纳入所谓“信号屏蔽”以求阻塞该信号。如果产生的信号处于“信号屏蔽”之列,那么此信号将一直保持挂起状态,直至解除对该信号的组设。

1-4_基本概念_进程间通信及同步