Linux进程编程(2)进程间管道通信之无名管道

Linux进程编程(2)进程间管道通信(无名管道)


什么是无名管道

管道(Pipe)是一种用于进程间通信的机制,在Unix和类Unix系统中广泛使用。它允许一个进程将数据写入到管道中,而另一个进程则可以从管道中读取这些数据。管道通常用于在父进程和子进程之间传递数据。

管道有两种类型:有名管道(Named Pipe)和无名管道(Unnamed Pipe)。在这里,我们主要讨论无名管道,因为在本篇文章中使用的就是无名管道。

无名管道是一种匿名的、单向的通信通道。它只能在有亲缘关系(父子关系)的进程之间使用,因为无名管道在创建时并没有名字,只存在于相应的进程内部。无名管道具有以下特点:

  1. 单向通信:无名管道是单向的,它只能实现单向的数据传输。其中一个进程用于写入数据,另一个进程用于读取数据。

  2. 基于文件描述符:无名管道在创建时返回两个文件描述符。一个用于读取数据(读取端),另一个用于写入数据(写入端)。这些文件描述符可以用于像操作文件一样进行数据读写。

  3. 先进先出:无名管道是一个先进先出(FIFO)的数据结构。先写入的数据先被读取,确保数据按照写入顺序读取。

  4. 有限大小:无名管道有限制其缓冲区的大小,这意味着一旦写入的数据超过了管道的容量,写入操作将被阻塞,直到有足够空间接收数据。

在本文章中,我们使用pipe()函数创建了一个无名管道,并在父进程和子进程之间通过管道进行了数据传递。子进程向管道写入了一条消息,父进程从管道中读取并打印出收到的消息。这样实现了简单的进程间通信。


一、用到的函数

1.	int pipe(int pipefd[2]);
•	返回值:若成功,返回0;若失败,返回-1。
•	作用:pipe()函数用于创建一个无名管道,通过pipefd数组返回两个文件描述符,pipefd[0]用于读取数据,pipefd[1]用于写入数据。
•	参数:pipefd是一个int类型的数组,用于存储管道的读写文件描述符。调用时直接传入该数组即可。
2.	pid_t fork(void);
•	返回值:若成功,返回子进程的PID(在父进程中),返回0(在子进程中);若失败,返回-1。
•	作用:fork()函数用于创建一个新进程,新进程是当前进程(父进程)的副本,成为子进程。子进程从fork()函数返回的值为0,父进程从fork()函数返回子进程的PID。
•	参数:fork()函数没有参数,调用时直接使用即可。
3.	int close(int fd);
•	返回值:若成功,返回0;若失败,返回-1。
•	作用:close()函数用于关闭一个文件描述符。在本代码中,用于关闭管道的读取端和写入端,以确保进程之间的通信顺利进行。
•	参数:fd是一个int类型的文件描述符,表示要关闭的文件或管道的描述符。在本代码中,我们需要分别关闭读取端和写入端,所以在适当的位置调用close()函数,并传入相应的文件描述符。
4.	ssize_t write(int fd, const void *buf, size_t count);
•	返回值:若成功,返回写入的字节数;若失败,返回-1。
•	作用:write()函数用于将数据从指定缓冲区buf写入文件描述符fd对应的文件或管道。在本代码中,用于子进程向管道写入数据。
•	参数:fd是一个int类型的文件描述符,表示要写入的文件或管道的描述符。buf是一个指向要写入数据的缓冲区。count是要写入的字节数。
5.	ssize_t read(int fd, void *buf, size_t count);
•	返回值:若成功,返回读取的字节数;若到达文件末尾,返回0;若失败,返回-1。
•	作用:read()函数用于从文件描述符fd对应的文件或管道中读取数据到指定缓冲区buf。在本代码中,用于父进程从管道读取数据。
•	参数:fd是一个int类型的文件描述符,表示要读取的文件或管道的描述符。`

二、无名管道的实现

1.代码


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    int pipefd[2]; // 创建一个数组来存储管道的读写文件描述符
    char buffer[20]; // 创建一个缓冲区用于存储读取的数据

    // 创建管道,pipefd[0]用于读取,pipefd[1]用于写入
    pipe(pipefd);

    pid_t pid = fork(); // 创建一个子进程

    if (pid < 0) {
        // fork失败
        fprintf(stderr, "进程创建失败\n");
        return 1;
    } 
    else if (pid == 0) 
    {
        // 子进程
        close(pipefd[0]); // 关闭子进程的读取端,因为子进程只写入数据
        write(pipefd[1], "Hello from child!", 17); // 向管道写入数据
        close(pipefd[1]); // 关闭写入端,表示写入完成
    } 
    else
     {
        // 父进程
        close(pipefd[1]); // 关闭父进程的写入端,因为父进程只读取数据
        read(pipefd[0], buffer, sizeof(buffer)); // 从管道读取数据到缓冲区
        printf("收到消息:%s\n", buffer); // 打印收到的消息
        close(pipefd[0]); // 关闭读取端,表示读取完成
        wait(NULL); // 父进程等待子进程结束
    }

    return 0;
}

2.运行结果

收到消息: Hello from child!
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值