Linux编程基础 5.1:管道

1 简介

Linux进程通信机制:

  • 管道
  • 信号量
  • 消息队列
  • 共享内存
  • socket通信

2 管道

在这里插入图片描述
管道其实质是由内核管理的一个缓冲区
形象地认为管道的两端连接着两个进程:

  • 一个进程进行信息输出,将数据写入管道;
  • 另一个进程进行信息输入,从管道中读取信息。

管道分为:

  • 匿名管道:只能用于有亲缘关系的进程间通信,进程退出后管道会被销毁。
  • 命名管道:命名管道与进程的联系较弱,相当于一个读写内存的接口,进程退出后,命名管道依然存在。

2.1 匿名管道

匿名管道的使用流程如下:
①在进程中创建匿名管道,pipe函数;
②关闭进程中不使用的管道端口,close函数;
③在待通信的进程中分别对管道的读、写端口进行操作,read/write函数;
④关闭管道,close函数。

2.1.1 pipe函数

#include <unistd.h>
int pipe(int pipefd[2]);

功能:创建匿名管道

参数说明

  • pipefd:传入参数,一个文件描述符数组;Linux将管道抽象为一个特殊文件。

返回值说明

  • 成功:返回0.
  • 不成功:返回-1。

【案例1】使用pipe()实现父子进程间通信,父进程作为读端,子进程作为写端。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){int tempFd[2];//定义文件描述符数组int tempRet=pipe(tempFd);//创建管道if(tempRet == -1){   perror("pipe");exit(1);}   pid_t tempPid=fork();if(tempPid > 0){//父进程—读close(tempFd[1]);//关闭写端char tempBuf[64]={0};tempRet = read(tempFd[0], tempBuf, sizeof(tempBuf));//读数据close(tempFd[0]);write(STDOUT_FILENO, tempBuf, tempRet);//将读到的数据写到标准输出wait(NULL);} else if(tempPid == 0){//子进程—写close(tempFd[0]);//关闭读端char *tempStr="hello,pipe\n";write(tempFd[1], tempStr, strlen(tempStr)+1);//写数据close(tempFd[1]);}//of ifreturn 0;
}//of main

分析如下:
pipe()创建管道后读端的文件描述符为fd[0],写端的文件描述符为fd[1];
调用fork后父子进程共享文件描述符,文件描述符与管道的关系如图所示:
在这里插入图片描述

父进程进行读操作,子进程进行写操作;使用close()函数关闭父进程的写端与子进程的读端。
在这里插入图片描述
在这里插入图片描述

2.1.2 dup2函数

【案例2】使用管道实现兄弟进程间通信,兄弟进程实现命令“ls | wc –l”的功能。

  • 在实现本案例时会用到重定向函数dup2:
#include <unistd.h>
int dup2(int oldfd, int newfd);
  • 其功能是将参数oldfd的文件描述符复制给newfd
  • 若函数调用成功则返回newfd
  • 否则返回-1,并设置errno。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){int tempFd[2];int tempRet = pipe(tempFd);if(tempRet == -1){perror("pipe err");exit(1);}//of if   int i;pid_t tempPid, tempWpid;for(i=0; i<2; i++){//2个子if((tempPid = fork()) == 0){break;}//of if}//of ifif(2 == i){//父进程,回收子进程close(tempFd[0]); //关闭读close(tempFd[1]); //关闭写tempWpid = wait(NULL);printf("wait child 1 success,pid=%d\n", tempWpid );tempPid = wait(NULL);printf("wait child 2 success,pid=%d\n", tempPid);} else if(0 == i){//子进程1—写close(tempFd[0]);dup2(tempFd[1], STDOUT_FILENO);//定向到标准输出execlp("ls", "ls", NULL);} else if(1 == i){//子进程2—读close(tempFd[1]);dup2(tempFd[0], STDIN_FILENO);execlp("wc", "wc", "-l", NULL);}//of ifreturn 0;
}//of main

注意:

int execlp(const char *file, const char *arg, ...);

execlp是一个可变参数函数。它需要2个const char *。其余的参数(如果有的话)为转移到运行程序的附加参数,也是char * ,最后一个参数必须是NULL指针。
所以,文件参数是要执行的可执行文件的路径名。 arg是我们想在可执行文件中显示为argv [0]的字符串。按照惯例,argv [0]只是可执行文件的文件名,通常它被设置为与文件相同。

兄弟进程间通信,进程文件描述符与管道的关系如图所示:
在这里插入图片描述:
实线所示的箭头为编程中需要保留的文件描述符

2.1.3 popen/pclose函数

Linux标准I/O库两个函数popen()和pclose(),可完成管道通信的流程。

#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);

功能
popen函数的功能是:

  • 调用pipe()函数创建管道;
  • 调用fork()函数创建子进程;
  • 之后在子进程中通过execve()函数调用shell命令执行相应功能。

pclose函数的功能:

  • 关闭popen()打开的I/O流;
  • 通过调用wait()函数等待子进程命令执行结束;
  • 返回shell的终止状态,防止产生僵尸进程。

参数说明
popen函数的参数:

  • command:命令;
  • type:指定命令类型(输入w/输出r);

pclose函数的参数:

  • stream:I/O流。

返回值说明
popen函数的返回值:

  • 成功:管道文件的描述符;
  • 不成功:返回-1。

pclose函数的返回值:

  • 成功:0;
  • 不成功:-1。

【案例3】使用popen与pclose函数实现管道通信。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){FILE *tempRfp,*tempWfp;char temBuf[100];tempRfp = popen("ls","r");		//读取命令执行结果tempWfp = popen("wc -l","w");	//将管道中的数据传递给进程while(fgets(temBuf, sizeof(temBuf), tempRfp)!=NULL){fputs(temBuf, tempWfp);}//of while   pclose(tempRfp);pclose(tempWfp);return 0;
}//of main

2.2 命名管道

#include <sys/type.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);

功能:创建命名管道(FIFO文件),命名管道与系统中的一个路径名关联,以文件的形式存在于文件系统中,通过FIFO的路径名访问FIFO文件,实现进程间通信。

参数说明

  • pathname:管道文件的路径名,通过FIFO路径名访问FIFO文件;
  • mode:指定FIFO的权限;

返回值说明

  • 成功:0;
  • 不成功:-1,并设置errno。

【案例4】使用FIFO实现没有亲缘关系进程间的通信。没有亲缘关系的进程间通信,需要两段程序来实现:

  • fifo_write.c实现FIFO的写操作;
  • fifo_read.c实现FIFO的读操作。
fifo_write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int paraArgc,char *paraArgv[]){if(paraArgc < 2){							//判断是否传入文件名printf("./a.out fifoname\n");exit(1);}//of ifint tempRet = access(paraArgv[1], F_OK);	//判断fifo文件是否存在if(tempRet == -1){							//若fifo不存在就创建fifo int tempFIFO = mkfifo(paraArgv[1], 0664);if(tempFIFO == -1){						//判断文件是否创建成功perror("mkfifo");exit(1);} else{printf("fifo creat success!\n");}//of if}//of ifint tempFd = open(paraArgv[1], O_WRONLY);		//读写方式打开while(1){									//循环写入数据char *tempStrp="hello,world!";write(tempFd, tempStrp, strlen(tempStrp)+1);sleep(1);}//of whileclose(tempFd);return 0;
}//of mainfifo_read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int paraArgc,char *paraArgv[]){if(paraArgc < 2){						//判断是否传入文件名printf("./a.out fifoname\n");exit(1);}//of ifint tempRet = access(paraArgv[1], F_OK);	//判断fifo文件是否存在if(tempRet == -1){						//若fifo不存在就创建fifo int tempFIFO = mkfifo(paraArgv[1], 0664);if(tempFIFO == -1){					//判断文件是否创建成功perror("mkfifo");exit(1);} else{printf("fifo creat success!\n");}//of if}//of ifint tempFd = open(paraArgv[1], O_RDONLY);	//只读方式打开if(tempFd == -1){perror("open");exit(1);}//of ifwhile(1){								//不断读取fifo中的数据并打印char temBuf[1024]={0};read(tempFd, temBuf, sizeof(temBuf));printf("buf=%s\n", temBuf);}//of whileclose(tempFd);							//关闭文件return 0;
}//of main

