首页 > 系统相关 >C语言--常用进程间通信方式

C语言--常用进程间通信方式

时间:2023-01-04 18:11:36浏览次数:41  
标签:fpid -- 描述符 C语言 间通信 管道 fd 进程 buff

管道

管道是一种队列型的数据结构,它的数据从一端输入,另一端输出。管道最常见应用就是连接两个进程的输入和输出,将一个进程的输入作为另一个进程的输出。

shell中有专门的管道运算符|,常用于检索内容,如:find | grep str

无名管道

无名管道一般直接称为管道,占用两个文件描述符,只能被具有亲缘关系的进程共享,一般是指父子进程

无名管道的建立

UNIX中一切皆是文件,管道也是文件中的一种。当系统创建一个管道时,它返回两个文件描述符,分别用作输出端(读)和输入端(写);
在UNIX中,使用pipe函数来创建管道:
头文件:#include <unistd.h>
声明:int pipe(int __pipedes[2])
功能:创建单向通信通道(管道)。如果成功,两个文件描述符将存储在__pipedes[2]中。一般写在__pipedes[1]上的字节可以从__pipedes[0]读取。
返回值:成功返回0;否则返回-1;

单向管道

通常管道的两端分别被两个不同的进程控制,这样两个进程就能够进行通信。控制输入端的进程向管道发送信息,控制输出端的进程从管道中读取信息。

在父进程创建管道并产生子进程之后,父子进程就都拥有管道两端的访问权。此时通过控制父子进程中管道两端开闭,就能够实现父子进程之间的单向通信;例:

#include <stdio.h>
#include <unistd.h>

int main() {
    int fd[2];
    pid_t fpid;
    char buff[20];
    // 创建管道,实现父进程向子进程发送信息
    if (pipe(fd) < 0) {
        printf("create Pipe error !!\n");
    }
    // 创建子进程
    fpid = fork();
    if (fpid < 0) {
        printf("fork error !!\n");
    } else if (fpid == 0) {
        // 子进程关闭管道输入端
        close(fd[1]);
        // 子进程从管道输出端读取
        read(fd[0], buff, 20);
        printf("%s\n", buff);
    } else {
        // 父进程关闭管道输出端
        close(fd[0]);
        // 父进程从输入端写入
        write(fd[1], "hello world\n", 12);
    }
    return 0;
}

若想要实现子进程向父进程发送信息,将父子进程中代码内容交换即可(即更改输入输出端);

双向管道

管道是进程间的单向交流方式,如果要实现双向通信就需要使用两个管道。
具体使用方式如下:

#include <stdio.h>
#include <unistd.h>

int main() {
    int fd1[2], fd2[2];
    pid_t fpid;
    char buff[20];
    // 创建管道1和管道2
    if (pipe(fd1) < 0 || pipe(fd2) < 0) {
        printf("create Pipe error !!\n");
    }
    // 创建子进程
    fpid = fork();
    if (fpid < 0) {
        printf("fork error !!\n");
    } else if (fpid == 0) {
        // 子进程关闭管道1输入端,从管道1输出端读取并打印
        close(fd1[1]);
        read(fd1[0], buff, 20);
        printf("[child] %s\n", buff);
        // 子进程关闭管道2输出端,从管道2输入端写入
        close(fd2[0]);
        write(fd2[1], "child information!\n", 20);
    } else {
        // 父进程关闭管道1输出端,从管道1输入端写入
        close(fd1[0]);
        write(fd1[1], "parent information!\n", 20);
        // 父进程关闭管道2输入端,从管道2输出端读取并打印
        close(fd2[1]);
        read(fd2[0], buff, 20);
        printf("[parent] %s\n", buff);
    }
    return 0;
}

运行结果:

[child] parent information!

[parent] child information!

管道图

连接I/O管道模型

通过使用dup2函数可以对标准输入、输出、错误进行重定向,例如:

dup2(fd1,0)//复制文件描述符fd1到文件描述符0即可重定向标准输入
dup2(fd2,1)//复制文件描述符fd2到文件描述符1即可重定向标准输出
dup2(fd3,2)//复制文件描述符fd3到文件描述符2即可重定向标准错误

