文章目录

  • 前言
  • 一、创建无名管道
  • 二、尝试在无名管道中读取
    • 1.引入库
    • 2.验证无名管道的内容只能读一次
  • 三、测试无名管道能写入多少个字节
  • 四、测试两个进程是否能通信
  • 五、父子进程通信案例
  • 总结

前言

本文记录的是进程间通信之无名管道


一、创建无名管道

pipe ( 建立无名管道 )
头文件:
#include <unistd.h>

         定义函数:int pipe(int pipefd[2]);参数分析:pipefd[0] --> 接收管道描述符pipefd[1] --> 写管道描述符返回值:若成功则返回 0, 否则返回-1, 错误原因存于 errno 中.
#include <stdio.h>#include <unistd.h>int main(int argc, char const *argv[])
{int pipe_fd[2];    //两个文件描述符//int pipe(int pipefd[2]);int ret = pipe( pipe_fd );if ( ret < 0 ) {printf("create pipe failure\n");perror("create pipe error");return -1;} printf("create pipe success! pipe_fd[0] = %d, pipe_fd[1] = %d\n", pipe_fd[0], pipe_fd[1]);return 0;
}

结果显示:

二、尝试在无名管道中读取

1.引入库

把"hello linux!" 写进无名管道,然后通过read函数读取出来。

#include <stdio.h>#include <unistd.h>int main(int argc, char const *argv[])
{char buffer[20];int pipe_fd[2];    //两个文件描述符//int pipe(int pipefd[2]);int ret_pipe = pipe( pipe_fd );if ( ret_pipe < 0 ) {printf("create pipe failure\n");perror("create pipe error");return -1;} printf("create pipe success! pipe_fd[0] = %d, pipe_fd[1] = %d\n", pipe_fd[0], pipe_fd[1]);//把hello linux!写入无名管道int ret_write = write(pipe_fd[1], "hello linux!", sizeof("hello linux!") );if( ret_write < 0 ) {printf("写入失败!\n");perror("write error");return -1;}read(pipe_fd[0], buffer, sizeof(buffer) );printf("%s\n", buffer);close(pipe_fd[0]);close(pipe_fd[1]);return 0;
}

结果显示:

2.验证无名管道的内容只能读一次

代码如下(示例):

#include <stdio.h>
#include <unistd.h>
#include <string.h>int main(int argc, char const *argv[])
{char buffer[20];int pipe_fd[2];    //两个文件描述符//int pipe(int pipefd[2]);int ret_pipe = pipe( pipe_fd );if ( ret_pipe < 0 ) {printf("create pipe failure\n");perror("create pipe error");return -1;} printf("create pipe success! pipe_fd[0] = %d, pipe_fd[1] = %d\n", pipe_fd[0], pipe_fd[1]);//把hello linux!写入无名管道int ret_write = write(pipe_fd[1], "hello linux!", sizeof("hello linux!") );if( ret_write < 0 ) {printf("写入失败!\n");perror("write error");return -1;}//The first readread(pipe_fd[0], buffer, sizeof(buffer) );printf("%s\n", buffer);//The second read void *memset(void *s, int c, size_t n);memset(buffer, 0, 20);      //前20个字节清零read(pipe_fd[0], buffer, sizeof(buffer) );printf("%s\n", buffer);close(pipe_fd[0]);close(pipe_fd[1]);return 0;
}

结果显示:

从执行结果来看,第二次读取无名管道的内容的时候,并没有成功,终端一直在执行着。

三、测试无名管道能写入多少个字节

