匿名沟通渠道

管道Linux最初支持Unix IPC其中的一种形式。具有下列特征:

1.管道是半双工。数据可以仅在一个方向流动;当双方需要沟通。建设两条管线需要。

2.仅仅能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

什么是管道

管道对于管道两端的进程而言,就是一个文件。但它不是普通的文件,它不属于某种文件系统。而是自立门户,单独构成一种文件系统,而且仅仅存在与内存中。

数据的读出和写入

一个进程向管道中写的内容被管道还有一端的进程读出。写入的内容每次都加入在管道缓冲区的末尾。而且每次都是从缓冲区的头部读出数据。

管道的创建

#include int pipe(int fd[2])

管道两端可分别用描写叙述字fd[0]以及fd[1]来描写叙述,须要注意的是,管道的两端是固定了任务的。即一端仅仅能用于读,由描写叙述字fd[0]表示,称其为管道读端;还有一端则仅仅能用于写,由描写叙述字fd[1]来表示,

管道的规则

1.      当管道内容长度为0时,读端将处于堵塞状态,等待写端向管道写入内容

2.      当写端数据长度小于缓冲区长度时。数据将以原子性写入缓冲区。

对读进程来说:

3.      当写端被关闭时。全部数据被读出后,read返回0。

4.      当写端未被关闭时。全部数据被读出后。读端堵塞。

对写进程来说:

5.      当读端关闭时,如写端数据长度大于管道最大长度时,写完管道长度时。产生信号SIGPIPE后退出程序。

(以存入管道的数据读进程能够读取到)

6.      当读端未被关闭时。如写端数据长度大于管道最大长度时,写完管道长度时,写端将处于堵塞状态

规则分析1

#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/wait.h> int main() {
int fd[2];
pid_t cid; if (pipe(fd) == -1) {
perror("管道创建失败! ");
exit(1);
}
cid = fork();
switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
close(fd[1]);
char message[1000];
int num = read(fd[0], message, 1000);
printf("子进程读入的数据是:%s,长度是=%d", message, num);
close(fd[0]);
break;
default:
close(fd[0]);
char *writeMsg = "父进程写入的数据! ";
sleep(10);//1
write(fd[1], writeMsg, strlen(writeMsg));
close(fd[1]);
break;
}
return 0;
}

[root@ Release 18$] ps -C processcomm -opid,ppid,stat,cmd

PID  PPID STAT CMD

5973 2488 S   /root/workspace/processcomm/Release/processcomm

5976 5973 S   /root/workspace/processcomm/Release/processcomm

=>读端因为堵塞中。其所在进程(子进程)处于sleep状态

控制台输出

父进程工作PID=5973,PPID=2488

子进程工作PID=5976,PPID=5973

子进程读入的数据是:父进程写入的数据!

,长度是=27

规则分析2

switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); close(fd[0]);
const long int writesize=4000;
char writeMsg[writesize];
int i;
for(i=0;i<writesize;i++)
{
writeMsg[i]='a';
}
int writenum=write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[1]);
wait(NULL);
break;
}

控制台输出

父进程工作PID=7072,PPID=2488

父进程写入的数据长度是=4001

子进程工作PID=7077,PPID=7072

规则分析3

switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[40001];
int num = read(fd[0], message, 4001);
printf("子进程读入的数据长度是=%d\n", num);
num = read(fd[0], message, 4000);
printf("子进程再次读入的数据长度是=%d", num);
close(fd[0]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); close(fd[0]);
const long int writesize = 4000;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize; i++) {
writeMsg[i] = 'a';
}
int writenum = write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[1]);
// wait(NULL);
break;
}

[root@ Release30$] ps -C processcomm -o pid,ppid,stat,cmd

PID PPID STAT CMD

=>读写进程都已退出

控制台输出

父进程工作PID=8004,PPID=2488

父进程写入的数据长度是=4001

子进程工作PID=8009,PPID=1

子进程读入的数据长度是=4001

子进程再次读入的数据长度是=0

规则分析4

switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
char message[40001];
int num = read(fd[0], message, 4001);
printf("子进程读入的数据长度是=%d", num);
num = read(fd[0], message, 4000);
printf("子进程再次读入的数据长度是=%d", num);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[0]);
const long int writesize = 4000;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize; i++) {
writeMsg[i] = 'a';
}
int writenum = write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[1]);
break;
}

[root@ Release29$] ps -C processcomm -o pid,ppid,stat,cmd

PID PPID STAT CMD

7916    1 S   /root/workspace/processcomm/Release/processcomm

=>读进程堵塞

控制台输出:

父进程工作PID=7914,PPID=2488

父进程写入的数据长度是=4001

子进程工作PID=7916,PPID=1

规则分析5

switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[65535];
int num = read(fd[0], message, 65535);
printf("子进程读入的数据长度是=%d", num);
close(fd[0]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); close(fd[0]);
const long int writesize = 80000;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize; i++) {
writeMsg[i] = 'a';
}
int writenum = write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[1]);
wait(NULL);
break;
}

[root@ Release25$] ps -C processcomm -o pid,ppid,stat,cmd

PID PPID STAT CMD

=>全部进程都以退出

控制台输出

父进程工作PID=7776,PPID=2488

子进程工作PID=7778,PPID=7776

子进程读入的数据长度是=65535

规则分析6

switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
const long int writesize=80000;
char writeMsg[writesize];
int i;
for(i=0;i<writesize;i++)
{
writeMsg[i]='a';
}
int writenum=write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum);
wait(NULL);
break;
}

父进程工作PID=7309,PPID=2488

子进程工作PID=7314,PPID=7309

[root@ Release24$] ps -C processcomm -o pid,ppid,stat,cmd

PID PPID STAT CMD

7309 2488 S   /root/workspace/processcomm/Release/processcomm

7314 7309 Z    [processcomm]<defunct>

管道代码举例

1.   当发送信息小于管道最大长度

#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/wait.h> int main() {
int fd[2];
pid_t cid; if (pipe(fd) == -1) {
perror("管道创建失败!");
exit(1);
}
cid = fork();
switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[1000];
int num;
do { num = read(fd[0], message, 1000);
printf("子进程读入的数据长度是=%d\n", num);
} while (num != 0); close(fd[0]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[0]);
const long int writesize = 37;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize-1; i++) {
writeMsg[i] = 'a';
}
writeMsg[writesize-1]='\0';
int writenum = write(fd[1], writeMsg, strlen(writeMsg)+1);
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[1]);
break;
}
return 0;
}

2.   当发送信息大于管道最大长度

此样例主要应该规则6。当发送信息大于管道长度时且写进程在未所有将新数据写入管道中。写进程处于堵塞状态。直到所有数据写入管道

int main() {
int fd[2];
pid_t cid; if (pipe(fd) == -1) {
perror("管道创建失败。");
exit(1);
}
cid = fork();
switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[1000];
int num;
do {
num = read(fd[0], message, 1000);
printf("子进程读入的数据长度是=%d\n", num);
}while(num!=0); close(fd[0]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); const long int writesize = 80000;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize-1; i++) {
writeMsg[i] = 'a';
}
writeMsg[writesize-1]='\0';
int writenum = write(fd[1], writeMsg, strlen(writeMsg)+1);
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[0]);
close(fd[1]);
break;
}
return 0;
}

3.   写进程多次写入

此例应用规则6,防止多次写入,写入数据长度管道最大长度

int main() {
int fd[2];
pid_t cid; if (pipe(fd) == -1) {
perror("管道创建失败。");
exit(1);
}
cid = fork();
switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[1000];
int num;
do {
num = read(fd[0], message, 1000);
if (num > 0) {
printf("子进程读入的数据长度是=%d %s\n", num, message);
} } while (num != 0); close(fd[0]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); const long int writesize = 10;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize - 1; i++) {
writeMsg[i] = 'a';
}
writeMsg[writesize - 1] = '\0';
int writenum = write(fd[1], writeMsg, strlen(writeMsg));
printf("父进程写入的数据长度是=%d\n", writenum); char *newmsg = "helloworld";
writenum = write(fd[1], newmsg, strlen(newmsg) + 1);
printf("父进程再次写入的数据长度是=%d\n", writenum);
close(fd[0]);
close(fd[1]);
break;
}
return 0;
}

