管道和FIFO
pipe
子进程从终端读取一个文件名, 通过管道将文件名传递给父进程
父进程收到文件名后, 读取文件内容并通过管道传递给子进程
子进程接收到文件内容并输出到终端
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <sys/wait.h>
#define MAXLINE 4096
void err_quit(char *fmt,...){
int errno_save;
errno_save=errno;
va_list list;
va_start(list,fmt);
vfprintf(stderr,fmt,list);
if(errno != 0)
fprintf(stderr," :%s",strerror(errno_save));
va_end(list);
exit(1);
}
void Pipe(int *fds){
if(pipe(fds)<0)
err_quit("pipe error");
}
void Close(int fd){
if(close(fd)<0)
err_quit("close error");
}
pid_t Waitpid(pid_t pid,int *statloc,int option){
pid_t retpid=waitpid(pid,statloc,option);
if(retpid == -1)
err_quit("waipid error");
return retpid;
}
char *Fgets(char *buf,int n,FILE *fp){
char *rptr=fgets(buf,n,fp);
if(rptr == NULL && ferror(fp))
err_quit("fgets error");
return rptr;
}
ssize_t Read(int fd,void *buf,size_t nbytes){
ssize_t nread=read(fd,buf,nbytes);
if(nread == -1)
err_quit("read error");
return nread;
}
void Write(int fd,void *buf,size_t nbytes){
if(write(fd,buf,nbytes) != nbytes)
err_quit("write error");
}
void client(int,int), server(int,int);
int main(int argc, char *argv[]){
int pipe1[2],pipe2[2];
pid_t childpid;
Pipe(pipe1);
Pipe(pipe2);
if((childpid=fork())<0)
err_quit("fork error");
else if(childpid == 0){
Close(pipe1[1]);
Close(pipe2[0]);
server(pipe1[0],pipe2[1]);
}else{
Close(pipe1[0]);
Close(pipe2[1]);
client(pipe2[0],pipe1[1]);
Waitpid(childpid,NULL,0);
}
exit(0);
}
void client(int readfd,int writefd){
size_t len;
ssize_t n;
char buf[MAXLINE];
Fgets(buf,MAXLINE,stdin);
len=strlen(buf);
if(buf[len-1] == '\n')
len--;
Write(writefd,buf,len);
while((n=Read(readfd,buf,MAXLINE))>0)
Write(STDOUT_FILENO,buf,n);
}
void server(int readfd,int writefd){
int fd;
ssize_t n;
char buff[MAXLINE];
if((n=Read(readfd,buff,MAXLINE))==0)
err_quit("end-of-file while reading pathname");
buff[n]='\0';
if((fd=open(buff,O_RDONLY))<0){
snprintf(buff+n,sizeof(buff)-n,":can't open, %s\n",
strerror(errno));
n=strlen(buff);
Write(writefd,buff,n);
}else{
while((n=Read(fd,buff,MAXLINE))>0)
Write(writefd,buff,n);
Close(fd);
}
}
popen/pclose
popen的打开属性为读或写
写时表示向子进程传递命令, 读时表示从子进程读取命令的执行结果
//头文件和其它包裹函数同pipe
void Fputs(const char *ptr,FILE *fp){
if(fputs(ptr,fp)==EOF)
err_quit("fputs errro");
}
FILE *Popen(const char *command,const char *type){
FILE *fp;
if((fp=popen(command,type)) == NULL)
err_quit("popen error");
return fp;
}
void Pclose(FILE *fp){
if(pclose(fp) == -1)
err_quit("pclose error");
}
int main(int argc, char *argv[]){
size_t n;
char buff[MAXLINE],command[MAXLINE];
FILE *fp;
Fgets(buff,MAXLINE,stdin);
n=strlen(buff);
if(buff[n-1]=='\n')
n--;
snprintf(command,sizeof(command),"cat %s",buff);
fp=Popen(command,"r");
while(Fgets(buff,MAXLINE,fp) != NULL)
Fputs(buff,stdout);
Pclose(fp);
exit(0);
}
FIFO
在管道的基础上, 增加了管道命名, 在物理磁盘上会多出一个管道文件, 可用于非亲代进程之间传递消息
mkfifo函数用于创建命名管道, 默认含有O_CREAT | O_EXCL属性, 要么创建新管道文件, 要么出错返回EEXIST
管道文件打开模式要么只读要么只写, 不支持lseek
//头文件和其它包裹函数同pipe
#include <sys/types.h>
#include <sys/stat.h>
int Open(const char *pathname,int flag,mode_t mode){
int fd;
if((fd=open(pathname,flag,mode)) == -1)
err_quit("open error");
return fd;
}
void Unlink(const char *pathname){
if(unlink(pathname) == -1)
err_quit("unlink error");
}
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define FIFO1 "./fifo.1"
#define FIFO2 "./fifo.2"
int main(int argc, char *argv[]){
int readfd,writefd;
pid_t childpid;
if((mkfifo(FIFO1,FILE_MODE)) && (errno != EEXIST))
err_quit("can't create %s",FIFO1);
if((mkfifo(FIFO2,FILE_MODE)<0) && (errno != EEXIST)){
Unlink(FIFO1);
err_quit("can't create %s",FIFO2);
}
if((childpid=fork())<0)
err_quit("fork error");
else if(childpid==0){
readfd=Open(FIFO1,O_RDONLY,0);
writefd=Open(FIFO2,O_WRONLY,0);
server(readfd,writefd);
exit(0);
}
writefd=Open(FIFO1,O_WRONLY,0);
readfd=Open(FIFO2,O_RDONLY,0);
client(readfd,writefd);
Waitpid(childpid,NULL,0);
Close(readfd);
Close(writefd);
Unlink(FIFO1);
Unlink(FIFO2);
exit(0);
}
管道和FIFO的更多相关文章
- 第四章:管道与FIFO
4.1:概述 管道是最初的Unix IPC形式,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限在于没有名字,从而只能由亲缘关系的进程使用.这一点随FIFO的加入得改正 ...
- linux进程间通信-有名管道(FIFO)
有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...
- 第4章 管道和FIFO
4.1 管道 管道是由pipe函数创建的,提供一个单向数据流. 头文件 #include <unistd.h> 函数原型 int pipe(int fd[2]); 返回值 成功则为0,出错 ...
- Linux系统编程——进程间通信:命名管道(FIFO)
命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...
- 第4章 管道与FIFO
4.1 概述 管道只在亲缘进程间使用,FIFO在任意进程间使用 4.2 管道 #include <unistd.h> ]) fd[0]用来读管道,fd[1]用来写管道 1)命令who | ...
- [转] IPC之管道、FIFO、socketpair
管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...
- linux 有名管道(FIFO)
http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...
- UNIX环境高级编程——管道和FIFO限制
系统加于管道和FIFO的唯一限制为: OPEN_MAX 一个进程在任意时刻打开的最大描述符数: PIPE_BUF 可原子的写往一个管道或FIFO的最大数据量. OPEN_MAX的值 ...
- UNIX环境高级编程——管道和FIFO的额外属性
一个描述符能以两种方式设置成非阻塞. (1)调用open时可以指定O_NONBLOCK标志. writefd = open(FIFO1,O_WRONLY | O_NONBLOCK,0); (2)如果一 ...
- 管道和FIFO 一
管道和FIFO 管道(pipe) 管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道 ...
随机推荐
- [wordpress] 输出一个过滤器绑定的方法
参考了WordPress: How do I get all the registered functions for 'the_content' filter, function print_fil ...
- 关于在asp.net的web页面中的全局变量问题
在asp.net的web页面中是不是没有全局变量?有的,在Class类内部的都是,只不过在WebWofm程式中跟WinForm和Console程式有些区别,当页面刷新时,它们的值不会保持,依然会再次初 ...
- 教你21天学会C++ (有图有真相)
这张图,是在一位有十多年开发经验的资深前辈博客里看到的,觉得很有趣,分享之~ 这位大神的博客是:http://coolshell.cn 理论是可行的,当你刚开始学习C++,到第21天的时候出门千万要小 ...
- Android支付宝SDK开发笔记
一.准备工作 〉1.下载开发包 https://b.alipay.com/order/productDetail.htm?productId=2014110308141993&tabId=4# ...
- HTML之调用摄像头实现拍照和摄像功能
应该有很多人知道,我们的手机里面有个功能是“抓拍入侵者”,说白了就是在解锁应用时如果我们输错了密码手机就会调用这一功能实现自动拍照. 其实在手机上还有很多我们常用的软件都有类似于这样的功能,比如微信扫 ...
- 浅谈sqlserver数据库优化(一)----开光篇
今天暂时无事,风和日丽,万里无云.游山的.玩水的.遛麻雀的都闲的不亦乐乎,也忙的不亦乐乎.在这美好的季节,依旧躲在被窝或是电脑旁绞尽脑汁敲键盘的人们,也别有一番滋味.废话少说,言归正传. 赶上了一个最 ...
- vs 2015密钥
专业版:HMGNV-WCYXV-X7G9W-YCX63-B98R2企业版:HM6NR-QXX7C-DFW2Y-8B82K-WTYJV
- java创建Date日期时间笔记
(1)public Date() 创建的日期类对象的日期时间被设置成创建时刻相对应的日期时间. 例: Java代码 1.Date today=new Date(); //today被设置成创建时刻相 ...
- C#代码配置IIS 操纵IIS
前言: IIS到目前经历了四个版本分别为 IIS4.0 IIS5.0 IIS6.0 IIS7.0,其中IIS6.0 IIS7.0是在5.0的安全问题的基础上获得的发展,目前为止.6.0版本以后的都是 ...
- ASP.NET MVC自定义路由 - 实现IRouteConstraint限制控制器名(转载)
自定义约束前 namespace MvcApplication2 { public class RouteConfig { public static void RegisterRoutes(Rout ...