管道是两个或多个相关进程之间的通信介质,它可以在一个进程内,也可以在子进程与父进程之间进行通信。
可以实时查看管道机制,例如用管道将水填充到某个容器(例如桶)中,然后取回某人(例如用杯子)。填充进程只不过是写入管道,而读取进程只不过是从管道中检索,这意味着一个输出(水)被输入到另一个(桶)。
#include<unistd.h> int pipe(int pipedes[2]);
该系统调用将创建用于单向通信的管道,即它创建两个描述符,第一个描述符连接以从管道读取,而另一个连接以写入管道。
描述符pipedes [0]用于读取,pipedes [1]用于写入,可以将任何写入pipedes [1]的内容从pipedes [0]中读取。
成功时此调用将返回零,失败时将返回-1,要知道失败的原因,请使用errno变量或perror()函数进行检查。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
即使可以读写文件的基本操作,也必须在执行操作之前先打开文件,并在完成所需的操作后关闭文件。通常默认情况下为每个进程打开3个描述符,分别用于文件描述符0(标准输入– stdin)、1(标准输出– stdout)和2(标准错误– stderr)。
Read(读权限) - 4,Write(写权限) - 2和Execute (执行权限)- 1。
例如:八进制值(以0开头),0764表示所有者拥有读取,写入和执行权限,组拥有读取和写入权限,其他拥有读取权限。这也可以表示为S_IRWXU |。 S_IRGRP | S_IWGRP | S_IROTH,表示或操作为0700 | 0040 | 0020 | 0004→0764。
如果发生错误,此系统调用成功后将返回新的文件描述符ID和-1。可以使用errno变量或perror()函数确定错误原因。
#include<unistd.h> int close(int fd)
上面的系统调用关闭已经打开的文件描述符,这意味着该文件不再使用,并且关联的资源可以由任何其他进程重用。该系统调用成功返回零,如果出错则返回-1。可以使用errno变量或perror()函数确定错误原因。
#include<unistd.h> ssize_t read(int fd, void *buf, size_t count)
上面的系统调用是从指定的文件中读取文件描述符fd的参数,具有已分配内存(静态或动态)的适当缓冲区以及缓冲区的大小。
文件描述符ID用于标识相应的文件,该文件在调用open()或pipe()系统调用后返回,从文件读取之前,需要先打开文件。如果调用pipe()系统调用,它将自动打开。
要知道失败的原因,请使用errno变量或perror()函数进行检查。
#include<unistd.h> ssize_t write(int fd, void *buf, size_t count)
上面的系统调用是使用文件描述符fd的参数,具有分配的内存(静态或动态)和缓冲区大小的适当缓冲区写入指定的文件。
范例程序
以下是一些示例程序。
示例程序1 -使用管道编写和读取两条消息的程序。
源代码:simplepipe.c
#include<stdio.h> #include<unistd.h> int main() { int pipefds[2]; int returnstatus; char writemessages[2][20]={"Hi", "Hello"}; char readmessage[20]; returnstatus = pipe(pipefds); #创建管道 if (returnstatus == -1) { printf("Unable to create pipe\n"); return 1; } printf("Writing to pipe - Message 1 is %s\n", writemessages[0]); write(pipefds[1], writemessages[0], sizeof(writemessages[0])); #向管道发送消息 read(pipefds[0], readmessage, sizeof(readmessage)); #从管道中检索消息并将其写入标准输出 printf("Reading from pipe – Message 1 is %s\n", readmessage); printf("Writing to pipe - Message 2 is %s\n", writemessages[0]); write(pipefds[1], writemessages[1], sizeof(writemessages[0])); #向管道发送另一条消息 read(pipefds[0], readmessage, sizeof(readmessage)); #从管道中检索消息并将其写入标准输出 printf("Reading from pipe – Message 2 is %s\n", readmessage); return 0; }
注意-理想情况下,需要检查每个系统调用的返回状态。为了简化进程,不对所有calls进行检查。
汇编
gcc -o simplepipe simplepipe.c
执行/输出
Writing to pipe - Message 1 is Hi Reading from pipe – Message 1 is Hi Writing to pipe - Message 2 is Hi Reading from pipe – Message 2 is Hell
示例程序2 - 使用父进程和子进程通过管道写入和读取两条消息的程序。
源代码:pipewithprocesses.c
#include<stdio.h> #include<unistd.h> int main() { int pipefds[2]; int returnstatus; int pid; char writemessages[2][20]={"Hi", "Hello"}; char readmessage[20]; returnstatus = pipe(pipefds); #创建管道 if (returnstatus == -1) { printf("Unable to create pipe\n"); return 1; } pid = fork(); #创建一个子进程 //Child process if (pid == 0) { read(pipefds[0], readmessage, sizeof(readmessage)); #子进程从管道中检索消息并将其写入标准输出 printf("Child Process - Reading from pipe – Message 1 is %s\n", readmessage); read(pipefds[0], readmessage, sizeof(readmessage)); printf("Child Process - Reading from pipe – Message 2 is %s\n", readmessage); } else { //Parent process printf("Parent Process - Writing to pipe - Message 1 is %s\n", writemessages[0]); write(pipefds[1], writemessages[0], sizeof(writemessages[0])); #父进程写入管道 printf("Parent Process - Writing to pipe - Message 2 is %s\n", writemessages[1]); write(pipefds[1], writemessages[1], sizeof(writemessages[1])); } return 0; }
汇编
gcc pipewithprocesses.c –o pipewithprocesses
执行
Parent Process - Writing to pipe - Message 1 is Hi Parent Process - Writing to pipe - Message 2 is Hello Child Process - Reading from pipe – Message 1 is Hi Child Process - Reading from pipe – Message 2 is Hello
双向通讯
管道通信仅被视为单向通信,即父进程写入而子进程读取,反之亦然,但不是两者都通信。但是如果父进程和子进程都需要同时写入和读取管道,该解决方案是使用管道的双向通信,需要两条管道来创建双向通信。
以下是实现双向通信的步骤-
步骤1 - 创建两个管道,第一个是父进程写,子进程读,比如pipe1。第二个是让子进程写,父进程读,例如pipe2。
步骤2 - 创建一个子进程。
步骤3 - 关闭不必要的一端,因为每次通信只需要一端。
步骤4 - 在父进程中关闭不需要的端,读取pipe1的端并写入pipe2的端。
步骤5 - 关闭子进程中不需要的一端,写入pipe1的一端,并读取pipe2的一端。
步骤6 - 根据需要执行通信。
样例程序
示例程序1 - 使用管道实现双向通讯。
源代码:twowayspipe.c
#include<stdio.h> #include<unistd.h> int main() { int pipefds1[2], pipefds2[2]; int returnstatus1, returnstatus2; int pid; char pipe1writemessage[20] = "Hi"; char pipe2writemessage[20] = "Hello"; char readmessage[20]; returnstatus1 = pipe(pipefds1); #父进程创建管道1,子进程读取管道 if (returnstatus1 == -1) { printf("Unable to create pipe 1\n"); return 1; } returnstatus2 = pipe(pipefds2); #为要写入的子进程和要读取的父进程创建pipe2 if (returnstatus2 == -1) { printf("Unable to create pipe 2\n"); return 1; } pid = fork(); if (pid != 0) //Parent process { close(pipefds1[0]); //Close the unwanted pipe1 read side #从父级和子级关闭管道的多余末端 close(pipefds2[1]); //Close the unwanted pipe2 write side printf("In Parent: Writing to pipe 1 – Message is %s\n", pipe1writemessage); write(pipefds1[1], pipe1writemessage, sizeof(pipe1writemessage));#编写消息的父进程和阅读并在屏幕上显示的子进程 read(pipefds2[0], readmessage, sizeof(readmessage)); printf("In Parent: Reading from pipe 2 – Message is %s\n", readmessage); } else { //child process close(pipefds1[1]); //Close the unwanted pipe1 write side close(pipefds2[0]); //Close the unwanted pipe2 read side read(pipefds1[0], readmessage, sizeof(readmessage)); #编写消息的子进程和读取和显示在屏幕上的父进程。 printf("In Child: Reading from pipe 1 – Message is %s\n", readmessage); printf("In Child: Writing to pipe 2 – Message is %s\n", pipe2writemessage); write(pipefds2[1], pipe2writemessage, sizeof(pipe2writemessage)); } return 0; }
执行步骤
汇编
gcc twowayspipe.c –o twowayspipe
执行
In Parent: Writing to pipe 1 – Message is Hi In Child: Reading from pipe 1 – Message is Hi In Child: Writing to pipe 2 – Message is Hello In Parent: Reading from pipe 2 – Message is Hello
进程 - 管道(Pipes) - 无涯教程网无涯教程网提供管道是两个或多个相关进程之间的通信介质,它可以在一个进程内,也可以在子进程与父进...https://www.learnfk.com/process/inter-process-communication-pipes.html