进程间通信目的(通信)
- 资源共享: 多个进程之间共享同样的资源
- 派发任务: 如进程池
管道
- 概念: 从一个进程连接到另一个进程的一个数据流称为一个“管道"(本质是文件)
- 特点: 单向通信(半双工), 内存级文件(生命周期随进程)
- 种类: 匿名管道, 命名管道
- 访问控制
- 写快, 读慢, 写满不能在写了
- 写慢, 读快, 管道没有数据的时候,读必须等待
- 写关, 读0, 标识读到了文件结尾
- 读关, 写继续写, OS终止写进程
匿名管道
- 特点: 匿名
- 应用: 父子进程的通信
匿名管道的使用
int pipe(int fd[2]);
功能: 创建匿名管道
头文件: <unistd.h>
参数: fd:文件描述符数组. (fd[0]表示读端, fd[1]表示写端)
返回值:成功返回0,失败返回错误代码
//fd[2]:输出型参数,期望通过调用它, 得到被打开的文件fd
命名管道
- 特点:命名(在磁盘上构建了文件名,但本质还是内存文件)
- 应用: 不同进程之间的通信(进程打开目录下同一文件)
命名管道的使用
命令行创建
创建管道: mkfifo filename
删除管道文件: unlink 文件名(name_pipe) 也可以 rm 文件名
程序中创建: int mkfifo(const char* pathname , mode_t mdoe)
头文件: <sys/types.h> <sys/stat.h>
返回值: 创建成功: 0 创建失败: -1
参数:
pathname: 管道名称
mode: 权限码(如666)
共享内存
共享内存的使用
key_t ftok(const char *pathname, int proj_id);
功能:用于创建共享内存、消息队列和信号量等 IPC 对象的键值
参数
pathname:路径名
proj_id:项目标识符
返回值:成功返回一个键值,失败返回-1
//将 pathname 所指向文件的索引节点号(inode number)与 proj_id 结合起来,
//生成一个唯一的键值,这个键值可以用作创建或获取 IPC 对象的标识符。
int shmget(key_t key, size_t size, int shmflg);
功能:用来创建共享内存
参数:
key:这个共享内存段名字
size:共享内存大小
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将共享内存段连接到进程地址空间
参数
shmid: 共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。
公式:shmaddr -(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
int shmdt(const void *shmaddr);
功能:将共享内存段与当前进程脱离
参数:
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:用于控制共享内存
参数:
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1
注: 当进程运行结束, 我们的共享内存还存在, IPC资源的生命周期随内核
命令行删除:
查看共享内存: ipcs -m
删除共享内存: ipcrm -m shmid (手动)
对比
匿名管道与命名管道
- 同: 它们都是内存级别文件, 生命周期随进程
- 异:
- 特点: 匿名(磁盘上无对应的映像). 命名(磁盘上构建了文件名)
- 通信方式: 匿名管道通过子进程继承方式, 命名管道通过打开目录下的同一文件
管道与共享内存
- 速度:
- 共享内存速度最快(无需多次拷贝, 直接向共享内存写数据).一方写另一方直接能看到
- 管道(文件)要通过系统调用往文件里写数据与读数据 + 自己要定义缓冲区
- 生命周期
- 共享内存生命周期随内核
- 管道生命周期随进程
- 访问控制: 共享内存没有, 管道有