linux进程----匿名管道和命名管道

14 篇文章 0 订阅
13 篇文章 0 订阅

linux进程----匿名管道和命名管道

在Linux中,管道是用于进程间通信的一种机制,可以分为两种类型:匿名管道(也称为匿名fifo)和命名管道(也称为命名fifo或named pipe)。

匿名管道(Anonymous Pipe)

匿名管道是一种半双工的通信机制,它允许一个进程的输出直接传递给另一个进程的输入。匿名管道通常由管道符(|)在命令行中创建。

  1. 创建匿名管道
    command1 | command2
    
    在这个例子中,command1 的输出会被传递给 command2 的输入。
  2. 特点
    • 匿名管道没有名称,因此无法在文件系统中直接访问。
    • 它只能用于父子进程之间,或者兄弟进程之间(通过fork)。
    • 它是一次性的,即一旦两个进程完成通信,管道就会消失。在这里插入图片描述

命名管道(Named Pipe)

命名管道是一种全双工的通信机制,它允许多个进程之间进行通信。命名管道在文件系统中有一个名称,可以像文件一样被访问。

  1. 创建命名管道
    mkfifo filename
    
    或者在命令行中使用:
    command1 | tee >(mkfifo filename) | command2
    
    在这个例子中,command1 的输出被传递给 tee 命令,后者将输出同时写入一个匿名管道和一个文件(这里通过命名管道)。command2 的输入则来自这个匿名管道。
  2. 特点
    • 命名管道在文件系统中有一个名称,可以在多个进程之间共享。
    • 它允许全双工通信,即可以同时进行读写操作。
    • 它具有持久性,即即使创建它的进程已经结束,管道仍然存在,直到最后一个使用它的进程结束。在这里插入图片描述

使用示例

  • 匿名管道
    ls | grep "file"
    
    在这个例子中,ls 命令的输出会被传递给 grep 命令的输入。
  • 命名管道
    mkfifo myfifo
    cat > myfifo
    cat < myfifo
    
    在这个例子中,首先创建了一个命名管道 myfifo。然后,一个进程通过 cat > myfifo 将数据写入管道,另一个进程通过 cat < myfifo 从管道中读取数据。
    这两种管道机制都是Linux中常用的进程间通信方式,它们各有优缺点,可以根据具体需求选择合适的方法。

匿名管道(Anonymous Pipe)

匿名管道是一种简单的进程间通信机制,它允许一个进程的输出直接传递给另一个进程的输入。匿名管道是半双工的,这意味着数据只能单向传输。

工作原理:
  1. 创建匿名管道
    • 当你在命令行中使用管道符 | 连接两个命令时,实际上是在创建一个匿名管道。
    • 第一个命令的输出被重定向到匿名管道中,而匿名管道的输出则被重定向到第二个命令的输入。
  2. 数据传输
    • 第一个命令开始执行,其输出被写入匿名管道。
    • 第二个命令开始执行,它从匿名管道中读取数据作为输入。
  3. 管道消失
    • 一旦两个命令执行完毕,匿名管道就会被销毁。
特点:
  • 单向通信:匿名管道只能用于单向通信,即一个进程的输出传递给另一个进程的输入。
  • 半双工:数据只能单向传输,不能同时读写。
  • 一次性的:匿名管道是一次性的,一旦两个进程完成通信,管道就会消失。
  • 父子进程或兄弟进程间通信:匿名管道通常用于父子进程之间或通过fork创建的兄弟进程之间。

命名管道(Named Pipe)

命名管道是一种全双工的进程间通信机制,它允许多个进程之间进行通信。命名管道在文件系统中有一个名称,可以像文件一样被访问。

工作原理:
  1. 创建命名管道
    • 使用 mkfifo 命令创建一个命名管道,或者在命令行中通过 tee 命令创建匿名管道,然后重定向到命名管道。
  2. 数据传输
    • 进程可以通过 cat > named_pipe 将数据写入管道,也可以通过 cat < named_pipe 从管道中读取数据。
  3. 持久性
    • 即使创建它的进程已经结束,命名管道仍然存在,直到最后一个使用它的进程结束。在这里插入图片描述
特点:
  • 全双工通信:命名管道允许全双工通信,即可以同时进行读写操作。
  • 持久性:命名管道在文件系统中有一个名称,可以在多个进程之间共享,并且具有持久性。
  • 灵活性:命名管道可以被任何进程读写,不受父子进程或兄弟进程的限制。

使用示例:

  • 匿名管道
    ls | grep "file"
    
    在这个例子中,ls 命令的输出会被传递给 grep 命令的输入。
  • 命名管道
    mkfifo myfifo
    cat > myfifo
    cat < myfifo
    
    在这个例子中,首先创建了一个命名管道 myfifo。然后,一个进程通过 cat > myfifo 将数据写入管道,另一个进程通过 cat < myfifo 从管道中读取数据。
    匿名管道和命名管道都是Linux中常用的进程间通信方式,它们各有优缺点,可以根据具体需求选择合适的方法。匿名管道适用于简单的单向通信,而命名管道适用于复杂的双向通信和多进程间通信。

管道所用的函数在这里插入图片描述

在Linux系统中,管道(Pipe)的创建和使用涉及到一些特定的系统调用和函数。以下是创建和使用管道的一些关键函数和概念:

创建管道

在Linux中,可以使用 pipe 系统调用来创建一个匿名管道。这个函数会返回两个文件描述符:一个用于读取管道,另一个用于写入管道。

#include <unistd.h>
int pipe(int fd[2]);
  • fd[2]:这是一个包含两个整数的数组,第一个整数用于读取,第二个整数用于写入。
  • 返回值:成功时返回0,失败时返回-1。

使用管道

