Linux学习记录–匿名管道通信

匿名管道通讯

管道是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);//1write(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

规则分析3switch (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

规则分析4switch (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

再怎么风光明媚的自家山川,

Linux学习记录–匿名管道通信

相关文章:

你感兴趣的文章:

标签云: