常用进程通信方式
pipe
匿名管道是一种未命名的、单向管道,通常用来在一个父进程和一个子进程之间传输数据,filedes[0] 用于读,filedes[1] 用于写,事实上,从 filedes[0] 中读出的数据即是向 filedes[1] 中写入的数据。
POSIX实现了全双工的管道。
FIFO
fifo又称为命名管道,与进程间通信无关的通信机制,也能用于线程间通信。
XSI IPC
XSI结构体是内核中,进程间通信的数据对象,主要有三种IPC结构:消息队列,信号灯(semaphore),和共享内存。内核中每个IPC结构体都被一个非负整数标识,但这个标识符只能是IPC对象的内部名字,需要一个外部的命名机制来与相同的IPC对象交互,因此IPC对象都与一个KEY关联,这个KEY就是其外部名称。
那么,该如何确定 KEY 值呢?有三种方式:
-
合作进程对 KEY 值进行约定。这种方式的坏处是约定的 KEY 值可能己与某个 IPC 对象关联起来了。
-
由其中一个进程在创建 IPC 对象时将 KEY 值指定为 IPC_PRIVATE ,这样可以保证使用的 KEY 值的唯一性,但该进程却不得不通过某种途径(例如放入文件中)将获得的标识符传递给其它进程。
-
合作进程约定一个路径名和一个项目ID(1~255),然后使用 ftok 函数生成 KEY。
消息队列
消息队列的数据结构为链表形式
int msgget(key_t key, int flag);
如果KEY值没有和消息队列的数据结构关联,则该函数创建一个新的消息队列,否则,返回一个已有的消息队列的标识符。
创建了一个消息队列,然后进程终止,该消息队列是不会自动从系统中删除的。
信号灯(semaphore)
主要用于进程间同步资源,没仔细看。
共享内存
一个进程想要使用共享内存,首先得把它映射到自己的地址空间,使用 shmat 函数:
void *shmat(int shmid, const void *addr, int flag);
Socket
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。
int socket(int domain, int type, int protocol);
domain
- AF_INET IPv4 因特网域。
- AF_INET6 IPv6 因特网域。
- AF_UNIX UNIX 域。
- AF_UNSPEC 未指定,这是一个可以表达任何域的通配符。
type
- SOCK_DGRAM 固定长度,无连接,不可靠的消息。
- SOCK_RAW IP 协议的数据报接口。(在 POSIX.1 中是可选的)
- SOCK_SEQPACKET 固定长度,顺序式,面向连接的,可靠的消息。
- SOCK_STREAM 顺序式,面向连接的,双向的,可靠的字节流
protocol 参数代表协议号,如果给0,则使用对于给定 domain 和 type 下的默认协议。在 AF_INET 通信域下,SOCK_STREAM 类型的默认协议是 TCP (Transmission Control Protocol),而对于 SOCK_DGRAM 类型的默认协议则是 UDP (User Datagram Protocol)。
bind: 绑定socket与网络地址 connect:建立连接(面向连接) listen:服务器对socket进行监听 accept:接收一个请求,建立连接成功(三次握手完成),返回socket描述符,与客户端描述符建立一个tcp连接
UNIX 域的socket
UNIX 域同时支付流和数据报接口,不同于英特网域,这两种接口都是可靠的。