进程间的通信简介
一、进程间的通信
1、linux下进程间通信概述
进程间通信就是在不同进程之间传播或交换信息。
进程间通信(IPC interprocess communication)主要包括以下几种:
1、管道及有名管道
管道:具有亲缘关系进程间的通信
有名管道:可以在许多不相关的进程之间进行通信
2、信号(signal):用于通知接收进程有某种事件发生
3、报文(message)队列(消息队列):消息队列是消息的链接表
4、共享内存:使多个进程可以访问同一块内存空间
5、信号量:作为进程间以及同一进程不同线程之间的同步手段
6、套接字(socket):可用于不同机器之间的进程间通信。
2、管道通信(连接一个进程的标准输入到另一个进程的标准输出的方法)
1、管道
当进程创建一个管道时,系统内核设置了两个管道可以使用的文件描述符。(write,read)
特点:
管道是半双工的
只能用于具有亲缘关系的进程
单独构成一种独立的文件系统
数据的读出和写入:(FIFO)写入的内容每次都添加在管道缓冲区的末尾,
并且每次都是从缓冲区的头部读出数据
(1)管道的创建
pipe()函数用于创建无名管道,当管道创建时会创建fd[0]和fd[1]两个文件描述符
函数原型:
int pipe(int fd[2])
fd[2]: fd[0]固定用于读管道,fd[1]固定用于写管道
返回值:成功——返回0; 失败——返回-1
(2)管道的关闭
close(): 关闭了fd[0]和fd[1]就关闭了管道
(3)管道的读/写操作
写操作:
close(fd[0]);//关闭读取端
sleep(3);//确保已关闭相应的读描述符
write(fd[1],string,strlen(string));//通过写端将字符串写入管道
close(fd[1]);//关闭写描述符
读操作:
close(fd[1]);//关闭写入端
read(fd[0],readbuffer,sizeof(readbuffer));//从管道中读取字符串
printf("%s",readbuffer);
close(fd[0]);//关闭读描述符
2、标准流管道
创建管道:FILE * popen(char * command, char * type)
command: 启动shell后执行的命令
type: 管道中数据流的方向w/r,不能同时为读和写(type只以第一个字符代表的方式打开)。
关闭管道:int pclose(FIFE * stream);
读写:fputs函数和fputc函数
3、有名管道(FIFO管道)
有名管道指创建的管道文件是有文件名的,任何程序都可以通过文件名或路径名与这个文件挂上钩
FIFO管道不是一个临时对象,而是在文件系统中作为一个特殊的设备文件而存在的实体。
(1)FIFO的创建
FIFO文件即”先进先出“文件,
创建方法:
mknod MYFIFO p
mkfifo a = rw MYFIFO
以上的两个命令执行同样的操作,但其中有一点不同。mkfifo提供一个在创建之后改变FIFO文
件存取权限的途径,而mknod需要调用命令chmod。
mkfifo函数原型:
int mkfifo(const char * pathname, mode_t mode)
pathname: 将在文件系统中创建的一个专用文件
mode:规定FIFO的读/写权限
返回值:成功——返回0;失败——返回-1
(2)使用
有名管道可以用于任意两个进程间通信。由于管道都是单向的,因此双方通信需要两个管道。
示例:
写入数据:
mkfifo(namedpipe, 0777);//创建管道
pipe_fd = open(namedpipe, O_WRONLY);//以只写方式打开
sour_fd = open(sourtxt, O_RDONLY);//以只读方式打开源文件
bytes_read = read(sour_fd, buffer, sizeof(buffer));
buffer[bytes_read] = '\0';
while(bytes_read > 0) {//向管道写入数据
write(pipe_fd, buffer, sizeof(buffer));
bytes_read = read(sour_fd, buffer, sizeof(buffer));
buffer[bytes_read] = '\0';
}
读取数据:
pipe_fd = open(namedpipe, O_RDONLY);//以只读方式打开管道
dest_fd = open(desttxt, O_WRONLY|O_CREAT, 0664);
bytes_read = read(pipe_fd, buffer, sizeof(buffer));
do {//从管道读出数据到目标文件
count = read(pipe_fd, buffer, sizeof(buffer));
write(dest_fd, buffer,sizeof(buffer));
} while (count > 0)
三、共享内存通信
共享内存:最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是 ——
同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的
更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制(互斥锁、信号量)
对于系统V共享内存,主要有以下几个API:shmget(),shmat(),shmdt(),shmctl()
shmget(): 获取共享内存区域的ID,不存在指定共享区域则创建相应的区域
shmat():把共享内存区域映射到调用进程的地址空间中去
shmdt():接触进程对共享内存区域的映射
shmctl():实现对共享内存区域的控制操作
函数原型:
int shmget(key_t key, int size, int shmflg)
key:IPC结构的键值,通常取常量IPC_PRIVATE
size: 共享内存区的大小(新建时必须制定size大小,引用已有的区域,则size设为0)
shmflg:权限位,可以用八进制表示
返回值:成功——返回共享内存区域标识符ID,即shmid;出错——返回-1
char * shmat(int shmid, const void * shmaddr, int shflg)
shmid: 通过shmget得到的共享内存区标识符ID
shmaddr:将共享内存映射到指定位置。0 —— 表示映射到调用进程的地址空间
shmflg: 选项位,设置权限,常用选项是SHM_RDONLY(只读),默认为0(读写)。
返回值:成功——返回被映射的段地址,失败——返回-1
(使用以上两个函数即可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读/写命令对
其进行操作)
int shmdt(const void * shmaddr)
shmaddr: 表示被映射的共享内存段地址
返回值:成功——返回0;失败——返回-1
转载于:https://blog.51cto.com/tobeys/1720014