进程控制和通信(二)

本文详细介绍了Linux中的进程间通信(IPC)方式,重点关注匿名管道和具名管道(FIFO)。文章阐述了匿名管道的创建、读写特性,包括其循环队列性质和半双工通信模式。同时,介绍了具名管道的创建、读写方式,以及其作为文件系统中真实存在的文件,但数据存储在内核缓存的特点。最后,讨论了全双工通信的实现以及管道的阻塞与非阻塞行为。
摘要由CSDN通过智能技术生成

我们经常可以看到, 诸如Chrome/VSCode之类的程序打开运行的时候, 可以在后台看到会有多个相关进程启动. 同一个程序启动的不同进程间, 必然存在合作关系, 那么这些进程之间是如何合作的呢?

IPC

进程间通信也叫做IPC(InterPorcess Communication). 进程间通信可以让不同的进程共同合作完成某些任务.

不同进程的虚拟内存空间可能会映射到不同的物理内存空间, 但是虚拟内存空间中的虚拟内核空间都会映射到相同的物理内核空间, 因为一般认为系统的内核只有一个.

https://z3.ax1x.com/2021/04/23/cXVQnx.png

不同进程映射到相同物理内核空间

所以, 为了剔除用户空间映射不一致的影响, 可以在内核空间操作, 只要在内核空间中开辟相同的物理内存, 供不同进程访问, 那么就可以做到IPC.

https://z3.ax1x.com/2021/04/23/cXVKj1.png

内核提供共享区域做IPC

或者, 可以使用文件做IPC. 不同进程只要能够指向相同的文件, 再加上对文件的访问控制, 就可以在不同进程间通过文件系统通信.

https://z3.ax1x.com/2021/04/23/cXVucR.png

使用文件系统做IPC

再或者, 可以通过我们熟知的网络链接做IPC.

https://z3.ax1x.com/2021/04/23/cXZfRH.png

通过网络做IPC

匿名管道

C提供了pipe函数用于创建管道. pipe是内核在内核空间提供的一段缓存区.

pipe

1
2
3
4
5
/* Create a one-way communication channel (pipe).
   If successful, two file descriptors are stored in PIPEDES;
   bytes written on PIPEDES[1] can be read from PIPEDES[0].
   Returns 0 if successful, -1 if not.  */
extern int pipe (int __pipedes[2]) __THROW __wur;

pipe输入参数是包含两个pipe描述符的二元数组. pipe执行失败返回-1, 执行成功则返回0, 同时第一个pipe描述符PIPEDES[0]指向pipe的读端, 第二个pipe描述符PIPEDES[1]指向pipe的写端. 调用pipe之后我们拿到了读写端口, 然后再调用fork函数, 现在父子进程都拿到了pipe的读写端口.

https://z3.ax1x.com/2021/04/23/cXUIZ8.png

父子进程都拿到了pipe的读写端口

Create a one-way communication channel (pipe).

函数注释中已经说明, pipe是一个one-way communication channel, 只能一个通路, 也就是说只能从一端进一端出, 所以在父子进程必须确定谁来发送, 谁来接收, 不用的端口需要关闭.

下面的例子使用子进程写, 父进程读:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

int main()
{
int pipef[2] = {0, 0};

int ret = pipe(pipef);
if (ret &lt; 0)
{
    printf("create pipe error\n");
    return -1;
}
printf("pipef[0] %d, pipef[1] %d\n", pipef[0], pipef[1]);

int pid = fork();
if (pid &lt; 0)
{
    printf("fork error\n");
    return -1;
}
else if (pid == 0)
{
    //close read
    close(pipef[0]);
    char msg[128] = "pipe message.";
    int count = 5;
    while(count-- &gt; 0)
    {
        strcat(msg, "+");
        int write_stat = write(pipef[1], msg, sizeof(msg));
        printf("child send[%d]: %s\n", write_stat, msg);
        // sleep(1);
    }
    printf("write complete\n");
    close(pipef[1]);
}
else
{
    //close write
    close(pipef[1]);
    char msg[1024] = {0};
    int count = 5;
    while(count-- &gt; 0)
    {
        int read_stat = read(pipef[0], msg, sizeof(msg));
        if
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值