/************************************************************************
*
* 文件名:pipe_03.c
*
* 功能:测试无名管道能写入多少个字节
*
* 创建人:LiZhenhao
*
* 时间:2021年10月20日19:02:56
*
* 版本号:3.0
*
* 结果:无名管道最多能写入65507个字节
*
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <string.h>int main(int argc, char const *argv[])
{char buffer[20];int pipe_fd[2];    //两个文件描述符int i = 0;//创建无名管道int ret_pipe = pipe( pipe_fd );if ( ret_pipe < 0 ) {printf("create pipe failure\n");perror("create pipe error");return -1;} printf("create pipe success! pipe_fd[0] = %d, pipe_fd[1] = %d\n", pipe_fd[0], pipe_fd[1]);//把hello linux!写入无名管道int ret_write = write(pipe_fd[1], "hello linux!", sizeof("hello linux!") );printf("ret_write = %d\n", ret_write);while( ret_write != -1 ) {ret_write = write(pipe_fd[1], "hello linux!", sizeof("hello linux!") );i++;printf("total = %d\n", i);}//关闭文件描述符close(pipe_fd[0]);close(pipe_fd[1]);return 0;
}

结果显示:

从上面界面的结果来看,执行次数是5039次,然后写入的字节一次总共写了13个字节,通过计算13*5039 = 65,507个字节

四、测试两个进程是否能通信

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{int status;//创建无名管道int pipefd[2];if( 0 == pipe(pipefd) ) {printf("创建无名管道成功!\n");}//创建子进程pid_t pid = fork();if(pid > 0) {printf("我是父进程,ID:%d\n", getpid());ssize_t ret = write (pipefd[1], "hello linux!", strlen("hello linux!"));printf("成功写入%ld个字节进无名管道\n", ret);wait(&status);if( WIFEXITED(status) ) {printf("子进程正常退出,退出值为:%d\n", WEXITSTATUS(status));}sleep(1);} else if(0 == pid){printf("我是子进程,ID:%d\n", getpid());char re_buf[20] = {0};ssize_t ret = read(pipefd[0], re_buf, sizeof(re_buf));printf("成功进从无名管道读取%ld个字节, 内容是:%s\n", ret, re_buf);//exit(1);}return 0;
}

结果显示:

从上面结果分析:父子进程同时进行,父进程写入数据到无名管道,子进程成功从无名管道读取数据

五、父子进程通信案例

/* 实习父子进程通信  */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>//char* msg_buf = NULL;int main(int argc, char const *argv[])
{int status;//msg_buf = (char*)malloc(sizeof(char) * 1024);char msg_buf[1024];//创建无名管道int pipefd[2];if( pipe(pipefd) < 0) {printf("创建无名管道失败!\n");perror("create pipe error");return -1;}//创建子进程pid_t pid = fork();if(pid > 0) {  //父进程printf("我是父进程,ID:%d\n", getpid());usleep(1000);while(1) {printf("父进程请输入:\n");memset(msg_buf, 0, 1024);fgets(msg_buf, 1024, stdin);ssize_t ret = write (pipefd[1], msg_buf, strlen(msg_buf)+1);printf("父进程成功写入%ld个字节进无名管道\n", ret);usleep(1000);ret = read(pipefd[0], msg_buf, sizeof(msg_buf));printf("父进程成功进从无名管道读取%ld个字节, 内容是:%s\n", ret, msg_buf);}wait(&status);close(pipefd[0]);close(pipefd[1]);} else if(0 == pid){   //子进程printf("我是子进程,ID:%d\n", getpid());     ssize_t ret;while(1) {ret = read(pipefd[0], msg_buf, 1024);printf("子进程成功进从无名管道读取%ld个字节, 内容是:%s\n", ret, msg_buf);printf("子进程请输入:\n");memset(msg_buf, 0, 1024);fgets(msg_buf, 1024, stdin);ssize_t ret = write (pipefd[1], msg_buf, strlen(msg_buf) + 1);printf("子进程成功写入%ld个字节进无名管道\n", ret);usleep(1000);}close(pipefd[0]);close(pipefd[1]);//exit(1);}return 0;
}

结果如图所示:

父进程和子进程在写完内容都无名管道以后,要usleep等待一下,不然会出现父进程写,父进程读这种情况。同理,子进程也一样。


总结

1、无名管道的通信方式是要有血缘关系的进程才能使用,父子进程对同一管道的通信
2、要在创建父子进程fork()之前,先创建无名管道,不然的话,父进程写完数据到无名管道,子进程会发生读阻塞。

