Linux学习笔记(12)-进程间通信|匿名管道
Linux的进程间通信有几种方式,包括,管道,信号,信号灯,共享内存,消息队列和套接字等……
现在一个个的开始学习!
——————————————————————————————————————————————————
管道是一个进程链接另一个进程的数据通道,它通常是把一个进程的输出,接到另一个进程的输入,从而传递数据。
在Linux的终端上,用单竖线|来表示,那么,这个符号可以做什么呢?
举个栗子,如果我用ps -ef命令,可以查看我当前所有的进程:
正如上图表示,显示出来的东西太多了,让人眼花缭乱,如果想在其中找到自己想要的进程,比如看看sshd服务是否启动了,那绝对会找到我吐血。
换一种方式,如果使用管道那就简单多了……
首先,用ps -ef命令后,他的输出就是一大堆的进程列表,我用这个输出,作为别的命令的输入,比如grep命令,那么就能轻易找到自己想要的进程。
ps -ef|grep sshd
下面来试试……
这样就很明显的看出,已经把进程中,拥有关键字sshd的进程给筛选了出来,而且还涂上了红色。一目了然,我的sshd服务已经启动了。
————————————————————————————————————————————————————————————————————————
管道分为匿名管道和命名管道两种,匿名管道主要用在两个拥有血缘关系的进程间通信,比如父子,爷孙……
而命名管道主要用在两个陌生进程之间的通信。
匿名管道是一种半双工管道,半双工就意味这,他在同一时间内,只能进程送信或者受信的一种,无法同时进行。
管道这个功能,如果表现在程序中,那么需要用到下面这个函数:
int pipe(int pipefd[2])
其中参数pipefd[2]是一个文件描述符性质的数组,代表打开管道的两端,其中pipefd[0]为读入,pipefd[1]为写入。
现在写个程序,父进程使用管道向子进程发送一个信号,子进程收到后,在返回一个信号。
因为一点小错误,这个程序写了将近一个小时……
重点:管道的读取read和写入write,这两个函数都是阻塞操作的!
重点中的重点:一定要在进程创立之前,建立好管道。
重点中的重点中的重点:匿名管道是半双工,在通信开始前,一定要先关闭不需要的通道,在通信结束后,一定也要执行关闭。
在匿名管道中,读进程和写进程初始都会拥有[0],[1],两个描述符各自一套,写程序时一定要注意在写处理里面 close(pi[0]),在读进程里面 close(pi[1]),在写进程写任务执行完之后务必 close(pi[1]),读进程读完之后务必 close(pi[0])。
否则将会出现无限阻塞的问题,关于这个问题,害得我花费了一个小时……
疑问:当一个匿名管道关闭之后,能不能再次重新打开呢?比如说用open(pi2[1])之后,在继续发送数据呢?
我在网上找了好久,但没有看见这方面的描述,我感觉,这匿名管道总不能是一次性的吧?如果真是那样,那也太奢侈了!!
- #include<sys/wait.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- int main(int argc, char *argv)
- {
- int pi1[];
- int pi2[];
- pid_t pid_test;
- char buff[];
- char buff2[]={"儿子:你好,我是儿子!"};
- char buff1[]= {"老子:你好,我是老子!"};
- if (pipe(pi1)== -)
- {
- printf("管道1号创建失败!\n");
- exit();
- }
- if (pipe(pi2) == -)
- {
- printf("创建2号管道失败!\n");
- }
- pid_test = fork();
- if (pid_test < )
- {
- printf("创建子进程失败!\n");
- exit();
- }
- if (pid_test == )
- {
- printf("我是儿子,名叫:%d,我爹是:%d\n",getpid(),getppid());
- write(STDOUT_FILENO,"\n",);
- close(pi1[]);
- while(read(pi1[],buff,) > )
- {
- write(STDOUT_FILENO,buff,);
- }
- write(STDOUT_FILENO,"\n",);
- close(pi1[]);
- printf("儿子读完了!\n");
- printf("儿子读完了!\n");
- sleep();
- close(pi2[]);
- write(pi2[],buff2,strlen(buff2));
- close(pi2[]);
- printf("儿子写完了!\n");
- exit(EXIT_SUCCESS);
- exit();
- }
- else
- {
- printf("我是爹!我的ID是:%d,我儿子的ID是:%d\n",getpid(),pid_test);
- sleep();
- close(pi1[]);
- write(pi1[],buff1,strlen(buff1));
- close(pi1[]);
- printf("老子写完了!\n");
- close(pi2[]);
- while(read(pi2[],buff,) > )
- {
- write(STDOUT_FILENO,buff,);
- }
- write(STDOUT_FILENO,"\n",);
- printf("老子读完了!\n");
- close(pi2[]);
- wait(NULL);
- exit();
- }
- return ;
- }
代码执行的结果如下:
程序OK了!!
今天,太累了!
Linux学习笔记(12)-进程间通信|匿名管道的更多相关文章
- linux学习笔记-12.输入输出重定向及管道
1.新建一个文件 touch a.txt> b.txt 2.错误重定向:2> find /etc -name zhaoxing.txt 2> error.txt 3.将正确或错误的信 ...
- linux学习笔记之进程间通信
一.基础知识. 1:进程通信基础(interProcess Communication, IPC):管道,FIFO(命名管道),XSI IPC,POSIX 信号量. 2:管道. 1,缺陷. 1)部分系 ...
- Linux学习笔记12—磁盘管理
一.查看磁盘或目录的容量 1. df命令 作用:查看已挂载磁盘的总容量.使用容量.剩余容量等,可以不加任何参数,默认是按k为单位显示的 参数: -I : 查看inodes使用状况 -h: 使用合适的 ...
- Linux学习笔记12——Unix中的进程
通过调用fork和exec函数都能创建新的进程,但两者有着本质的区别:fork函数拷贝了父进程的内存映像,而exec函数用用新的映像来覆盖调用进程的进程映像的功能. 一 fork函数 #includ ...
- Linux 学习笔记之超详细基础linux命令 Part 12
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 11---------------- ...
- Linux学习笔记——管道PIPE
管道:当从一个进程连接数据流到另一个进程时,使用术语管道(pipe).# include <unistd.h> int pipe(int filedes[2]); //创建管道 pipe( ...
- Linux 学习笔记
Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...
- Linux 学习笔记之超详细基础linux命令 Part 3
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 2----------------- ...
- 91 Testing Linux学习笔记
91 Testing Linux学习笔记... 学习地址:91Testing 的Linux教程=====================学习网址:http://www.91testing.net/ar ...
- linux的IPC进程通信方式-匿名管道(一)
linux的IPC进程通信-匿名管道 什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号"|"来使用管道,但是管道的真正定义是 ...
随机推荐
- [译]flexbox全揭秘
原文:http://css-tricks.com/snippets/css/a-guide-to-flexbox/ 弹性布局(弹性盒子,现今仍是w3c的候选推荐),目标在于,对于一个容器中的各个项目块 ...
- Android之分页加载数据
基本的原理和我的上一篇随笔“Android之下拉刷新ListView”差不多,代码里面有注释,这里就不废话了,直接上代码. 自定义的分页显示ListView——PagedListView.java代码 ...
- ASP.NET 验证码控件
public class ValidateCode : WebControl { /// <summary> /// 默认构造函数,暴露的属性接口 /// </summary> ...
- 【bzoj1700】Problem Solving 解题
题目描述 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地说,他们有P (1 <= P <= 300) 道题目要做. 他们还离开了农场并且象普通人一 ...
- Python 局部变量与全局变量
本来以为 局部变量就是在函数/def/class/lambda内部的变量,全局变量就是在之前这些之外的变量.但是,再一次学习Python atm 中应用时发现了一次特例(意外) 字典中 在函数内部改变 ...
- C#RSA算法实现+如何将公钥为XML格式转为PEM格式,给object-C使用
.net中,处于安全的考虑,RSACryptoServiceProvider类,解密时只有同时拥有公钥和私钥才可以.原因是公钥是公开的,会被多人持有.这样的数据传输是不安全的.C#RSA私钥加密,公钥 ...
- .Net Framework认知
在托管代码的世界里,应用程序首先被加载到应用程序域(AppDomain)中,然后将应用程序域加载到进程中,一个进程可以包含多个应用程序域,也就是说一个进程可以包含多个应用程序,毕竟应用程序域之间的切换 ...
- Rails 5 开发进阶
Rails 5 开发进阶:https://www.gitbook.com/book/kelby/rails-beginner-s-guide/details cancan : http://blo ...
- rocketmq生产者和消费者
1.生产者: package com.ebways.mq.test.mq; import com.alibaba.rocketmq.client.exception.MQClientException ...
- 编译安装 varnish-4.1.2和yum 安装 varnish-4.0.3
vanish可以让用户自己选择缓存数据是存于内存还是硬盘,存于内存一般基于二八法则即常访问的数据是磁盘存储的总数据五分之一,因此内存也应该是硬盘文件大概五分之一.如果有多台vanish则,总内存满足即 ...