第15章 进程间通信(IPC)

许多程序都包含一个或多个进程.进程间通过共享数据或传递数据进行通信.举例来说,
两个人通过使用Unix的talk命令进行对话,他们就运行了两个进程,将数据从键盘和socket
传输到屏幕和socket

某些进程需要从多个源端接受数据,并将数据送到多个目的地.select和poll调用允许进程
等待多个文件描述符的输入

Unix提供了许多方法来进行数据在进程间传输,命名管道和共享内存是同一机器上的进程间
通信使用的两种技术.通信方法的区别在于他们的速度,所传输的消息类型,需要的范围,
限制访问权限的能力以及防止数据冲突的能力

文件锁是进程间使用的避免对文件访问冲突的技术

信号量是进程合作时所使用的系统级的变量.进程挂起等待另一进程改变信号量的值

纵观IPC:
fork-execv-argv, exit-wait
用于使用一组参数来调用某个程序,被调用函数将一个整形值返回给其调用者
面向消息,只能用在相关的进程中,且只能单机上使用

environ
系统调用exec通过environ这个全局变量自动将一组字符串复制给新程序,子进程无法改变
父进程的运行环境
面向对象,单向,只能用在相关进程,且只能在单机上使用

pipe
管道是由进程创建的单向数据流
面向流,单向,相关进程,单机

kill-signal
信号是一条从一个进程发往另一个进程的整形消息
面向消息,单向,进程必须有相同的用户ID,单机

Internet sockets
字节流通过socket进行传输,从一个进程到另一个进程
面向消息,面向流,双向传输,可以在无关进程中使用,可通过网络传输

Named Sockets
命名socket,使用文件名作为地址而不是主机名-端口号对
面向消息,面向流,双向传输,可以在无关进程中使用,单机

Named Pipes(FIFOs)
命令管道工作方式类似于常规管道,但是可以连接两个无关进程
单向,面向流,可以连接无关进程,单机

File Locks
文件锁
面向消息,多个无关进程可同时交互,单机

Shared Memory
每个进程有自己的数据空间,进程可以通过shmget shmat调用来创建可以被多个进程共享的内存段
面向随即访问,多个无关进程同时交互,单机

Semaphores
信号量是系统级的变量,程序之间可以通过信号量进行通信
面向消息,多个无关进程同时交互,单机

Message Queues
消息队列工作原理类似FIFO
面向消息,单向传输,单机

Files
文件可以被多个进程在同一时刻打开
面向随即访问,多个无关进程同时交互,网络文件系统(NFS)可以支持跨机器的多进程通信

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
* shm_ts.c
*
* the time server using shared memory, a bizarre application
*/

#include <stdio.h>
#include <sys/shm.h>
#include <time.h>

#define TIME_MEM_KEY 99
#define SEG_SIZE ((size_t)100)

main()
{
int seg_id;
char * mem_ptr, *ctime();
long now;
int n;

// create a shared memory segment
seg_id = shmget(TIME_MEM_KEY, SEG_SIZE, IPC_CREAT|0777);
if (seg_id == -1)
printf("error");

// attach to it and get a pointer to where it attaches
mem_ptr = shmat(seg_id, NULL, 0);
if (mem_ptr == (void *)-1)
printf("error");

// run for a minute
for (n = 0; n < 60; n++)
{
time(&now);
strcpy(mem_ptr, ctime(&now));
sleep(1);
}

// remove it
shmctl(seg_id, IPC_RMID, NULL);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
* shm_tc.c
*/

#include <stdio.h>
#include <sys/shm.h>
#include <time.h>

#define TIME_MEM_KEY 99
#define SEG_SIZE ((size_t)100)

main()
{
int seg_id;
char * mem_ptr, *ctime();
long now;

// create a shared memory segment
seg_id = shmget(TIME_MEM_KEY, SEG_SIZE, 0777);
if (seg_id == -1)
printf("error");

// attach to it and get a pointer to where it attaches
mem_ptr = shmat(seg_id, NULL, 0);
if (mem_ptr == (void *)-1)
printf("error");

printf("Time is %s", mem_ptr);

shmdt(mem_ptr);
}