首页 > 系统相关 >无涯教程-进程 - 管道(Pipes)

无涯教程-进程 - 管道(Pipes)

时间:2023-08-26 19:31:37浏览次数:37  
标签:教程 int Pipes 无涯 pipe 管道 进程 Message readmessage

管道是两个或多个相关进程之间的通信介质,它可以在一个进程内,也可以在子进程与父进程之间进行通信。

可以实时查看管道机制,例如用管道将水填充到某个容器(例如桶)中,然后取回某人(例如用杯子)。填充进程只不过是写入管道,而读取进程只不过是从管道中检索,这意味着一个输出(水)被输入到另一个(桶)。

Pipe with one
#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   -  根据需要执行通信。

Pipe with two

样例程序

示例程序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

参考链接

https://www.learnfk.com/process/inter-process-communication-pipes.html

标签:教程,int,Pipes,无涯,pipe,管道,进程,Message,readmessage
From: https://blog.51cto.com/u_14033984/7245953

相关文章

  • Cinema 4D Download Install资源及使用教程
    Cinema4Dr25是一款专业的3D建模、动画、模拟和渲染软件解决方案,该软件其快速、强大、灵活和稳定的工具集使设计、运动图形、VFX、AR/MR/VR、游戏开发和所有类型的可视化专业人士更容易和高效地使用3D工作流程。使用它,哪怕是像制作动物毛发这样十分精细的三维特效也是可以轻轻......
  • 无涯教程-进程 - 其它进程
    到目前为止,我们已经讨论了进程,进程的创建,父进程和子进程等。如果不讨论其他相关进程(如孤立进程,僵尸进程和守护进程),则将是不完整的。孤立进程当我们运行程序或应用程序时,该应用程序的父进程是shell,当我们使用fork()创建进程时,新创建的进程是子进程,而创建子进程的进程是父进程......
  • [Python] PyCharm(Python IDE)安装教程
    1简介PyCharm是目前最流行、使用最广泛的PythonIDE(IntegratedDevelopmentEnvironment,集成开发环境),带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。比如调试、语法高亮、项目管理、代码跳转、智能提示、单元测试、版本控制等。此外,还提供了一些高级功能,以......
  • 无涯教程-进程 - 创建&终止
    到现在为止,我们知道无论何时执行程序,都会创建一个进程,并且该进程将在执行完成后终止,如果我们需要在程序中创建一个进程,并且可能希望为其安排其他任务,该怎么办。能做到吗?是的,显然是通过进程创建的,当然,工作完成后,它将自动终止,或者您可以根据需要终止它。进程创建是通过fork()系......
  • 求生之路2私人服务器开服搭建教程centos
    求生之路2私人服务器开服搭建教程centos大家好我是艾西,朋友想玩求生之路2(left4dead2)重回经典。Steam玩起来有时候没有那么得劲,于是问我有没有可能自己搭建一个玩玩。今天跟大家分享的就是求生之路2的自己用服务器搭建的一个心路历程。(因平台原因本文中www即为xxx,com即为zzz,http/......
  • 求生之路2社区服务器sourcemod安装配置搭建教程centos
    求生之路2社区服务器sourcemod安装配置搭建教程centos大家好我是艾西,通过上文我们已经成功搭建了求生之路2的服务端。但是这个服务端是纯净的服务端,就是那种最纯粹的原版。如果想要实现插件、sm开头的命令等功能,需要安装这个sourcemod。那本篇文章给搭建简单的说下sourcemod安装以......
  • Stable Diffusion web UI 部署详细教程
    前言本文使用AutoDL平台进行StableDiffusionwebUI云端部署AutoDL官网:[AutoDL算力云|弹性、好用、省钱。租GPU就上AutoDL]StableDiffusionwebUI官网:AUTOMATIC1111/stable-diffusion-webui:StableDiffusionwebUI(github.com)步骤租用实例选择社区镜像AUTOM......
  • Android入门教程 | Fragment 基础概念
    什么是Fragment?Fragment,直译为“碎片”,“片段”。Fragment表示FragmentActivity中的行为或界面的一部分。可以在一个Activity中组合多个片段,从而构建多窗格界面,并在多个Activity中重复使用某个片段。可以将片段视为Activity的模块化组成部分,它具有自己的生命周期,能接收自......
  • 无涯教程-进程 - 子进程监控
    正如我们所看到的,每当我们使用fork从程序创建子进程时,都会发生以下情况-当前进程成为父进程新进程成为子进程如果父进程比子进程提前完成任务然后退出,会发生什么?现在谁将成为子进程的父进程?子进程的父进程是init进程,它是启动所有任务的第一个进程。为了监视子进程的执行状......
  • AI绘画StableDiffusion美女实操教程:斗破苍穹-小医仙
    之前分享过StableDiffusion的入门到精通教程:AI绘画:StableDiffusion终极炼丹宝典:从入门到精通但是还有人就问:安装是安装好了,可是为什么生成的图片和你生成的图片差距那么远呢?怎么真实感和质感一个天一个地呢?出图效果展示:那么,我画的图,和你画的图,差别在哪里呢?很关键的因素,就......