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. umbraco使用VS安装

    新建——程序包管理器控制台——install - package umbracocms vs中的快捷键: ctrl+F5为调试: ctrl+shift+B生成解决方案: 打包前,App_data文件夹 ...

  2. Win10 VMware虚拟机无法打开内核设备“\\.\Global\vmx86“

    前几项与Win7配置相同 用管理员模式打开CMD 运行 net start vmci net start vmx86 net start VMnetuserif 这三条命令 为了不用每次启动都这样,修 ...

  3. MVC datetime? & datetime 设置格式

    设置datetime的格式,直接有方法重载进行,即使数据为datetime?格式 设置起始时间在配置的时候添加设置 $('#closeTime').datetimepicker({ language: ...

  4. 揪出ie和Edge的js代码

    var userAgent = navigator.userAgent; var isIE = userAgent.indexOf("compatible") > -1 &a ...

  5. C++ 单链表的基本算法

    线性表是最简单,最常用的一种数据结构.线性表的逻辑结构是n个数据元素的有限序列(a1,a2,…,an).而线性表的物理结构,我们已经学习过顺序表,也就是数组 :另一种线性表的物理结构——链表 . 什么 ...

  6. json2.js 的使用

    转载自:http://www.cnblogs.com/youring2/archive/2013/03/01/2938850.html -------------------------------- ...

  7. shell运行报 too many arguments错误

    有时候shell在运行的时候可能会报 too many arguments错误,出现这种错误的一般情况是出现了多值问题,也就是一个变量可能有多个值了. 例:#!/bin/sh echo "I ...

  8. select--from--where--group by--having--order by 依次顺序

    1.查询中用到的关键词主要包含六个,并且他们的顺序依次为 select--from--where--group by--having--order by 其中select和from是必须的,其他关键词 ...

  9. JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  10. 7款震撼人心的HTML5文字特效

    1.CSS3五彩文字特效 文字带阴影效果 这是一款非常具有卡通形象的CSS3五彩文字特效,虽然没有迷人的动画效果,但是五彩缤纷的文字展现在屏幕上也是非常酷的,再加上每一个文字都有不同角度的阴影效果,加 ...