无名管道可以使用lseek函数返回值吗

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
#include &sys/types.h&#include &unistd.h&off_t lseek(int fd, off_t offset, int whence);所有打开的文件都有一个当前文件偏移量&(current file offset),以下简称为 cfo。cfo 通常是一个非负整数&,用于表明文件开始处到文件当前位置的字节数&。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了&O_APPEND&。&&& 使用 lseek 函数可以改变文件的 cfo 。&&&&&&& #include&&&unistd.h&&&&&&&& off_t lseek(int filedes, off_t offset, int whence);&&&&&&&&&&&&&&&&&&& 返回值:新的偏移量(成功),-1(失败)参数 offset 的含义取决于参数 whence:&&& 1. 如果 whence 是&SEEK_SET&,文件偏移量将被设置为 offset。&&& 2. 如果 whence 是&SEEK_CUR&,文件偏移量将被设置为 cfo 加上 offset,&&&&&& offset 可以为正也可以为负。&&& 3. 如果 whence 是&SEEK_END&,文件偏移量将被设置为文件长度加上 offset,&&&&&& offset 可以为正也可以为负。SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在这之前使用的是 0、1 和 2。&&& lseek 的以下用法返回当前的偏移量&:&&&&&&& off_t&&&&&&&&&& currpos = lseek(fd, 0, SEEK_CUR);这个技巧也可用于判断我们是否可以改变某个文件的偏移量。如果参数 fd(文件描述符)指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 并且置 errno 为&ESPIPE&。对于普通文件&(regular file),cfo 是一个非负整数。但对于特殊设备&,cfo&有可能是负数&。因此,我们不能简单地测试 lseek 的返回值是否小于 0 来判断 lseek 成功与否,而应该测试 lseek 的返回值是否等于 -1 来判断 lseek 成功与否。&&lseek 仅将 cfo 保存于内核中,不会导致任何 I/O 操作。这个 cfo 将被用于之后的读写操作。&&& 如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大&(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入&文件的所有字节由重复的 0&表示。空洞是否占用硬盘空间是由文件系统&(file system)决定的。
阅读(9312)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'Linux系统编程--lseek',
blogAbstract:'5.&lseek&每个打开的文件都记录着当前读写位置,打开文件时读写位置是0,表示文件开头,通常读写多少个字节就会将读写位置往后移多少个字节。但是有一个例外,如果以O_APPEND方式打开,每次写操作都会在文件末尾追加数据,然后将读写位置移到新的文件末尾。lseek和标准I/O库的fseek函数类似,可以移动当前读写位置(或者叫偏移量)。',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:7,
publishTime:9,
permalink:'blog/static/',
commentCount:3,
mainCommentCount:3,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}博客访问: 58225
博文数量: 78
博客积分: 30
博客等级: 民兵
技术积分: 287
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
原文地址: 作者:
每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲 区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)如下图所示:进程间通信共七种方式:第一类:传统的unix通信机制:# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。# 有名管道 (named pipe) :&有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。# 信号 ( sinal ) :&信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。第二类:System V IPC:&# 信号量( semophore ) :&信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。# 消息队列( message queue ) :&消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。第三类:BSD 套接字:# 套接字( socket ) :&套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。本文介绍IPC之无名管道(pipe)和有名管道(fifo)管道是Linux支持的最初Unix IPC形式之一,具有以下特点:管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。#include
int pipe(int fd[2])
该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。从管道中读取数据:如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。注:(PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。Posix.1要求PIPE_BUF至少为512字节,red hat 7.2中为4096)。向管道中写入数据:向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。&注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。管道的主要局限性正体现在它的特点上:只支持单向数据流;只能用于具有亲缘关系的进程之间;没有名字;管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;无代码,无真相/*function:利用无名管道pipe实现有血缘关系的进程间通信,pipo_fd[0]是读端,pipo_fd[1]是写端。pipe是半双工的。
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
&&&&int pipe_fd[2];
&&&&pid_t pid;
&&&&char r_buf[10];
&&&&char w_buf[4];
&&&&int r_num;
&&&&memset(r_buf,0,sizeof(r_buf));
&&&&memset(w_buf,0,sizeof(w_buf));
&&&&if(pipe(pipe_fd)<0)
&&&&&&&&printf("pipe create error\n");
&&&&&&&&return -1;
&&&&if((pid=fork())==0)
&&&&&&&&printf("\n");
&&&&&&&&close(pipe_fd[1]);
&&&&&&&&sleep(3);//确保父进程关闭写端
&&&&&&&&r_num=read(pipe_fd[0],r_buf,10);
&&&&&&&&printf(&&&&"read num is %d
the data read from the pipe is %d\n",r_num,atoi(r_buf));
&&&&&&&&close(pipe_fd[0]);
&&&&&&&&exit(1);
&&&&else if(pid>0)
&&&&&&&&close(pipe_fd[0]);//close read
&&&&&&&&strcpy(w_buf,"111");
&&&&&&&&if(write(pipe_fd[1],w_buf,4)!=-1)
&&&&&&&&&&&&printf("parent write over\n");
&&&&&&&&printf("parent close fd[1] over\n");
&&&&&&&&close(pipe_fd[1]);//write
&&&&&&&&sleep(10);
&&&&return 0;
管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。#include
int mkfifo(const char * pathname, mode_t mode);该函数的第一个参数是一个普通的路径名,也就是创建后FIFO的名字。第二个参数与打开普通文件的open()函数中的mode 参数相同。 如果mkfifo的第一个参数是一个已经存在的路径名时,会返回EEXIST错误,所以一般典型的调用代码首先会检查是否返回该错误,如果确实返回该错误,那么只要调用打开FIFO的函数就可以了。一般文件的I/O函数都可以用于FIFO,如close、read、write等等。有名管道比管道多了一个打开操作:open。FIFO的打开规则:如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。从FIFO中读取数据:约定:如果一个进程为了从FIFO中读取数据而阻塞打开FIFO,那么称该进程内的读操作为设置了阻塞标志的读操作。如果有进程写打开FIFO,且当前FIFO内没有数据,则对于设置了阻塞标志的读操作来说,将一直阻塞。对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。对于设置了阻塞标志的读操作说,造成阻塞的原因有两种:当前FIFO内有数据,但有其它进程在读这些数据;另外就是FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样(此时,读操作返回0)。如果没有进程写打开FIFO,则设置了阻塞标志的读操作会阻塞。注:如果FIFO中有数据,则设置了阻塞标志的读操作不会因为FIFO中的字节数小于请求读的字节数而阻塞,此时,读操作会返回FIFO中现有的数据量。向FIFO中写入数据:约定:如果一个进程为了向FIFO中写入数据而阻塞打开FIFO,那么称该进程内的写操作为设置了阻塞标志的写操作。对于设置了阻塞标志的写操作:当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。对于没有设置阻塞标志的写操作:当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;无代码,无真相
/* name:fifo_r.c
&* 功能:读有名管道,并把读到的数据打印到屏幕*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define N 80
int main(void) {
&&&&int in_file;
&&&&int count = 1;
&&&&char buf[N];
&&&&if((mkfifo("myfifo",0666))<0)//创建有名管道
&&&&&&&&if(errno==EEXIST)//管道已经存在
&&&&&&&&&&&&printf("The fifo is exist.\n");
&&&&&&&&else{
&&&&&&&&&&&&printf("creat myfifo failed!\n");
&&&&&&&&&&&&exit(-1);
&&&&&&&&printf("created by this process.\n");&&&&
&&&&in_file = open("myfifo",O_RDONLY);
&&&&if (in_file < 0) {
&&&&&&&&printf("Error in opening.\n");
&&&&&&&&exit(1);
&&&&while ((count = read(in_file,buf,N)) > 0)
&&&&&&&&printf("received from fifo: %s\n", buf);
&&&&&&&&memset(buf,0,N);
&&&&close(in_file);
&&&&return 0;
}/* name:fifo_w.c
&* 功能:从标准输入中读取数据,并到写有名管道*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define N 80
int main() {
&&&&int out_file;
&&&&int nbyte;
&&&&char buf[N];
&&&&if((mkfifo("myfifo",0666))<0)&&&&//创建有名管道
&&&&&&&&if(errno==EEXIST)
&&&&&&&&&&&&printf("The fifo is exist.\n");
&&&&&&&&else{
&&&&&&&&&&&&perror("creat myfifo failed!\n");
&&&&&&&&&&&&exit(-1);
&&&&}else{
&&&&&&&&printf("created by this process.\n");
&&&&out_file = open("myfifo",O_WRONLY);
&&&&if (out_file < 0) {
&&&&&&&&printf("Error opening fifo.");
&&&&&&&&exit(1);
&&&&printf("please input something:\n");
&&&&while((nbyte = read(0,buf,N))){
&&&&&&&&write(out_file,buf,nbyte);
&&&&&&&&printf("please input something:\n");
&&&&close(out_file);
&&&&return 0;
}管道常用于两个方面:(1)在shell中时常会用到管道(作为输入输入的重定向),在这种应用方式下,管道的创建对于用户来说是透明的;(2)用于具有亲缘关系的进程间通信,用户自己创建管道,并完成读写操作。FIFO可以说是管道的推广,克服了管道无名字的限制,使得无亲缘关系的进程同样可以采用先进先出的通信机制进行通信。管道和FIFO的数据是字节流,应用程序之间必须事先确定特定的传输"协议",采用传播具有特定意义的消息。要灵活应用管道及FIFO,理解它们的读写规则是关键。
阅读(66) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。嵌入式系统考试答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
嵌入式系统考试答案
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩9页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢下次自动登录
现在的位置:
& 综合 & 正文
17、有名管道与无名管道之间的区别
1)无名管道管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。
单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。(有点像队列哈)
#include &unistd.h&
int pipe(int fd[2])
该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由 创建管道后,一般再一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
向管道中写入数据时将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的信号,应用可以处理该信号,也可以忽略(默认动作则是应用程序终止)。
2)有名管道:不同于管道之处在于它提供一个路径名与之关联,以的文件形式存在于文件系统中。这样,即使与的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过相互通信(能够访问该路径的进程以及的创建进程之间),因此,通过不相关的进程也能交换数据。值得注意的是,严格遵循先进先出(),对管道及的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如等文件定位操作。
有名管道的创建
#include &sys/types.h&
#include &sys/stat.h&
int mkfifo(const char * pathname, mode_t mode)
该函数的第一个参数是一个普通的路径名,也就是创建后的名字。第二个参数与打开普通文件的函数中的参数相同。如果的第一个参数是一个已经存在的路径名时,会返回错误,所以一般典型的调用首先会检查是否返回该错误,如果确实返回该错误,那么只要调用打开的函数就可以了。一般文件的函数都可以用于,如、、等等
3)无名管道由一个在基本文件系统存储设备上的,一个与其相连的内存,两个打开文件控制块(分别对应管道的信息发送端和信息接收端)及其所属进程的描述信息来标识,在系统执行()命令行之后生成。并在中返回管道的读通道打开文件描述等,在中返回管道的写通道打开文件描述符。从结构上看,无名管道没有文件路径名,不占用文件目录项,因此文件目录结构中的链表不适用于这种文件,它只是存在于打开文件结构中的一个临时文件,随其所依附的进程的生存而生存,当进程终止时,无名管道也随之消亡。
送入管道的信息一旦被读进程取用就从管道中消失了,读写操作之间符合先进先出的队列原则。
管道文件是进程间通信的工具,为了尽量少的占用系统存储资源,一般系统均将其限制为最大长度为()字节的小型文件。当欲写入的消息超过字节时,就产生了读、写进程之间的同步问题。首先写操作查找文件中当前指针的偏移量,然后从此位置开始尽量写入信息,当长度达到字节时,系统控制写进程进入睡眠状态,一直等待读进程取走全部信息时,文件长度指针置,写进程才被唤醒继续工作。
为防止多个进程同时读写一个管道文件而产生混乱,在管道文件的标志字项中设置了标志项,以设置软件锁的方式实现多进程间对管道文件的互斥使用。
无名管道存在着如下两个严重的缺点。
第一,无名管道只能用于连接具有共同祖先的进程。
第二,无名管道是依附进程而临时存在的。所以后来推出了一种无名管道的变种有名管道,它常被称为。有名管道除继承了无名管道的所有特性优点之外,还屏弃了无名管道的两个缺点。
首先,是一种永久性的机构,它具有普通的系统文件名。在系统下可利用命令建立永久的管道,除非刻意删除它,否则它将一直保持在系统中。
其次,正是由于有名管道以“文件名”来标识,所以只要事先约定某一特定文件名,那样所有知道该约定的服务进程,不论它们之间是否有亲属关系,都可以便利地利用管道进行通信。
通过下面的命令可以创建一个命名管道:
/etc/mknod pipe_name p
其中“”是要创建的命名管道的名字,参数必须出现在命名管道名字之后。
命名管道文件被创建后,一些进程就可以不断地将信息写入命名管道文件里,而另一些进程也可以不断地从命名管道文件中读取信息。对命名管道文件的读写操作是可以同时进行的。下面的例子显示命名管道的工作过程。
进程、、中运行的程序只是一条简单的命令,它们不断地把信息写入到命名管道文件中。与此同时,程序中的“”命令不断地从命名管道文件中读取这些信息,从而实现这些进程间的信息交换。
程序执行时,首先创建命名管道文件,此时程序处于等待状态,直到、、进程中某一个进程往命名管道中写入信息时,程序才继续往下执行。使用命令可以删除命名管道文件从而清除已设置的 命名管道。
下面是一个用于记录考勤的例子:
在主机上运行的程序产生命名管道,并不断地从命名管道中读取信息送屏幕上显示。
/tmp/text程序:
if [ ! p /tmp/pipe1 ]
/etc/mknode /tmp/pipe1 p
if [ “msg" = “
done & /tmp/pipe1
在终端上运行的是雇员签到程序。每个雇员在任何一台终端上键入自己的名字或代码,程序将把这个名字连同当时的签到时间送入命名管道。
/tmp/text1程序:
tty=‘‘$’’
today=‘’
echo “$$
done & /tmp/pipe1
当雇员从终端上输入自己的姓名后,运行程序的主机将显示类似下面的结果:
wang Thu Jan 28 09:29:26 BTJ 1999
he Thu Jan 28 09:29:26 BTJ 1999
cheng Thu Jan 28 09:30:26 BTJ 1999
zhang Thu Jan 28 09:31:26 BTJ 1999
named pipes(命名管道)管道具有很好的使用灵活性,表现在:
1) 既可用于本地,又可用于网络。
2) 可以通过它的名称而被引用。
3) 支持多客户机连接。
4) 支持双向通信。
5) 支持异步重叠操作。
不过,当前只有支持服务端的命名管道技术等不支持。 等数据库就有的连接方式。
(资料来源于互联网)
&&&&推荐文章:
【上篇】【下篇】有名管道和无名管道的区别&
1)无名管道管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。
单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。(有点像队列哈)
int pipe(int
该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由创建管道后,一般再一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
&&&&向管道中写入数据时将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。
2)有名管道:不同于管道之处在于它提供一个路径名与之关联,以的文件形式存在于文件系统中。这样,即使与的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过相互通信(能够访问该路径的进程以及的创建进程之间),因此,通过不相关的进程也能交换数据。值得注意的是,严格遵循先进先出(),对管道及的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如等文件定位操作。
有名管道的创建
mkfifo(const char * pathname, mode_t mode)
该函数的第一个参数是一个普通的路径名,也就是创建后的名字。第二个参数与打开普通文件的函数中的参数相同。如果的第一个参数是一个已经存在的路径名时,会返回错误,所以一般典型的调用代码首先会检查是否返回该错误,如果确实返回该错误,那么只要调用打开的函数就可以了。一般文件的函数都可以用于,如、、等等
3)无名管道由一个在基本文件系统存储设备上的,一个与其相连的内存,两个打开文件控制块(分别对应管道的信息发送端和信息接收端)及其所属进程的描述信息来标识,在系统执行()命令行之后生成。并在中返回管道的读通道打开文件描述等,在中返回管道的写通道打开文件描述符。从结构上看,无名管道没有文件路径名,不占用文件目录项,因此文件目录结构中的链表不适用于这种文件,它只是存在于打开文件结构中的一个临时文件,随其所依附的进程的生存而生存,当进程终止时,无名管道也随之消亡。
送入管道的信息一旦被读进程取用就从管道中消失了,读写操作之间符合先进先出的队列原则。
1.管道pipe
3.命名管道FIFO
特点:1.FIFO是作为一个特殊的设备文件存在;
2.不同祖先进程的进程之间可以共享数据;
3.使用完后FIFO将继续保存。
通常对命名管道的读在写之前。
FIFO创建后,可以用open(),close(),read(),write(),unlink()等流操作函数操作。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 lseek函数 rston 的文章

 

随机推荐