4.   兄弟间的管道通讯

int main() {
int fd[2];
pid_t cid, did; if (pipe(fd) == -1) {
perror("管道创建失败!");
exit(1);
}
cid = fork();
switch (cid) {
case -1:
perror("兄进程创建失败");
exit(2);
break;
case 0:
printf("兄进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[1000];
int num;
do {
num = read(fd[0], message, 1000);
if (num > 0) {
printf("兄进程读入的数据长度是=%d,%s\n", num, message);
} } while (num != 0); close(fd[0]);
break;
default:
did = fork();
if (did == 0) {
printf("弟进程工作PID=%d,PPID=%d\n", getpid(), getppid()); const long int writesize = 10;
char writeMsgs[writesize];
int i;
for (i = 0; i < writesize - 1; i++) {
writeMsgs[i] = 'a';
}
writeMsgs[writesize - 1] = '\0';
int writenum = write(fd[1], writeMsgs, strlen(writeMsgs) + 1);
printf("弟进程写入的数据长度是=%d\n", writenum);
close(fd[0]);
close(fd[1]);
} else if (did == -1) {
perror("弟进程创建失败!");
exit(3); } break;
}
return 0;
}

5.   父子双通道管道通讯

int main() {
int fd[2], backfd[2];
pid_t cid; if (pipe(fd) == -1) {
perror("管道创建失败!");
exit(1);
}
if (pipe(backfd) == -1) {
perror("管道创建失败!");
exit(2);
}
cid = fork();
switch (cid) {
case -1:
perror("子进程创建失败");
exit(2);
break;
case 0:
printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
close(fd[1]);
char message[10000];
int num; do { num = read(fd[0], message, 10000);
printf("子进程读入的数据长度是=%d\n", num);
} while (num != 0); close(fd[0]); close(backfd[0]);
char *msg1 = "消息返回成功啊! ";
write(backfd[1], msg1, strlen(msg1) + 1);
close(backfd[1]);
break;
default:
printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid()); const long int writesize = 80000;
char writeMsg[writesize];
int i;
for (i = 0; i < writesize - 1; i++) {
writeMsg[i] = 'a';
}
writeMsg[writesize - 1] = '\0';
int writenum = write(fd[1], writeMsg, strlen(writeMsg) + 1);
printf("父进程写入的数据长度是=%d\n", writenum);
close(fd[0]);
close(fd[1]);
close(backfd[1]);
char msg2[1000];
int num1 = read(backfd[0], msg2, 1000);
printf("返回消息:%s", msg2);
close(backfd[0]);
break;
}
return 0;
}

