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的更多相关文章

  1. 第四章:管道与FIFO

    4.1:概述 管道是最初的Unix IPC形式,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限在于没有名字,从而只能由亲缘关系的进程使用.这一点随FIFO的加入得改正 ...

  2. linux进程间通信-有名管道(FIFO)

    有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...

  3. 第4章 管道和FIFO

    4.1 管道 管道是由pipe函数创建的,提供一个单向数据流. 头文件 #include <unistd.h> 函数原型 int pipe(int fd[2]); 返回值 成功则为0,出错 ...

  4. Linux系统编程——进程间通信:命名管道(FIFO)

    命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...

  5. 第4章 管道与FIFO

    4.1 概述 管道只在亲缘进程间使用,FIFO在任意进程间使用 4.2 管道 #include <unistd.h> ]) fd[0]用来读管道,fd[1]用来写管道 1)命令who |  ...

  6. [转] IPC之管道、FIFO、socketpair

    管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...

  7. linux 有名管道(FIFO)

    http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...

  8. UNIX环境高级编程——管道和FIFO限制

    系统加于管道和FIFO的唯一限制为: OPEN_MAX     一个进程在任意时刻打开的最大描述符数: PIPE_BUF       可原子的写往一个管道或FIFO的最大数据量. OPEN_MAX的值 ...

  9. UNIX环境高级编程——管道和FIFO的额外属性

    一个描述符能以两种方式设置成非阻塞. (1)调用open时可以指定O_NONBLOCK标志. writefd = open(FIFO1,O_WRONLY | O_NONBLOCK,0); (2)如果一 ...

  10. 管道和FIFO 一

    管道和FIFO   管道(pipe)       管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道 ...

随机推荐

  1. python 基础——常用日志装饰器

    from functools import wraps class logit(): def __init__(self, logfile='out.log'): self.log = logfile ...

  2. IIs站点的建立

    控制面板——管理工具——Internet信息服务管理器 首先应设置的文件权限:System 和 admin 程序池:4.0 编辑权限:iis apppool\名称 身份验证:匿名身份——应用程序池标识

  3. hdu 4271 动态规划

    思路:考的是字符串的编辑距离.在蓝桥杯2012年决赛上出现过. #include<iostream> #include<cstdio> #include<cstring& ...

  4. 转:eclipse怎样修改包(package)的显示样式、格式 工具/原料

    转:http://blog.csdn.net/longyaxx258/article/details/50774128 eclipse 打开我们的项目,可以看到左侧的package看上去特别多,没有层 ...

  5. php读取mysql中文数据出现乱码

    1.PHP页面语言本身的编码类型不合适,这时候,你直接在脚本中写的中文肯定是乱码,不用说数据库了:    解决方法:选择'UTF8'或者'gb2312',这样客户浏览器会自动选择并出现正确的中文显示. ...

  6. CS异步下载

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. 解决方案:Error:Execution failed for task ':app:compileDebugAidl'. > aidl is missing

    也许有朋友最初在用Android Studio创建新工程的时候会碰到这个错误,其实这个问题是由于版本不兼容导致的,解决方法很简单,只需要把编译工具的版本改一下就可以了: 1.选左侧的工程根目录app, ...

  8. 导航栏 UITabBarController等颜色的区别

    //tint color是设置你选中的那个tabBar的颜色,默认是蓝色,点击是设置的红色    vc.tabBar.tintColor = [UIColor redColor];        // ...

  9. 20150414---ListView简介(web)

    ListView,自带分页功能,而且用户自定义界面样式自由度高. 如下图,都是使用Listview完成的,(测试数据,内容较乱) 所在位置:工具--数据-ListView 这里是配置ListView样 ...

  10. 求单链表倒数第m个结点

    问题:求单链表倒数第m个结点,要求不准求链表的长度,也不许对链表进行逆转 解:设置两个指针p和q,p.q指向第一个结点.让p先移动到链表的第m个结点,然后p和q同时向后移动,直到p首先到达尾结点.此时 ...