-- 需求背景
进程间能共享或传递数据就算是进程间通信。
进程间能共享或传递数据就算是进程间通信。
IPC手段 | 含义 | 通信方式 |
---|---|---|
共享内存(Shared Memory) | 多个进程共享一块物理内存 | 直接通信 |
文件(File) | 多个进程可访问同一文件 | 间接通信 |
直接通信:两个进程间不需要通过内核的中转,就可以相互传递信息
间接通信:两个进程间通过系统调用和内核的中转,来相互传递消息
除了共享内存机制,其它IPC机制都会经过内核的中转。
进程间能共享或传递数据就算是进程间通信。
IPC手段 | 含义 | 通信方式 |
---|---|---|
管道(Pipe) | 单方向传输字节流 | 间接通信 |
消息队列(Message Queue) | 通过队列中收/发消息 | 间接通信 |
信号(Signal) | 异步发送信号给进程处理 | 间接通信 |
套接字(Socket) | 多/单机进程间网络通信 | 间接通信 |
进程间能共享或传递数据就算是进程间通信。
Remote Procedure Call,RPC = send + recv
进程间能共享或传递数据就算是进程间通信。
进程间能共享或传递数据就算是进程间通信。
管道(pipe)
管道(pipe)
int pipe(int pipefd[2])
管道(pipe)
管道(pipe)
$ gcc -o ex1 ex1.c
$ ./ex1
parent
write: the 0 message.
...
children
read: the 0 message.
...
建议:同学们可在课后在自己的开发环境中实践一下
Shell也提供了管道 ,只需使用一根竖线 "|" 连接两个命令即
rCore-Tutorial-v3 on ch7
❯ cat README.md | grep rcore
$ git clone https://github.com/rcore-os/rCore-Tutorial-v3.git
...
* [x] expand the fs image size generated by `rcore-fs-fuse` to 128MiB
这种管道称为匿名管道,它对于编写灵活的命令行脚本非常方便。
但:不支持任意两个进程间的通信
在shell下,还支持使用mkfifo命令创建命名管道(named pipe),也称为FIFO,它支持任意进程间的数据通信。
$ mkfifo name.fifo
$ ls -l name.fifo # 文件类型为p
prw-r--r-- 1 chyyuu chyyuu 0 4月 14 20:19 name.fifo
注:无名管道与有名管道都属于单向通信机制。有名管道与无名管道不同的是,有名管道可以支持任意两个进程间的通信。
命名管道是阻塞式的单向通信管道,任意一方都可以读、写,但是只有读、写端同时打开了命名管道时,数据才会写入并被读取。
shell A
$ echo README > name.fifo #写命名管道阻塞
shell B
$ cat name.fifo
但:字节流形态,不支持任意两个进程间的双向通信
消息队列(Message Queue)
消息的结构
struct msgbuf {
long mtype; /* 消息的类型 */
char mtext[1]; /* 消息正文 */
};
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
参数:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
返回值:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
那么如何获取key值?
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
参数:
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
int msgrcv(int msgid, void *msg_ptr, size_t msgsz,long int msgtype, int msgflg);
int msgrcv(int msgid, void *msg_ptr, size_t msgsz,long int msgtype, int msgflg);
返回值:
$ gcc ex1.c
$ ./a.out
建议:同学们可在课后在自己的开发环境中实践一下
共享内存 shared memory, shmem
注:需要信号量(后续介绍)等机制协调共享内存的访问冲突
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size,int shmflg);
返回值:成功:共享内存标识符; 失败:-1。
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
将一个共享内存段映射到调用进程的数据段中。简单来理解,让进程和共享内存建立一种联系,让进程某个指针指向此共享内存。
返回值:
void *shmat(int shmid, const void *shmaddr, int shmflg);
$ gcc writer.c -o w
$ gcc reader.c -o r
$ ./w
Writer: copy data to shared-memory
$ ./r
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0xdf20482b 1 chyyuu 666 512 0
data = [ How are you, mike: from Writer ]
deleted shared-memory
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
建议:同学们可在课后在自己的开发环境中实践一下
之前的IPC聚焦在数据传输上
信号(Signal)
问题:
Ctrl+C
为什么可以结束进程?信号命名
信号发送方
信号发送方
信号接收进程的处理方式
Linux有哪些信号? -- 62个
Linux有哪些信号? -- 62个
Linux常用信号
信号应用编程
实现机制
实现机制
另外一种定义 https://zhidao.baidu.com/question/1695485023365050948.html 直接通信为了实现直接通信,要有发送和接收的ID进程必须正确地命名对方send( P, message) - 发送信息到进程P通信链路的属性自动建立链路一条链路恰好对应一对通信进程每对进程之间只有一个链接存在链接可以是单向的,但通常为双向的 间接通信为了实现间接通信,要发送到共享区,发送方和接收方都不关注具体的另一方是谁定向从消息队列接收消息:每个消息队列都有一个唯一的ID只有他们共享了一个消息队列,进程才能通信通信链路的属性
https://zhuanlan.zhihu.com/p/268389190 Linux进程间通信——消息队列
https://zhuanlan.zhihu.com/p/147826545 Linux系统编程之进程间通信:共享内存
Ref: Understanding the Linux Kernel Signals and Inter-Process Communication https://compas.cs.stonybrook.edu/~nhonarmand/courses/fa14/cse506.2/slides/ipc.pdf