Linux学习记录--匿名沟通渠道的更多相关文章

  1. linux学习记录(第六章、Linux 的文件权限与目录配置)

    书看的是鸟哥的私房菜,系统用的是centos.被微软坑了N年才发现linux才是王道. 在这里记录些学习的记录.备忘

  2. Linux 学习记录 一(安装、基本文件操作).

         Linux distributions主要分为两大系统,一种是RPM方式安装软件的系统,包括Red Hat,Fedora,SuSE等都是这类:一种则是使用Debian的dpkg方式安装软件的 ...

  3. Linux 学习记录一(安装、基本文件操作).

    Linux 名字的由来,是当时作者将初版的 Linux 发布在网上,供别人下载完善,而那个核心文件夹就叫 Linux,就这么叫着了.而为什么 Linux 的吉祥物是一只企鹅呢?是因为当时大家要发行稳定 ...

  4. Linux学习记录

    ---恢复内容开始--- linux与unix的关系 linux是借鉴了unix设计思想,也称linux位类unix系统. Linux常用命令 1.命令基本格式 命令[选项][参数] 注意:个别命令不 ...

  5. Linux 学习记录

    整理学习Linux操作系统遇到的不理解的概念.逐个进行补充.我们用的版本是CentOs. what's the gcc? what's the yum? what's the wget?

  6. Linux学习记录--命名管道通信

    命名管道通信 什么是命名管道 一个主要的限制是,它是匿名管道的应用还没有名字,因此,只有它可以用于进程间通信的方式与亲缘关系.在命名管道(named pipe或FIFO)提出后,该限制得到了克服.FI ...

  7. Linux 学习记录 20170218

    一.Linux 硬件查看命令     ----/proc 文件系统是一种内核和内核模块用来向进程(process) 发送信息的机制.我们可以从这个文件里获取到系统的相关信息. 1.显卡信息dmesg ...

  8. linux学习记录.1.安装

    最近想了想决定开始学习linux. 在百度了一番后开始了安装,虚拟机VirtualBox,ubuntu. 基于VirtualBox虚拟机安装Ubuntu图文教程: http://blog.csdn.n ...

  9. Linux学习记录(一)

    1.Linux的简介 1.1.Linux的概述 Linux是基于Unix的开源免费的操作系统,由于系统的稳定性和安全性几乎成为程序代码运行的最佳系统环境.Linux是由Linus Torvalds(林 ...

随机推荐

  1. 【HTTP 2】 序言

    笔者序 HTTP 2 这个关键词在各大 IT 网站出现频率节节升高,然而出现在大家视野里的,仍以浅析居多.虽有一部分实战(如 InfoQ 之前推送的 iOS App 网络层次架构优化),但针对 HTT ...

  2. Hadoop 2.x(YARN)安装配置LZO

    今天尝试在Hadoop 2.x(YARN)上安装和配置LZO,遇到了很多坑,网上的资料都是基于Hadoop 1.x的,基本没有对于Hadoop 2.x上应用LZO,我在这边记录整个安装配置过程 1. ...

  3. 神奇的矩阵 NOI模拟题

    神奇的矩阵 题目大意 有一个矩阵\(A\),第一行是给出的,接下来第\(x\)行,第\(y\)个元素的值为数字\(A_{x-1,y}\)在\(\{A_{x-1,1},A_{x-1,2},A_{x-1, ...

  4. UVA - 10057 A mid-summer night&#39;s dream.

    偶数时,中位数之间的数都是能够的(包含中位数) 奇数时,一定是中位数 推导请找初中老师 #include<iostream> #include<cstdio> #include ...

  5. 多模块Maven项目怎样使用javadoc插件生成文档

    需求 近期要对一个项目结构例如以下的Maven项目生成JavaDoc文档. Project                         |-- pom.xml                   ...

  6. C#根据域名查询IP(CMD命令参数输入或者启动程序后再输入查询)

    有时因为需要,希望知道域名的IP,那用C#怎么实现呢?以下是实现代码 using System; using System.Collections.Generic; using System.Linq ...

  7. 说说关于php内置函数curl_init()

    昨天在我本地的项目,调试时碰到无法识别curl_init()方法,网上查了查才知道是我本地的php.ini文件里没加载上,完了把extension=php_curl.dll前面的;去掉后就好了,注意一 ...

  8. 一个故事讲清楚NIO(转)

    转载请引用:一个故事讲清楚NIO 假设某银行只有10个职员.该银行的业务流程分为以下4个步骤: 1) 顾客填申请表(5分钟): 2) 职员审核(1分钟): 3) 职员叫保安去金库取钱(3分钟): 4) ...

  9. [置顶] 正则表达式应用:匹配email地址

           email的组成主要有三部分         1用户名部分 2@   3域名部分        1用户名部分         用户名一般有数值字母下划线组成,所以正则表达式为:[\da- ...

  10. 每天4个linux命令--步骤一

     1 :Linux的诞生 Linux由芬兰赫尔辛基大学的Linus Torvalds创建 1991年10月,Linux第一个公开版 0.02版发布 1994年3月,Linux 1.0版发布 Linus ...