管道是进程间通讯中最古老的方式,全部UNIX都提供此种通讯机制。管道有如下两种局限性:服务器
FIFO没有第二种局限性。
尽管有这两种局限性,半双工管道仍然是最经常使用的IPC形式。网络
管道由pipe()函数建立:dom
#include <unistd.h> int pipe(int fd[2]); 返回值:若成功,返回0,若出错,返回-1 参数fd返回两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。fd[1]的输出是fd[0]的输入。
一般,进程会先调用pipe,接着调用fork,从而建立从父进程到子进程的IPC通道,反之亦然。fork以后作什么取决于咱们想要的数据流的方向。
对于从父进程到子进程的管道:父进程关闭管道的读端(fd[0]),子进程关闭写端(fd[1])。
对于从子进程到父进程的管道:父进程关闭管道的写端(fd[1]),子进程关闭读端(fd[0])。socket
FIFO有时被称为命名管道,经过FIFO,不相关的进程也能交换数据。
FIFO由mkfifo()函数建立:函数
#include <sys/stat.h> int mkfifo(const char *path, mode_t mode); 返回值:若成功,返回0,若出错,返回-1
FIFO有以下两种用途:测试
消息队列是消息的连接表,存储在内核中,由消息队列标识符标识。
客户进程和服务器进程之间的双向数据流。操作系统
msgget用于建立一个新队列或打开一个现有队列,msgsnd将新消息添加到队列尾端,每一个消息包含一个正的长整型类型的字段、一个非负的长度(nbytes)以及实际数据字节数(对应于长度),msgrcv用于从队列中取消息。指针
#include <sys/msg.h> int msgget(key_t key, int flag); 返回值:若成功,返回消息队列ID,若出错,返回-1 int msgsnd(int msgid, const void *ptr, size_t nbytes, int flag); 返回值:若成功,返回0,若出错,返回-1 ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag); 返回值:若成功,返回消息数据部分的长度,若出错,返回-1
本质上,信号量是一个计数器,用于为多个进程提供对共享数据对象的访问。
维护信号量状态的是Linux内核操做系统而不是用户进程。code
通常说来,为了得到共享资源,进程须要执行下列操做:
共享存储容许两个或多个进程共享一个给定的存储区。由于数据不须要在客户进程和服务器进程之间复制,因此这是最快的一种IPC。
一般,信号量被用来实现对共享存储数据存取的同步。(也能够用记录锁或互斥量)
shmget得到一个共享存储标识符,shmctl对共享存储段执行多种操做,shmat将共享存储段链接到它的地址空间。
#include<sys/shm.h> int shmget(key_t key, size_t size, int flag); 返回值:若成功,返回共享存储ID;若出错,返回-1 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 返回值:若成功,返回0;若出错,返回-1 void *shmat(int shmid, const void *addr, int flag); 返回值:若成功,返回指向共享存储段的指针;若出错,返回-1
不一样计算机(经过网络相连)上的进程相互通讯的机制:网络进程间通讯(network IPC)。
套接字是通讯端点的抽象。正如使用文件描述符访问文件,应用程序用套接字描述符访问套接字。
socket建立一个套接字,shutdown禁止一个套接字的I/O。
#include <sys/socket.h> int socket(int domain, int type, int protocol); 返回值:若成功,返回文件(套接字)描述符,若出错,返回-1 int shutdown(int sockfd, int how); 返回值:若成功,返回0,若出错,返回-1