Interprocess Communication

Table of Contents

1 IPC简介

在进程之间交换信息的方法,称为IPC(Interprocess Communication)。

IPC_summary.png

Figure 1: Summary of UNIX System IPC

参考:
Advanced Programming in the UNIX Environment, 3rd Edition, Chapter 15 Interprocess Communication
UNIX网络编程第2卷:进程间通信(第2版)

1.1 fork、exec和exit对IPC对象的影响

IPC_effect_of_calling_fork_exec.png

Figure 2: 调用fork、exec和exit对IPC对象的影响

参考:UNIX网络编程第2卷:进程间通信(第2版),1.5 节 fork、exec和exit对IPC对象的影响

2 System V IPC vs. POSIX IPC

消息队列、信号量和共享内存是三种重要的IPC方式:

  • Message queues can be used to pass messages (formatted data streams) between processes.
  • Semaphores permit multiple processes to synchronize their actions.
  • Shared memory enables multiple processes to share the same region (called a segment) of memory. Since access to user-space memory is a fast operation, shared memory is one of the quickest methods of IPC: once one process has updated the shared memory, the change is immediately visible to other processes sharing the same segment.

对于消息队列、信号量和共享内存这三种IPC方式,分别都有两套可用的设施:System V IPC和POSIX IPC。

System V IPC是20世纪70年代后期在贝尔实验室一个称为“Columbus Unix”的内部版本中开发的,System V IPC大约于1983年随System V加入到商业Unix系统中。由于System V IPC定义在Single UNIX Specification的XSI扩展中,所以 System V IPC也被称作XSI IPC

IPC_System_V_functions.png

Figure 3: Summary of System V IPC functions

IPC_POSIX_functions.png

Figure 4: Summary of POSIX IPC functions

2.1 System V IPC实例:Shared Memory

下面是Shared Memory(System V IPC)的一个例子,有两个程序shm_server和shm_client,一个写共享内存一个读共享内存。
源码如下:

/* shm_server: 往共享内存中写入27个字节:全部小写的英文字母加上NULL */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define SHMSZ     27      /* Size of shared memory */
#define IPCKEY    23456   /* Key of shared memory */

int main()
{
    key_t key = IPCKEY;
    int shmid;            /* Identifier of shared memory */
    char *shm, *s;
    char c;

    /* Create the shared memory segment. */
    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Attach the shared memory segment. */
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    s = shm;

    /* Write [abc...xyz] to shared memory. */
    for (c = 'a'; c <= 'z'; c++) {
        *s++ = c;
    }
    *s = NULL;

    return 0;
}
/* shm_client: 打印共享内存中的内容直到遇到NULL */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define IPCKEY    23456   /* Key of shared memory */

int main() {
    key_t key = IPCKEY;
    int shmid;
    char *shm, *s;

    /* Locate the shared memory segment. */
    if ((shmid = shmget(key, 0, 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Attach the shared memory segment to our data space. */
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    /* Read memory util meet NULL. */
    for (s = shm; *s != NULL; s++) {
        putchar(*s);
    }
    putchar('\n');

    return 0;
}

测试如下:

$ ./shm_server      # shm_server仅是创建共享内存并写入内存,没有输出
$ ./shm_client
abcdefghijklmnopqrstuvwxyz

说明:上面两个程序结束后,并没有删除共享内存,我们可以通过ipcs查看到shm_server创建的共享内存。如:

$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00061de2 513245204  root       666        28         0                       
0x435dce61 23560214   root       666        4          1                       
0x435dce60 23592983   root       666        8024       1                       
0x741cc1a0 48889886   root       666        28244      0                       
0x741cc1a1 48922655   root       666        6          0                       
0x741cc1a2 48955424   root       666        6          0                       
0x00005ba0 738689112  cig01      666        27         0                

上面输出中,最后一条记录就是shm_server创建的共享内存(程序中指定的key为23456,对应的十六进制为0x00005ba0)。

2.2 System V IPC和POSIX IPC的优缺点

POSIX IPC有下面优点:

  • POSIX IPC的接口更加简单,使用起来更加方便。
  • POSIX IPC模型使用“POSIX IPC名字”进行标识,使用xx_open/xxx_close/xx_unlink来操作它们,这和UNIX的文件模型更一致。
  • POSIX IPC对象是“引用计数”的,支持持续时间“随进程”的方式(没有进程访问它了就自动删除);而System V IPC没有访问计数,持续时间是“随内核”的,很可能出现由于用户疏忽或程序异常导致IPC资源一直没有释放。

System V IPC的主要优点是它的可移植性更好 ,这体现在几个方面:

  • 几乎所有的UNIX实现都支持System V IPC,而POSIX IPC在老的或某些新的UNIX中可能没有实现。
  • “POSIX IPC名字”可能是真正的路径名,也可能不是,不同系统的实现可能不同,用POSIX IPC编写可移植的代码需要做额外的工作。而System V IPC没有这个问题。

参考:
The Linux Programming Interface, 51.2 Comparison of System V IPC and POSIX IPC
UNIX网络编程第2卷:进程间通信(第2版),2.2 IPC名字(讨论了关于“POSIX IPC名字”的移植性问题)


Author: cig01

Created: <2013-01-05 Sat 00:00>

Last updated: <2017-01-16 Mon 14:55>

Creator: Emacs 25.1.1 (Org mode 9.0.7)