一旦管道被创建,就可以通过以下方式来使用它:

  1. 写入管道
    #include <unistd.h>
    int write(int fd, const void *buf, size_t count);
    
    • fd:文件描述符,用于写入管道。
    • buf:指向要写入数据的缓冲区的指针。
    • count:要写入的字节数。
  2. 读取管道
    #include <unistd.h>
    int read(int fd, void *buf, size_t count);
    
    • fd:文件描述符,用于从管道中读取数据。
    • buf:指向读取数据的缓冲区的指针。
    • count:最多可以读取的字节数。

关闭管道

在完成对管道的读写操作后,应该关闭相关的文件描述符。

#include <unistd.h>
int close(int fd);
  • fd:要关闭的文件描述符。

示例代码

以下是一个简单的C语言示例,展示了如何创建和使用管道:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
    int fd[2];
    pipe(fd); // 创建匿名管道
    // 子进程将执行的代码
    if (fork() == 0) {
        close(fd[0]); // 关闭读端
        write(fd[1], "Hello, World!", 14); // 写入管道
        close(fd[1]); // 关闭写端
        exit(0);
    }
    // 父进程将执行的代码
    close(fd[1]); // 关闭写端
    char buf[15];
    read(fd[0], buf, 14); // 从管道中读取数据
    printf("Received: %s\n", buf); // 打印接收到的数据
    close(fd[0]); // 关闭读端
    return 0;
}

在这个示例中,子进程向管道写入数据,而父进程从管道中读取数据。
请注意,这些函数和概念是Linux编程的基础,对于深入理解Linux系统编程非常重要。

在这里插入图片描述

匿名管道函数 命名管道函数 父子进程 不同进程通信

在Linux中,匿名管道和命名管道是进程间通信(IPC)的两种常见机制。它们用于在进程之间传递数据,特别是在父子进程之间或相关的进程之间。

匿名管道(Anonymous Pipe)

匿名管道是一种半双工的通信方式,用于在两个进程之间传输数据。匿名管道是在两个命令之间使用管道符(|)时自动创建的,不需要显式地创建。

创建和操作匿名管道:
  1. 创建:当一个命令的输出被管道符(|)连接到另一个命令的输入时,就会创建一个匿名管道。
  2. 读写
    • 第一个命令的输出被写入匿名管道。
    • 第二个命令的输入从匿名管道中读取。
  3. 关闭:当管道两端的进程都完成了读写操作后,管道会自动关闭。
示例:
ls | grep "file"

在这个例子中,ls 命令的输出被传递给 grep 命令的输入。

命名管道(Named Pipe)

命名管道是一种全双工的通信方式,可以在多个进程之间传输数据。它通过文件系统的路径进行访问,因此可以被多个进程共享。

创建和操作命名管道:在这里插入图片描述
  1. 创建:使用 mkfifo 命令或通过命令行创建匿名管道并重定向到命名管道。
  2. 读写
    • 进程可以通过 cat > named_pipe 将数据写入管道。
    • 进程可以通过 cat < named_pipe 从管道中读取数据。
  3. 持久性:即使创建它的进程已经结束,命名管道仍然存在,直到最后一个使用它的进程结束。
示例:
mkfifo myfifo
cat > myfifo
cat < myfifo

在这个例子中,首先创建了一个命名管道 myfifo。然后,一个进程通过 cat > myfifo 将数据写入管道,另一个进程通过 cat < myfifo 从管道中读取数据。

父子进程和不同进程通信:

  • 父子进程:匿名管道通常用于父子进程之间的通信。当一个进程通过 fork 创建一个子进程时,匿名管道可以用来在两个进程之间传递数据。
  • 不同进程:命名管道可以用于多个相关进程之间的通信。由于它可以通过文件系统的路径进行访问,因此可以被多个进程共享。
    在实际应用中,匿名管道和命名管道都是非常重要的IPC机制,它们各自适用于不同的场景。匿名管道适用于简单的单向通信,而命名管道适用于复杂的双向通信和多进程间通信。

代码示例

以下是一个简单的Python代码示例,展示了如何在两个进程之间使用命名管道进行通信。这个例子使用了os.fork()函数来创建一个子进程,并使用os.open()os.write()函数来创建和写入命名管道。

import os
import time
# 创建命名管道
named_pipe_path = '/tmp/my_named_pipe'
os.makedirs('/tmp', exist_ok=True)
os.mkfifo(named_pipe_path)
# 父进程代码
def parent_process():
    # 打开命名管道用于写入
    with os.open(named_pipe_path, os.O_WRONLY) as pipe:
        # 写入数据到命名管道
        os.write(pipe, b'Hello from parent\n')
        time.sleep(2)  # 等待子进程读取
        os.write(pipe, b'Parent done\n')
# 子进程代码
def child_process():
    # 打开命名管道用于读取
    with os.open(named_pipe_path, os.O_RDONLY) as pipe:
        # 读取数据从命名管道
        data = os.read(pipe, 1024)
        print(f'Child received: {data.decode("utf-8")}')
        time.sleep(1)  # 等待父进程写入
        data = os.read(pipe, 1024)
        print(f'Child received: {data.decode("utf-8")}')
# 创建子进程
if os.fork() == 0:
    child_process()
else:
    parent_process()

在这个例子中,父进程会创建一个名为 my_named_pipe 的命名管道,并在其中写入一些数据。子进程会打开同一个管道并从中读取数据。
请注意,这个例子需要在支持命名管道的环境中运行,并且需要相应的权限来创建和访问命名管道。此外,os.mkfifo() 函数在某些系统上可能需要管理员权限,因此你可能需要使用 sudo 命令来运行这个脚本。

在这里插入图片描述

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jing静~

ლ(°◕‵ƹ′◕ლ)让我一键努

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值