C 中的多个管道
本文演示了 C 中多管道的实现。
C 中的管道概述
管道是两个不同进程之间链接的抽象表示,其中从一个进程返回的标准输出成为另一个进程的标准输入。 管道是 UNIX 操作系统的重要组成部分,它使链接的进程能够相互通信(进程间通信)。
管道只能单向通信; 因此,我们可以利用它们让一个进程写入管道,而另一个进程从管道读取。 管道是以与虚拟文件相同的方式处理的主内存区域,此操作将打开一个管道。
在 C 中实现多个管道
让我们看一个有 1 个父进程和 2 个子进程的例子。 我们通过管道从父进程发送一个保证完整的值到子进程,然后我们将该值发送回父进程并添加一些增量。
首先,我们需要导入库以访问应用程序中包含的类和函数。 此外,还应开发一个 main()
函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char* argv[]) { }
在 main 函数中,我们将为三个管道生成文件描述符,以便我们可以在其他进程上进行读写。 然后,您需要定义一个类型为 i 为整数的变量,以建立一个 for 循环,该循环将生成三个管道,并检查所有管道的值是否小于零以返回错误。
int fd[3][2];
int i;
for (i = 0; i < 3; i++) {
if (pipe(fd[i]) < 0) {
return 1;
}
}
我们打开管道后,接下来就是开始fork各个进程了。 因此,您应该建立一个名为 processIdOne 的变量,然后分配给 fork()
函数。
此外,应用检查以验证 processIdOne 的值不小于零。
int processIdOne = fork();
if (processIdOne < 0) {
return 2;
}
现在,我们检查 processIdOne 的值是否等于零; 如果是,则表明我们处于第一个子进程中。 必须在第一个子进程中使用 close()
函数来关闭除属于该进程的文件描述符之外的所有文件描述符。
创建一个名为 x 的整型变量,并将数据类型指定为 int。 现在,我们使用 read()
方法,为其提供文件描述符、&x 和读取值的大小,并在显示错误消息之前检查其值是否小于零。
接下来,我们检查 fileDescriptor[1][1]
值是否小于零,如果是则显示错误。 为此,我们使用 write() 方法,将其参数传递给它,并使用 fileDescriptor[1][1]
进行写入。
第一个子进程的文件描述符应该在最后一步关闭。
if (processIdOne == 0) {
// Child process 1
close(fileDescriptor[0][1]);
close(fileDescriptor[1][0]);
close(fileDescriptor[2][0]);
close(fileDescriptor[2][1]);
int x;
if (read(fileDescriptor[0][0], &x, sizeof(int)) < 0) {
return 3;
}
x += 10;
if (write(fileDescriptor[1][1], &x, sizeof(int)) < 0) {
return 4;
}
close(fileDescriptor[0][0]);
close(fileDescriptor[1][1]);
return 0;
}
下一步是建立一个名为 processIdTwo 的变量,然后分配 fork()
函数。 此外,应执行检查以确保 processIdTwo 的值不等于或小于零。
int processIdTwo = fork();
if (processIdTwo < 0) {
return 5;
}
现在,我们检查 processIdTwo 的值是否为零; 如果是,则表明我们处于第二个子进程中。 在第二个子进程中,我们需要确保使用 close()
方法关闭除此特定进程之外的所有文件描述符。
声明一个名为 x 的数据类型为 int 的变量。 现在,我们使用 read()
方法,向其提供文件描述符 &x 和读取值的大小,并确保在值小于零时显示错误。
接下来,通过将值 10 添加到 x 来增加 x 的值,我们使用 write()
函数及其参数来使用 fileDescriptor[2][1]
进行写入。 然后我们检查它的值是否小于零,如果是,我们显示一条错误消息。
最后,关闭第二个子进程的文件描述符。
if (processIdTwo == 0) {
close(fileDescriptor[0][0]);
close(fileDescriptor[0][1]);
close(fileDescriptor[1][1]);
close(fileDescriptor[2][0]);
int x;
if (read(fileDescriptor[1][0], &x, sizeof(int)) < 0) {
return 6;
}
x += 10;
if (write(fileDescriptor[2][1], &x, sizeof(int)) < 0) {
return 7;
}
close(fileDescriptor[1][0]);
close(fileDescriptor[2][1]);
return 0;
}
正如我们之前所做的那样,我们现在将关闭父进程中除与该进程对应的文件描述符之外的所有其他文件描述符。
将变量 x 声明为整数类型。 现在,我们使用 read()
函数,给它文件描述符 &x 和读取值的大小,并检查它的值是否小于零以确定是否应该显示错误。
接下来,通过增加值 10 来增加 x 的值。我们使用带有参数的 write()
函数使用 fileDescriptor[2][0]
进行写入,并检查其值是否小于零以确定 是否显示错误信息。
通过关闭它们来停止打开的文件描述符。
对于 processIdOne 和 processIdTwo,应该使用 waitpid()
方法。 此函数等待所有进程完成,然后再继续下一个操作。
close(fileDescriptor[0][0]);
close(fileDescriptor[1][0]);
close(fileDescriptor[1][1]);
close(fileDescriptor[2][1]);
int x = 0;
if (write(fileDescriptor[0][1], &x, sizeof(int)) < 0) {
return 8;
}
if (read(fileDescriptor[2][0], &x, sizeof(int)) < 0) {
return 9;
}
printf("The value received from the child processes is: %d\n", x);
close(fileDescriptor[0][1]);
close(fileDescriptor[2][0]);
waitpid(processIdOne, NULL, 0);
waitpid(processIdTwo, NULL, 0);
在 C 中实现多个管道的完整源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char* argv[]) {
int fileDescriptor[3][2];
int i;
for (i = 0; i < 3; i++) {
if (pipe(fileDescriptor[i]) < 0) {
return 1;
}
}
int processIdOne = fork();
if (processIdOne < 0) {
return 2;
}
if (processIdOne == 0) {
// Child process 1
close(fileDescriptor[0][1]);
close(fileDescriptor[1][0]);
close(fileDescriptor[2][0]);
close(fileDescriptor[2][1]);
int x;
if (read(fileDescriptor[0][0], &x, sizeof(int)) < 0) {
return 3;
}
x += 10;
if (write(fileDescriptor[1][1], &x, sizeof(int)) < 0) {
return 4;
}
close(fileDescriptor[0][0]);
close(fileDescriptor[1][1]);
return 0;
}
int processIdTwo = fork();
if (processIdTwo < 0) {
return 5;
}
if (processIdTwo == 0) {
// Child process 2
close(fileDescriptor[0][0]);
close(fileDescriptor[0][1]);
close(fileDescriptor[1][1]);
close(fileDescriptor[2][0]);
int x;
if (read(fileDescriptor[1][0], &x, sizeof(int)) < 0) {
return 6;
}
x += 10;
if (write(fileDescriptor[2][1], &x, sizeof(int)) < 0) {
return 7;
}
close(fileDescriptor[1][0]);
close(fileDescriptor[2][1]);
return 0;
}
// Parent process
close(fileDescriptor[0][0]);
close(fileDescriptor[1][0]);
close(fileDescriptor[1][1]);
close(fileDescriptor[2][1]);
int x = 0;
if (write(fileDescriptor[0][1], &x, sizeof(int)) < 0) {
return 8;
}
if (read(fileDescriptor[2][0], &x, sizeof(int)) < 0) {
return 9;
}
printf("The value received from the child processes is: %d\n", x);
close(fileDescriptor[0][1]);
close(fileDescriptor[2][0]);
waitpid(processIdOne, NULL, 0);
waitpid(processIdTwo, NULL, 0);
return 0;
}
输出:
The value received from the child processes is: 20
相关文章
在 C 语言中使用 typedef enum
发布时间:2023/05/07 浏览次数:181 分类:C语言
-
本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。
C 语言中的 extern 关键字
发布时间:2023/05/07 浏览次数:114 分类:C语言
-
本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量
C 语言中的 #ifndef
发布时间:2023/05/07 浏览次数:186 分类:C语言
-
本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。