无名管道和有名管道区别
【最新精选】有名管道(FIFO)

2.10. 有名管道(FIFO)能做什么?2.10.1. 什么是有名管道?有名管道是一个能在互不相关进程之间传送数据的特殊文件。
一个或多个进程向内写入数据,在另一端由一个进程负责读出。
有名管道是在文件系统中可见的,也就是说ls可以直接看到。
(有名管道又称FIFO,也就是先入先出。
)有名管道可以将无关的进程联系起来,而无名的普通管道一般只能将父子进程联系起来——除非你很努力地去尝试——当然也能联系两个无关进程。
有名管道是严格单向的,尽管在一些系统中无名管道是双向的。
2.10.2. 我如何建立一个有名管道?在shell下交互地建立一个有名管道,你可以用mknod或mkfifo命令。
在有些系统中,mknod产生的文件可能在/etc目录下,也就是说,可能不在你的目录下出现,所以请查看你系统中的man手册。
[译者注:在Linux下,可以看一下fifo(4)]要在程序中建立一个有名管道:/* 明确设置umask,因为你不知道谁会读写管道 */umask(0);if (mkfifo("test_fifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGR P)){perror("mkfifo");exit(1);}也可以使用mknod。
[译者注:在Linux下不推荐使用mknod,因为其中有许多臭虫在NFS下工作更要小心,能使用mkfifo就不要用mknod,因为mkfifo()是POSIX.1 标准。
]/* 明确设置umask,因为你不知道谁会读写管道 */umask(0);if (mknod("test_fifo",S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,0)){perror("mknod");exit(1);}2.10.3. 我如何使用一个有名管道?使用有名管道十分简单:你如同使用一个普通文件一样打开它,用read()和write()进行操作。
进程间通信方式特点

进程间通信⽅式特点
1.⽆名管道( pipe ):管道是⼀种半双⼯的通信⽅式,数据只能单向流动,⽽且只能在具有亲缘关系的进程间使⽤。
进程的亲缘关系通常是指⽗⼦进程关系。
2.⾼级管道(popen):将另⼀个程序当做⼀个新的进程在当前程序进程中启动,则它算是当前程序的⼦进程,这种⽅式我们成为⾼级管道⽅式。
3.有名管道 (named pipe) :有名管道也是半双⼯的通信⽅式,但是它允许⽆亲缘关系进程间的通信。
4.消息队列( message queue ) :消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
消息队列克服了信号传递信息少、管道只能承载⽆格式字节流以及缓冲区⼤⼩受限等缺点。
5.信号量( semophore ) :信号量是⼀个计数器,可以⽤来控制多个进程对共享资源的访问。
它常作为⼀种锁机制,防⽌某进程正在访问共享资源时,其他进程也访问该资源。
因此,主要作为进程间以及同⼀进程内不同线程之间的同步⼿段。
6.信号 ( sinal ) :信号是⼀种⽐较复杂的通信⽅式,⽤于通知接收进程某个事件已经发⽣。
7.共享内存( shared memory ) :共享内存就是映射⼀段能被其他进程所访问的内存,这段共享内存由⼀个进程创建,但多个进程都可以访问。
共享内存是最快的 IPC ⽅式,它是针对其他进程间通信⽅式运⾏效率低⽽专门设计的。
它往往与其他通信机制,如信号两,配合使⽤,来实现进程间的同步和通信。
8.套接字( socket ) :套解字也是⼀种进程间通信机制,与其他通信机制不同的是,它可⽤于不同机器间的进程通信。
Linux进程通信-无名管道与有名管道

Linux进程通信-⽆名管道与有名管道⽆名管道(PIPE)和有名管道(FIFO)都是UNIX进程间通信(InterProcess Communication,简称IPC)的⼿段。
⽆名管道PIPE管道特点管道通常指⽆名管道,是IPC最古⽼的形式。
管道有何特点?1. 半双⼯通信,具有固定的读端、写端(单向传输数据);2. 管道只能在具有公共祖先的2个进程间使⽤,通常是⽗⼦进程;管道的创建管道由pipe函数创建,见#include <unistd.h>/* fd返回2个⽂件描述符:fd[0]为读⽽打开;fd[1]为写⽽打开。
fd[1]的输出是fd[0]的输⼊ */int pipe(int fd[2]);/* 提供位元选项可设置。
flags=0时,pipe2同pipe。
* 常⽤选项:O_NONBLOCK*/int pipe2(int fd[2], int flags);通过fd[0]调⽤read()读取数据的⼀端,叫读端;通过fd[1]调⽤write()写数据的⼀端进程,叫写端。
通常的创建模型:int pipefd[2];ret = pipe(pipefd);fork();管道的状态同⼀个进程使⽤管道没有意义,因为管道专门⽤于进程间通信。
进程内的通信使⽤全局变量即可。
要实现⽗⼦进程的通信,创建管道后,需要关闭⼀个读端,⼀个写端。
⽐如⼀个从⽗进程到⼦进程的管道,⽗进程关闭fd[0],⼦进程关闭fd[1]。
单进程半双⼯管道(⽆意义状态)fork⼦进程后的半双⼯管道(创建后的初始状态)⽗进程到⼦进程的管道(理想状态)管道的使⽤规则当管道的⼀端被关闭后,下⾯的规则起作⽤:1. 读端和写端都可以对应多个进程,但通常⼀个管道只有⼀个读进程和⼀个写进程;2. 当读⼀个写端已关闭的管道时,在所有数据都被读取后,read返回0,表⽰⽂件结束(只要还有⼀个写端还有进程,就不会产⽣⽂件的结束);3. 如果写⼀个读端已关闭的管道,会产⽣信号SIGPIPE。
无名管道和有名管道创建通信原理

无名管道和有名管道创建通信原理
无名管道和有名管道是操作系统中常见的进程间通信方式。
无名管道只能在父子进程或者兄弟进程之间通信,而有名管道则可以在不相关的进程之间通信。
在创建管道时,操作系统会为管道创建一个缓冲区,进程可以将数据写入缓冲区或者从缓冲区读取数据。
无名管道和有名管道的创建通信原理是类似的,下面分别介绍。
1. 无名管道创建通信原理
无名管道是通过调用系统调用pipe()来创建的。
该函数会返回两个文件描述符,分别用于读取和写入管道。
在父进程中创建管道后,可以通过fork()创建子进程,并把管道文件描述符传递给子进程。
这样,父进程和子进程就可以通过管道进行通信了。
父进程写入数据时,会将数据写入管道缓冲区中,并通知管道读取进程可以读取数据了。
子进程读取数据时,会从管道缓冲区中读取数据并进行处理。
2. 有名管道创建通信原理
有名管道是通过调用系统调用mkfifo()来创建的。
该函数会创建一个文件,并返回文件描述符。
进程可以像操作普通文件一样对有名管道进行读写操作。
不同的是,当进程写入数据时,数据会被放入管道缓冲区中,并等待其他进程进行读取。
多个进程可以同时对同一个有名管道进行读写操作。
当有进程向管道写入数据时,其他进程可以通过读取管道来获取数据。
总结:无名管道和有名管道都是通过操作系统提供的系统调用来
创建的。
无名管道只能在父子进程或兄弟进程之间通信,而有名管道可以在不相关的进程之间通信。
管道创建后,进程可以通过文件描述符对管道进行读写操作,实现进程间通信。
linux管道通信(C语言)

char buf_r[200];
memset(buf_r,0,sizeof(buf_r));
if(pipe(pipe_fd)<0;
return -1;
}
result=fork();
if(result<0){
printf("创建子进程失败");
Linux系统提供了丰富的进程通信手段,如信号、信号灯、管道、共享内存、消息队列等,能有效地完成多个进程间的信息共享和数据交换。管道作为最早的进程间通信机制之一,可以在进程之间提供简单的数据交换和通信功能。
2 管道技术简介
2.1 管道的概念及特点
管道分为无名管道和有名管道两种。无名管道可用于具有亲缘关系进程间的通信,如父子进程、兄弟进程。有名管道克服了管道没有名字的限制,允许无亲缘关系进程间的通信。本文应用的是无名管道通信机制。
exit(0);
}
else{
close(pipe_fd[0]);
if(write(pipe_fd[1],"**Hello world !**",17)!=-1)
printf("父进程向管道写入**Hello world !**\n");
if(write(pipe_fd[1]," **Welcome !**",15)!=-1)
命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。
接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。
有名管道和无名管道

实验七有名管道和无名管道1.实验目的(1)理解进程通信机制中有名管道和无名管道的实现原理(2)掌握管道的建立、读、写等函数的使用(3)掌握有名管道和无名管道实现进程之间的通信2.实验环境已安装Linux操作系统的微机一台3.实验内容编写程序:(1) 编写管道通信程序:要求主进程创建子进程后,在子进程中调用exec函数执行一个新程序前,通过管道给即将执行的程序传递命令行参数,包括:exit,子进程退出;getpid,获取进程号等。
(2)编写有名管道程序:实现写进程获得从键盘输入的数据,读进程获得从写进程端读的数据并显示在屏幕中。
○1源代码:#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){int pid;int pd[2];char msg_rec[10];char* message;if(pipe(pd)==-1)perror("pipe");pid=fork();if(pid==-1)perror("fork");else if(pid==0){//message="exit";message="getpid";// printf("send exit\n");printf("send getpid\n");printf("pid=%d\n",getpid());write(pd[1],message,10);exit(EXIT_SUCCESS);}else if(pid>0){sleep(1);if((read(pd[0],msg_rec,10))==-1){perror("read"); exit(EXIT_FAILURE);}printf("%s\n",msg_rec);execl("./newcode","newcode",msg_rec,(void*)0);printf("%s\n",msg_rec);exit(1);wait(NULL);}return 0;}程序的运行结果如下所示:○2源代码:#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<stdio.h>#define FIFO "/tmp/fifo"main(){pid_t pid;char buffer[80];int fd;unlink(FIFO);mkfifo(FIFO,0744);if(pid=fork()>0){fd=open(FIFO,O_WRONL Y);fgets(buffer,sizeof(buffer),stdin);write(fd,buffer,sizeof(buffer));printf("this is father write data is %s",buffer);printf("father's pid is %d\n",getpid());close(fd);exit(EXIT_SUCCESS);}else if(pid==0){sleep(2);fd=open(FIFO,O_RDONL Y);read(fd,buffer,80);printf("this is child read data is:%s\n",buffer);close(fd);printf("child's pid is %d\n",getpid());exit(EXIT_SUCCESS);}else{perror("fork");exit(EXIT_FAILURE);}}程序运行结果如下所示:4.实验总结通过本次实验理解了进程通信机制中有名管道和无名管道的实现原理,有名管道和无名管道实现通信的区别,以及文件描述符重定向和流重定向;掌握了管道的建立、读、写等函数的使用,掌握了有名管道和无名管道实现进程之间的通信。
ipc方案

IPC方案引言Inter-Process Communication (IPC),即进程间通信,是指在多个进程之间交换数据和信息的机制。
在计算机系统中,不同的进程可能需要相互协作以完成特定任务或实现某种功能。
IPC方案提供了一种可靠、高效地实现进程间通信的方式,使得不同进程能够安全地共享数据和资源。
本文将介绍几种常见的IPC方案,并对它们的特点和适用场景进行分析。
需要注意的是,每种IPC方案都有其适用的领域和优势,开发者应根据具体需求来选择最合适的方案。
1. 管道(Pipe)管道是一种IPC方式,用于在父子进程之间进行通信。
在Unix和Linux系统中,管道是一种特殊的文件,用于传输数据。
管道分为无名管道(匿名管道)和有名管道两种。
1.1 无名管道无名管道是进程间通信的简单方式,只能在有亲缘关系的进程之间进行通信。
一个无名管道有两个端点,一个读端口和一个写端口。
一个进程可以将数据写入管道的写端口,另一个进程则可以从管道的读端口读取数据。
无名管道的优势是实现简单,不需要额外的系统调用,适用于需要简单的双向通信的场景。
然而,无名管道只能在有亲缘关系的进程之间通信,且数据只能单向传输。
同时,无名管道也有一定的限制,如数据传输的大小受限,不能用于非阻塞传输等。
1.2 有名管道有名管道是一种命名的FIFO文件,可以在不相关的进程之间进行通信。
相比于无名管道,有名管道更灵活,可以实现非亲缘关系进程之间的通信。
有名管道的创建和使用需要使用mkfifo系统调用,在文件系统中创建一个FIFO文件。
创建后,进程可以像读写普通文件一样,通过FIFO文件进行通信。
需要注意的是,有名管道是按字节流方式进行数据传输的,不像无名管道可以自动进行块读取和写入。
有名管道的优势在于实现简单,能在不相关的进程之间实现双向通信。
然而,相比于无名管道,有名管道的创建和使用需要更多的系统调用,同时在使用时也可能需要实现同步机制和错误处理。
计算机操作系统(第四版)汤小丹课后答案完整版

计算机操作系统(第四版)汤小丹课后答案完整版答:(1)发送者A 可用自己的私用密钥Kda对明文P进行加密,得到密文DKda(P)。
(2)A 再用B的公钥Keb对DKda (P)加密,得到EKeb(DKda(P))后送B。
(3)B收到后,先用私钥Kdb解密,得到DKda(EKeb(DKda(P)))=DKda (P)。
(4)B再用A的公钥Kea 对DKda(P)解密,得到EKeb(DKda(P))=P。
10.数字证明书的作用是什么?用一例来说明数字证明书的申请、发放和使用过程。
答:数字证明书又称公钥证明书,用于证明通信请求者的身份。
数字证明书的申请、发放和使用过程如下:(1) 用户A 先向CA申请数字证明书,A 应提供身份证明和希望使用的公钥A。
(2) CA 收到A 发来的申请报告后,若接受申请,便发给A 一份数字证明书,其中包括公钥A 和CA 发证者的签名等信息,并对所有信息利用CA 私钥加密(即对CA 进行数字签名)。
(3) 用户 A 在向B 发送信息时,由A用私钥对报文加密(数字签名),连同证明书发给B。
(4) 为能对收到的数字证明书解密,用户B须向CA 申请获得CA 的公钥B。
CA 收到用户 B 的申请后,可决定将公钥B发给用户B。
(5) 用户B 利用CA 公钥B 对数字证明书解密,确认该数字证明书系原件,并从数字证明书中获得公钥A,并且确认该公钥A系用户A的密钥。
(6) 用户B再利用公钥A 对用户A 发来的加密报文解密,得到用发来报文的真实明文。
11.何谓链路加密?其主要特点是什么?答:链路加密是对网络相邻节点间的通信线路上传输的数据的加密过程。
特点是:(1)相邻节点间的物理信道上传输的报文是密文,在所有中间节点上的报文则是明文。
(2)对不同的链路分别采用不同的加密密钥。
12.何谓端-端加密?其主要特点是什么?答:端-端加密是在源主机或前端机FEP高层(从传输层到应用层)对传输数据进行的加密。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2011-06-08 21:45linux 管道 FIFO——写的很全,转来的pipe是Linux中最经典的进程间通信手段,在终端里通常用来组合命令,例如“ls -l|wc -l”。
它的作用很直观,就是使得前一个进程的输出作为后一个进程的输入,在概念上很符合“管道”的意思。
用管道实现“ls -l | wc -l”《情景分析》上有这个例子的代码,我觉得很适合用来了解管道。
这里假设终端对应的进程为PA,wc、ls是PA先后创建的两个子进程child_B与child_C。
代码简化后抄录如下:int main(){int pipefds[2], child_B, child_C;pipe(pipefds);if (!(child_B=fork()){ //先创建“读”的一端,它要关闭“写”的的一端close(pipefds[1]);close(0);dup2(pipefds[0], 0); //在执行系统调用execve后,child_B会释放0,1,2之外由父进程打开的文件,close(pipefds[0]); //所以要把pipefds[0]复制到标准输入对应的文件句柄0 execl("/usr/bin/wc", "-l", NULL);} //这里之后,A和B可以通过管道进行通信close(pipefds[0]);if (!(child_C=fork()){ //再创建“写”的一端,它要关闭“读”的的一端close(1);dup2(pipefds[1],1); //道理同前面close(pipefds[1]);execl("/bin/ls", "-1", NULL);} //这里之后,B和C可以通过管道进行通信close(pipefds[1]);wait4(child_B, NULL, 0, NULL);return 0;}FIFOFIFO就是命名管道,或有名管道。
对于pipe我们不难看出它只能用于一个进程家族之间通信,父子之间,兄弟之间等等。
如果想要让管道在更宽泛的环境中,那是不行的,原因是它没有“名字”或者说是匿名的,另外的进程看不到它,这样就有了命名管道。
它同样是基于VFS,对应的文件类型就是FIFO文件,可以通过mknod命令在磁盘上创建一个FIFO文件(注意:这就是它与pipe的本质区别,pipe完全就是存在与内存中,在磁盘上毫无痕迹),当进程想通过该FIFO 来通信时就可以标准的API open打开该文件,然后开始读写操作。
对于FIFO 的读写实现,它与pipe是相同的。
区别在于,FIFO有open这一操作,而pipe 是在调用pipe这个系统调用时直接创建了一对文件描述符用于通信。
并且,FIFO 的open操作还有些细致的地方要考虑,例如如果写者先打开,尚无读者,那么肯定是不能通信了,所以就需要先去睡眠等待读者打开该FIFO,反之对读者亦然。
管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别。
有名管道叫named pipe或者FIFO(先进先出),可以用函数mkfifo()创建。
Linux管道的实现机制在Linux中,管道是一种使用非常频繁的通信机制。
从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为:· 限制管道的大小。
实际上,管道是一个固定大小的缓冲区。
在Linux中,该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。
使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。
· 读取进程也可能工作得比写进程快。
当所有当前进程数据已被读取时,管道变空。
当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。
注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。
1. 管道的结构在 Linux 中,管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。
通过将两个 file 结构指向同一个临时的VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。
2.管道的读写管道实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即管道读函数pipe_read()和管道写函数 pipe_wrtie()。
管道写函数通过将字节复制到 VFS 索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。
当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用了锁、等待队列和信号。
当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的 file 结构。
file 结构中指定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。
写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作:·内存中有足够的空间可容纳所有要写入的数据;·内存没有被读程序锁定。
如果同时满足上述条件,写入函数首先锁定内存,然后从写进程的地址空间中复制数据到内存。
否则,写入进程就休眠在 VFS 索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。
写入进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写入数据,或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接收到信号。
当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤醒。
管道的读取过程和写入过程类似。
但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,这依赖于文件或管道的打开模式。
反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。
当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放。
因为管道的实现涉及很多文件的操作,因此,当读者学完有关文件系统的内容后来读pipe.c中的代码,你会觉得并不难理解。
Linux 管道的创建和使用都要简单一些,唯一的原因是它需要更少的参数。
实现与 Windows 相同的管道创建目标,Linux 和 UNIX 使用下面的代码片段:创建 Linux 命名管道int fd1[2];if(pipe(fd1)){ printf("pipe() FAILED: errno=%d",errno);return 1;}Linux 管道对阻塞之前一次写操作的大小有限制。
专门为每个管道所使用的内核级缓冲区确切为 4096 字节。
除非阅读器清空管道,否则一次超过 4K 的写操作将被阻塞。
实际上这算不上什么限制,因为读和写操作是在不同的线程中实现的。
Linux 还支持命名管道。
对这些数字的早期评论员建议我,为公平起见,应该比较 Linux 的命名管道和 Windows 的命名管道。
我写了另一个在 Linux 上使用命名管道的程序。
我发现对于 Linux 上命名的和未命名的管道,结果是没有区别。
Linux 管道比 Windows 2000 命名管道快很多,而 Windows 2000 命名管道比 Windows XP 命名管道快得多。
例子:#include<stdio.h>#include<unistd.h>int main(){int n,fd[2]; // 这里的fd是文件描述符的数组,用于创建管道做准备的pid_t pid;char line[100];if(pipe(fd)<0) // 创建管道printf("pipe create error\n");if((pid=fork())<0) //利用fork()创建新进程printf("fork error\n");else if(pid>0){ //这里是父进程,先关闭管道的读出端,然后在管道的写端写入“hello world"close(fd[0]);write(fd[1],"hello word\n",11);}else{close(fd[1]); //这里是子进程,先关闭管道的写入端,然后在管道的读出端读出数据n= read(fd[0],line,100);write(STDOUT_FILENO,line,n);}exit(0);}备注:管道分为无名管道和有名管道,其中无名管道不属于任何文件系统,只存在于内存中,它是无名无形的,但是可以把它看作一种特殊的文件,通过使用普通文件的read(),write()函数对管道进行操作,有名管道是有名有形的,为了使用这种管道,LINUX中设立了一个专门的特殊文件系统--管道文件,它存在于文件系统中,任何进程可以在任何时候通过有名管道的路径和文件名来访问管道。
但是在磁盘上的只是一个节点,而文件的数据则只存在于内存缓冲页面中,与普通管道一样。