FIFO文件和普通文件的区别:

  • FIFO文件是对内存进行操作;
  • 普通文件是存储在硬盘;
  • 对内存的的读取会比硬盘的读写要快很多;
  • 两个进程通过普通文件通信当然也是可以的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/507422.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python pd Series 添加行_Python数据分析与挖掘的常用工具

Python语言&#xff1a;简要概括一下Python语言在数据分析、挖掘场景中常用特性&#xff1a;列表(可以被修改)&#xff0c;元组(不可以被修改)字典(结构)集合(同数学概念上的集合)函数式编程(主要由lambda()、map()、reduce()、filter()构成)Python数据分析常用库&#xff1a;P…

Linux编程基础 5.2:消息队列

3 消息队列 消息队列的本质是一个存放消息的链表&#xff0c;该链表由内核来维护。一个消息队列由一个标识符&#xff08;即队列key&#xff09;来标识。消息队列的通信机制传递的数据具有某种结构&#xff0c;而不是简单的字节流&#xff1b;向消息队列中写数据&#xff0c;实…

python tab和空格混用_Python编程常见十大错误,看完你自己都笑了!

关注并置顶【柠檬班】的小哥哥小姐姐胸有成“猪”使用python会出现各种各样的错误&#xff0c;以下是Python常见的错误以及解决方法。01 ValueErrorValueError: ‘Conv2d_1a_33’ is not a valid scope name其实这就是命名错误的问题&#xff0c;如果仔细看“”是我在中文下打的…

升级浏览器_微软IE11浏览器 最后的升级机会

微软IE10浏览器将很快退出支持&#xff0c;许多Windows用户将没有任何安全或非安全更新&#xff0c;免费或付费辅助支持选项或在线技术内容等。幸运的是&#xff0c;微软正在为Windows用户提供升级到IE11的最后机会&#xff0c;目前IE11仅次于Firefox浏览器&#xff0c;这是互联…

jq如何获取选中option的值_【分享】如何获取变量token的值

一.什么是token客户端使用用户名跟密码请求登录服务端收到请求&#xff0c;去验证用户名与密码验证成功后&#xff0c;服务端会签发一个 Token&#xff0c;再把这个 Token 发送给客户端客户端收到 Token 以后可以把它存储起来&#xff0c;比如放在 Cookie 里或者 LocalStorage …

Linux编程基础 6.1:线程操作

1 线程操作 创建线程 挂起线程 终止线程 其它操作 1.1 创建线程 #include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); 功能&#xff1a;创建线程&#xff1b;线程调用pthread_crea…

灯效控制器和rgb控制器_更具个性的RGB风扇,机箱里的魔术师,九州风神MF120GT开箱...

写在前面不知道在2020年还有多少人会自己装机&#xff0c;相信喜欢个性的DIY玩家还是会陆陆续续跳进这个不小的坑。装机的乐趣在哪里&#xff0c;除了几大硬件&#xff0c;显然个性的灯效才是装机的灵魂。在光污染的道路上&#xff0c;普通的光环&#xff0c;光面等风扇&#x…

Linux编程基础 6.2:线程同步

2 线程同步 线程同步中的“同步”与生活中大家认知的“同步”略有不同&#xff0c;“同”不指同时&#xff0c;其主旨在于协同步调&#xff0c;按预定的先后次序执行线程&#xff1b;之所以需要实现线程同步&#xff0c;是因为若不对线程的执行次序加以控制&#xff0c;可能会…

电脑开两个微信_电脑怎么登录两个微信

1/4下载并安装微信电脑客户端&#xff0c;保证这台电脑没有登陆微信2/4就像正常打开微信一样&#xff0c;不过不是双击&#xff0c;而是快速连点四次3/4我们可以看到有两个微信登陆界面4/4用两个不同的账号进行扫码登陆即可

Linux编程基础 7.1:套接字通信流程及编程接口

1 socket通信流程 2 socket编程接口 Linux系统中常用的socket网络编程接口有&#xff1a; socket()bind()listen()accept()connect()send()recv()close()其中connect()与send()为客户端专用接口&#xff1b;bind()、listen()、accept()及recv()为服务器端专用接口&#xff1b…

cad2016中选择全图字体怎么操作_cad教程分享CAD中如何删除顽固图层?

Autocad教程公众号&#xff0c;专注于cad教程、cad教程视频的分享&#xff0c;欢迎关注&#xff0c;下载你所需的教程资源&#xff01;如你还未关注&#xff0c;请点击文章标题下方蓝色字体的"Autocad教程"进行关注。cad教程分享-CAD中如何删除顽固图层&#xff1f;方…

div 隐藏_div的position属性

如果你想把div放到合适的位置&#xff0c;请看看这篇文章。<!-- div的position属性--><html><style>.red{height:100px;background:red;}.green{height:100px;background:green;position:relative;left:50px;top:50px;}.black{height:100px;background:black…

乔布斯在斯坦福大学演讲稿英文_西方大文豪最爱的10个英文单词,写尽人世间细腻情感!...

从小浸染在汉语中的我们&#xff0c;常被汉字的意象美震撼到&#xff0c;一字就是一世界。汉字有种无与伦比的美丽&#xff0c;寥寥数字就能营造“只可意会不可言传”的意境&#xff0c;很多人感慨英文就是一串拉丁字母&#xff0c;无法传递细腻的情感。比如很多人说像「缘分」…

web前端开发论文写作_外语论文文献引言格式—MLA Style

我们之前讨论了外语论文文献引用格式—APA Style和Chicago Style—芝加哥论文脚注引注格式&#xff0c;今天我们来介绍在Essay写作中如何使用APA格式引用文献。MLA格式是英文论文写作最常用的一种参考文献格式。很多留学小伙伴都觉得MLA引用格式很复杂&#xff0c;今天译然小编…

pmbok第七版_PMBOK第七版要来了!都有哪些变化?你准备好了么?

PMBOK第7版#PMP##职场##项目管理##战略##价值#2020年1月15日PMBOK 第7版的征求意见稿发布&#xff0c;并于2020年1月14日结束意见征集&#xff0c;预计于今年第四季度发布。基于我的项目组合管理(PfMP)&#xff0c;项目集管理(PgMP),项目管理(PMP)的培训和研究经验&#xff0c;…

简述python的特性_Python的特性概要

1、和C比较&#xff0c;Python是解释型的语言&#xff0c; 2、a>字节码特性 b>动态语义&#xff0c;即在赋值时才确定数据类型 c>缩进&#xff0c;点击tap键缩进四个空格&#xff0c;使用编译器是记得查看&#xff01;3、注意 写Python的时候首先要记得定义编码格式&a…

python自动化办公实例展示_python自动化办公?学这些就够用了

知乎上有人提问&#xff1a;用python进行办公自动化都需要学习什么知识呢&#xff1f;这可能是很多非IT职场人士面临的困惑&#xff0c;想把python用到工作中&#xff0c;却不知如何下手&#xff1f; python在自动化办公领域越来越受欢迎&#xff0c;批量处理简直是加班族的福音…

Linux编程基础 8.3:I/O多路转接服务器

1 简介 为进一步提升服务器效率&#xff0c;人们提出了一种被称为I/O多路转接的模型。其中“多路”指代连接到服务器的多个客户端程序&#xff0c;而“转接”则是指在服务器主线与各分支之间设置一个“岗位”&#xff0c;由该岗位实现监控多路连接中数据状态的功能&#xff0c…

测井储层参数预测+人工智能方法

1 问题描述 测井储层参数预测 地层泥质含量&#xff1b;地层孔隙度&#xff08;POR&#xff09;&#xff1b;含水饱和度&#xff08;SW&#xff09;&#xff1b;渗透率&#xff08;PERM&#xff09;。 输入&#xff1a;声波时差&#xff08;AC&#xff09;、补偿中子&#x…

windows 安装openssh服务端_Git神器| SourceTree安装使用教程

SourceTree 是 Windows 和Mac OS X 下免费的Git客户端管理工具。支持创建、克隆、提交、push、pull 和合并等操作。一、sourcetree的安装1. 下载sourcetree下载链接&#xff1a;Sourcetree | Free Git GUI for Mac and Windows2. 安装sourcetree点击安装&#xff0c;第一个创建…