进程间通信之无名管道相关推荐

  1. linux进程间通信(IPC) ---无名管道

    管道概述 管道(pipe)又称无名管道 无名管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符 任何一个进程在创建的时候,系统都会,给它分配4G的虚拟内存,分为3G的用户空间和1G的内核空间 ...

  2. c语言系统编程六:Linux进程间通信之无名管道

    Linux进程间通信之无名管道 一 文件描述符复制 1.1 dup函数(复制文件描述符) 1.2 dup2函数(复制文件描述符) 二 无名管道的概述 三 无名管道的特点 四 无名管道的创建和使用 4. ...

  3. 【Linux系统编程】进程间通信之无名管道

    00. 目录 文章目录 00. 目录 01. 管道概述 02. 管道创建函数 03. 管道的特性 04. 管道设置非阻塞 05. 附录 01. 管道概述 管道也叫无名管道,它是是 UNIX 系统 IP ...

  4. linux进程间通信:无名管道 pipe

    文章目录 内核层实现 结构 通信原理 特点 使用 函数声明 使用实例 单向通信 双向通信 编程注意事项 管道中无数据时读操作会阻塞 将管道的写端句柄关闭,不会影响读端数据读取 管道中没有数据,写操作关 ...

  5. 进程间通信方式(一)-- 无名管道、有名管道

    文章目录 1. 进程间通信方式分类 2. 进程间通信实现方式 3. 无名管道 3.1 概念 3.2 相关函数 读写规律 3.3 无名管道实现进程间通信 4. 有名管道 4.1 概念 4.2 创建有名管 ...

  6. 进程间的通信——无名管道

    进程间的通信--无名管道 宗旨:技术的学习是有限的,分享的精神是无限的. 一.进程间的通信 (1)同主机进程间数据交互机制:无名管道(PIPE),有名管道(FIFO).消息队列和共享内存.无名管道多用 ...

  7. 【Linux系统编程】进程间通信--无名管道(pipe)

    管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,所有的 UNIX 系统都支持这种通信机制. 无名管道有如下特点: 1.半双工,数据在同一时刻只能在一个方向上流 ...

  8. Linux系统无名管道通信实验,Linux进程间通信(二)---管道通信之无名管道及其基础实验...

    管道简介 管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入(其实我更愿意将管道比喻为农村浇地的管子).Linux的管道主要包括两种:无名管道和有名管道.这一节主要讲 ...

  9. Linux 3.进程间通信(IPC)(pipe 无名管道、mkfifo 有名管道、ftok、msgget、msgrcv、msgsnd、msgctl 消息队列)

    Linux 3.进程间通信(IPC) 进程间通信: 进程间方式: pipe 管道(无名管道) 头文件及原型 特点 pipe 示例 FIFO(有名管道) 管道文件的创建 mkfifo 头文件及原型 mk ...

最新文章

  1. 给url添加时间戳,解决浏览器缓存
  2. oracle查找重复记录
  3. Linux下利用rsync实现网站镜像同步
  4. vivo分屏_如果你用的是vivo手机,这4个功能别忽略,不然几千块就白花了
  5. VS扩展CodeMaid代码整理插件
  6. 关于background-*的一些属性
  7. Python工作笔记-往dll中传入char*类型的参数并且如何接收char*的值
  8. php 中抽象类的作用,解释PHP中的抽象类。
  9. linux v4l2进行视频采集编程介绍
  10. 编码基本功:相似函数参数顺序要一致
  11. 【SpringBoot_ANNOTATIONS】 生命周期 02 实现InitializingBean, DisposableBean接口
  12. java私有的构造函数_Java 私有构造函数的使用
  13. 【STM32H7教程】第39章 STM32H7的DMAMUX基础知识(重要)
  14. PHP框架高级编程——应用Symfony、CakePHP和Zend
  15. Word2016“此功能看似已中断 并需要修复”问题解决办法
  16. 微信小程序基于云数据库简单实现帖子点赞功能。
  17. [paper]Feature Squeezing: Detecting Adversarial Examples in Deep Neural Networks
  18. 电路学习1——磁珠的工作原理、磁珠的分类、磁珠的模型、磁珠的参数、磁珠与电感的区别、磁珠的应用、磁珠的误区
  19. 进位计数制及其相互转换
  20. 阿里p9教你Java学到什么程度才能叫精通?

热门文章

  1. 如何更改Windows显示字体_更改系统字体
  2. 西屋除湿机:快速干衣除了烘干机你还有更棒的选择
  3. 最新电商团队的 OKR案例
  4. 如何把ntfs改成苹果电脑使用及mac写入ntfs硬盘软件教程
  5. 如何用计算机打地鼠,《“打地鼠”游戏的程序实现》教学设计
  6. 读书笔记-C语言程序设计-西安电子科技大学出版社-王娟勤-【未完待续】
  7. 金九银十,看看你在哪个阶段
  8. 学会网络远程控制,就可在办公室操作家中的电脑
  9. LRC软件测试自学,自学selenium笔记一 - kael的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  10. Game Theory: 公平博弈