迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C语言 >

从 C 语言中的管道读取数据

作者:迹忆客 最近更新:2023/03/27 浏览次数:

本文将演示有关如何从 C 语言中的管道读取的多种方法。


使用 piperead 系统调用在 C 语言中从管道中读取数据

管道是基于 UNIX 的系统中的进程间通信(IPC)原语的变体之一。它提供了一个单向通信通道,即两个进程之间的字节流,并且数据在一个方向上顺序移动。pipe 系统调用用于创建管道并获取其读取和写入端的文件描述符。注意,我们可以使用普通的 I/O 函数 readwrite 对管道描述符进行操作。pipe 系统调用采用包含两个元素的 int 数组,成功调用将返回两个文件描述符,分别表示第一个-读取和第二个-写入结束。请注意,写入管道的数据会在内核中进行缓冲,直到读取器检索到给定的字节为止。

在下面的示例中,我们演示了在父进程和子进程之间进行通信的管道的基本用法。首先,我们创建一个管道并将其描述符存储在 pipe_fd 数组中。接下来,我们在 switch 语句表达式中调用 fork,并在情况 0 下包含子进程的代码块。另一方面,default 情况将由父进程执行。

请注意 ,父级将写入从命令行参数中检索到的字符串,然后等待子级终止。同时,子进程从管道读取,并将读取的字节打印到控制台。子进程和父进程都关闭管道的一端,因为子进程继承了 fork 上父进程的文件描述符。最后,在读取发送的字节之后,子进程关闭管道的读取端,并以 exit 调用终止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

enum {BUF_SIZE = 4096};

int main(int argc, char *argv[]) {
    int pipe_fd[2];
    char buf[BUF_SIZE];
    ssize_t numRead;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    switch (fork()) {
        case -1:
            perror("fork");
            exit(EXIT_FAILURE);

        case 0:
            if (close(pipe_fd[1]) == -1) {
                perror("close - parent");
                exit(EXIT_FAILURE);
            }

            sleep(3);
            numRead = read(pipe_fd[0], buf, BUF_SIZE);
            write(STDOUT_FILENO, buf, numRead);

            write(STDOUT_FILENO, "\n", 1);
            if (close(pipe_fd[0]) == -1) {
                perror("close");
                exit(EXIT_FAILURE);
            }
            _exit(EXIT_SUCCESS);

        default:
            if (close(pipe_fd[0]) == -1) {
                perror("close - parent");
                exit(EXIT_FAILURE);
            }

            if (write(pipe_fd[1], argv[1], strlen(argv[1])) != strlen(argv[1])) {
                perror("write - partial/failed write");
                exit(EXIT_FAILURE);
            }

            if (close(pipe_fd[1]) == -1) {
                perror("close");
                exit(EXIT_FAILURE);
            }

            wait(NULL);
            exit(EXIT_SUCCESS);
    }
}

在 C 语言中使用 while 循环从管道中读取数据

先前的示例代码有一个欺骗性的错误,该错误可能导致子进程中的部分读取。read 调用返回的数据可能少于管道中的数据,因此在此示例中调用一个 read 调用将是错误的。幸运的是,read 函数返回读取的字节数,我们可以实现一个循环,以用尽管道中的数据,如下一个代码示例所示。

请注意 ,管道具有固定的容量,如果达到最大值,则写操作将阻塞,直到读取器检索到一些数据为止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

enum {BUF_SIZE = 4096};

int main(int argc, char *argv[]) {
    int pipe_fd[2];
    char buf[BUF_SIZE];
    ssize_t numRead;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    switch (fork()) {
        case -1:
            perror("fork");
            exit(EXIT_FAILURE);

        case 0:
            if (close(pipe_fd[1]) == -1) {
                perror("close - parent");
                exit(EXIT_FAILURE);
            }

            while (1) {
                numRead = read(pipe_fd[0], buf, BUF_SIZE);
                if (numRead == -1) {
                    perror("read");
                    exit(EXIT_FAILURE);
                }
                if (numRead == 0)
                    break;

                if (write(STDOUT_FILENO, buf, numRead) != numRead){
                    perror("write - partial/failed write");
                    exit(EXIT_FAILURE);
                }
            }

            write(STDOUT_FILENO, "\n", 1);
            if (close(pipe_fd[0]) == -1) {
                perror("close");
                exit(EXIT_FAILURE);
            }
            _exit(EXIT_SUCCESS);

        default:
            if (close(pipe_fd[0]) == -1) {
                perror("close - parent");
                exit(EXIT_FAILURE);
            }

            if (write(pipe_fd[1], argv[1], strlen(argv[1])) != strlen(argv[1])) {
                perror("write - partial/failed write");
                exit(EXIT_FAILURE);
            }

            if (close(pipe_fd[1]) == -1) {
                perror("close");
                exit(EXIT_FAILURE);
            }

            wait(NULL);
            exit(EXIT_SUCCESS);
    }
}

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 C 语言中使用 typedef enum

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。

C 语言中的静态变量

发布时间:2023/05/07 浏览次数:151 分类:C语言

本文介绍了如何在 C 语言中使用静态变量。在 C 语言中使用 static 变量在函数调用之间保存变量值

C 语言中生成随机数

发布时间:2023/05/07 浏览次数:64 分类:C语言

本文演示了如何在 C 语言中生成随机数。使用 rand 和 srand 函数在 C 语言中生成随机数

C 语言中的 i++ 与++i

发布时间:2023/05/07 浏览次数:83 分类:C语言

本文演示了如何在 C 语言中使用前缀增量与后缀增量运算符。C 语言中++i 和 i++ 记号的主要区别

C 语言中获取当前工作目录

发布时间:2023/05/07 浏览次数:182 分类:C语言

本文演示了如何在 C 语言中获取当前工作目录。使用 getcwd 函数获取当前工作目录的方法

C 语言中的位掩码

发布时间:2023/05/07 浏览次数:126 分类:C语言

本文介绍了如何在 C 语言中使用位掩码。使用 struct 关键字在 C 语言中定义位掩码数据

C 语言中的排序函数

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文演示了如何在 C 语言中使用标准库排序函数。使用 qsort 函数对 C 语言中的整数数组进行排序

C 语言中的 extern 关键字

发布时间:2023/05/07 浏览次数:114 分类:C语言

本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量

C 语言中的 #ifndef

发布时间:2023/05/07 浏览次数:186 分类:C语言

本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便