通过将标准输入,输出,错误重定向到管道两端的文件描述符,就可以实现两个进程间标准输入输出的传递;

以下程序中,父进程向stdout输出hello,直接转移到子进程的stdin,由子进程中的fgets(buff)接收

#include <stdio.h>
#include <unistd.h>

int main() {
    int fd[2];
    pid_t fpid;
    char buff[256];
    // 创建管道
    if (pipe(fd) < 0) {
        printf("create Pipe error!!");
        return -1;
    }
    // 创建子进程
    fpid = fork();
    if (fpid < 0) {
        printf("fork error!!");
        return -1;
    }
    // 子进程关闭管道输入端;将标准输入(stdin,文件描述符为0)重定向为文件描述符fd[0];
    else if (fpid == 0) {
        close(fd[1]);
        dup2(fd[0], 0);
        close(fd[0]);
        fgets(buff, 256, stdin);
        printf("[child] %s\n", buff);
        return 0;
    }
    // 父进程关闭管道输出端;将标准输出(stdout,文件描述符为1)重定向为文件描述符fd[1];
    else {
        close(fd[0]);
        dup2(fd[1], 1);
        close(fd[1]);
        puts("hello");
        return 0;
    }
}

运行结果

[child]:hello

命名管道

标签:fpid,--,描述符,C语言,间通信,管道,fd,进程,buff
From: https://www.cnblogs.com/liyugui/p/17024208.html

相关文章

  • 新博客地址!
    搞了个新的博客,之后应该只会在那上面更新了,老文章也会搬一搬火速点击zysgmzb.club芜!......
  • C语言中使用ESL连接FreeSwitch
    前言之前在【FreeSwitch开发实践】在nodejs中用ESL连接FreeSwitch一文介绍了在NodeJS下使用ESL连接FreeSwitch,本文则对在C语言下使用ESL连接FreeSwitch作了一个系统介绍......
  • 一文入门 3D 视觉算法基础
    背景知识一,基于3DMM的三维人脸重建技术概述1.1,3D人脸重建概述1.2,初版3DMM二,视觉SLAM算法基础概述2.1,视觉里程计2.2,后端优化2.3,回环检测2.4,建图三,三维点云......
  • python爬取银行存款利率数据
    三年疫情让各行各业的经济都下滑了很多,手里有钱的人都会很谨慎地进行一些投资项目。2023新年来临,银行存款利率也出现一波调整,近期多家中小银行对定期存款挂牌利率进行下调。......
  • 解答|虚拟机、容器和沙箱是什么关系?
    大家有没有想过:虚拟机、容器和沙箱是什么关系?首先,什么是沙箱?它本身就是一种线下生活现象的虚拟化。现实世界里,小孩子们在沙地、沙滩上用木板隔离出一个方盒子,在盒子里堆砌、......
  • 外贸人需要知道的销售技巧有哪些?
    外贸销售技巧米贸搜整理如下,希望对你有所帮助:​第一步:准备好。没有准备意味着为失败做准备,没有计划意味着为破产做打算。这是为什么呢?因为你不知道你这次要谈什么,所以你首......
  • 软件开发入门教程网 Search之C++ 动态内存
       C++基本的输入输出   ......
  • 软件开发入门教程网 Search之C++ 环境设置
       C++基本的输入输出   ......
  • 针对FreeSWITCH的最佳开源GUI解决方案
    为了获得FreeSWITCH的最大利益,您需要能够正确选择GUI解决方案。看看FreeSWITCH的一些开源GUI解决方案,见证了它们的广泛普及和采用率。FreeSWITCHGUI被广泛地描述为FsG......
  • 11G RAC环境GRID目录及文件错误权限的修复
    111.2.0.4环境测试1.1 测试前的资源状态下面查看一下测试前的资源状态,确保每个资源的状态都是正常的。[grid@rac112042~]$crsctlstatusresource-t-----------------......