linux -- 管道和重定向
目录
- 一、管道和重定向命令
- 1.1、管道命令 |
- 1.2、重定向命令 < , > , >>
- 二、重定向编程
- 2.1、close then open
- 2.2、dup函数
- 三、管道编程
- 3.1、匿名管道(单工)
- 3.2、命名管道
- 3.3、popen
- 四、综合应用
一、管道和重定向命令
1.1、管道命令 |
- 前一个命令的输出作为后一个命令的输入
- 可以叠加
$ ps -u$ ps -u | grep pts$ ps -u | grep pts | grep pts/0
1.2、重定向命令 < , > , >>
输入: <
输出: >
追加的方式输入: >>
#include <stdio.h> int main(int argc,char *argv[]) {//从标准输入中获取char str[1024];scanf("%s",str);//往标准输出中打印argc argvprintf("argc = %d\n",argc);for(int i = 0;i<argc;i++){fprintf( stdout, "%s\n", argv[i]);}printf("%s\n",str);//往标准错误中打印fprintf(stderr,"this is stderr\n");return 0; }
#不重定向 $ ./test #重定向 执行后不会打印出来,不用再输入参数 $ ./test01 0<in.txt 1>out.txt 2>err.txt#以追加的方式重定向,不会清空原文件 $ ./test01 2>>err.txt #要将文本输入到标准输入 只能用 0<xxx.txt :<<annotation标准输入 stdin 0标准输出 stdout 1标准错误 stderr 2 annotation
结论
重定向由shell实现
重定向符号和重定向文件不是参数
二、重定向编程
2.1、close then open
1、先关闭标准输出的文件描述符
2、再打开一个文件
3、这个文件的文件描述符就变成了1,从而实现重定向功能
- 每次获取文件描述符,系统总会分配最小且可用的描述符
- 适用于有文件名的情况
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {//输出到标准输出char buf[] = "1234567890\n";write(1,buf, sizeof(buf) - 1 );//sizeof会计算 \0//关闭标准输出,重定向到指定文件close(1);int fd = open("./out.txt",O_CREAT | O_RDWR | O_TRUNC,666);if(fd < 0){perror("open");exit(-1);}write(1,buf, sizeof(buf) - 1 );close(fd);return 0;
}
2.2、dup函数
#include <unistd.h>int dup(int oldfd);
int dup2(int oldfd, int newfd);
功能
复制一个文件描述符
参数说明
oldfd 要复制的文件描述符
newfd 复制后得到的文件描述符返回值
-1 出错
> -1 新的文件描述符
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>int main(int argc,char *argv[]) {int fd = open("./out.txt",O_CREAT | O_RDWR | O_TRUNC,666);if(fd<0){perror("open");exit(-1);}//输出到标准输出char buf[] = "hello\n";write(1,buf, sizeof(buf) - 1 );//sizeof会计算 \0//关闭标准输出,重定向到指定fd 方法1close(1);int newfd = dup(fd);if(newfd != 1){perror("dup");exit(-1);}close(fd);write(1,buf, sizeof(buf) - 1 );close(newfd);//关闭标准输出,重定向到指定fd 方法2
// dup2(fd,1);
// if(fd != 1){// perror("dup2");
// exit(-1);
// }
// write(1,buf, sizeof(buf) - 1 );
// close(fd);return 0;
}
- 补充
1、 如果只能拿到要重定向的文件的文件描述符,可用此方法
2、dup会申请一个新的文件描述符,同样是在最小可用当中去找
3、新的文件描述符和旧的一样,指向同样的文件
4、 dup2(int oldfd, int newfd) 如果newfd存在,则会先被关闭
三、管道编程
3.1、匿名管道(单工)
#include <unistd.h>int pipe(int pfd[2]); //man 手册是 pipefd,我简写成 pfd;
- 参数说明
pfd 存放管道两端文件描述符的数组
pfd[0] 存放读端的描述符
pfd[1]存放写端的描述符- 返回值
-1 错误
0 成功
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#include <string.h>int main() {int pfd[2];pid_t pid;char buf[] ="1234567890";if(pipe(pfd) == -1){perror("pipe");exit(-1);}pid = fork();if(pid<0){perror("fork");exit(-1);}else if(pid == 0){close(pfd[1]);memset(buf,0, sizeof(buf));read(pfd[0],buf, sizeof(buf) - 1 );printf("子进程接收 : %s\n",buf);close(pfd[0]);exit(0);}else{close(pfd[0]);write(pfd[1], buf, sizeof(buf) - 1);printf("父进程发送 : %s \n",buf);close(pfd[1]);wait(NULL);exit(0);}
}
- 补充
- pipe创建的是匿名管道,实质是一个队列 写时入队,读时出队
- 一般先创建管道后再创建子进程
- 匿名管道只能单向通信来保证准确性
- 只有有亲缘关系的进程才能用匿名管道通信
- 进程读操作
若管道中无数据,则会被阻塞,直到有数据写入
当所有进程都关闭了写端,此时read就会返回0 - 进程写操作
若管道已满,则会被阻塞
如果所有进程关闭了读端,此时写操作会出现段错误
3.2、命名管道
- 创建管道文件命令
#创建一个名为 fifo 的命名管道文件
$ mknod fifo p
#include <sys/types.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);
- 功能
创建命名管道文件- 参数
pathname 要创建的文件名
mode 文件权限- 返回值
0 成功
-1 失败
mkfifo("fifo",0644);int fd = open("fifo",O_RDWR);
- 补充
1、命名管道可以实现任意两个进程间的通信
2、管道是特殊类型的文件,实质也是队列,不能用lseek函数
3、读时若管道为空也会被阻塞,
3.3、popen
#include <stdio.h>FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
- 功能
通过创建管道、fork和调用shell来打开进程- 参数
command:要执行的命令或程序 (实际是打开了子进程)
type:分为 ‘r’和‘w’
r 表示读取command 的输出
w 表示写到command 的输入
- 先写个hello
#include <stdio.h>int main() {char buf[12] = {'\0'};fgets(buf, sizeof(buf),stdin);printf("%s\n",buf);
}
- test程序
#include <stdio.h>
#include <unistd.h>
#include <wait.h>int main() {FILE *fp = popen("./hello","w");int fd = fileno(fp);char buf[] = "hello world";write(fd,buf, sizeof(buf) - 1);wait(NULL);close(fd);pclose(fp);return 0;
}
- 执行test
四、综合应用
- shell 命令
$ ls -l / | grep lib
- 代码实现
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
//为了方便,没写出错处理
int main() {//fork一个子进程执行 ls -l / 并拿到输出结果FILE *fp = popen("ls -l /","r");int fd = fileno(fp);//重定向到标准输入dup2(fd,0);wait(NULL);close(fd);pclose(fp);char* argv[] = {"grep","lib",NULL};execvp("grep",argv);
}
笔记来源:mooc
linux -- 管道和重定向相关推荐
- Linux入门-7 Linux管道、重定向以及文本处理
Linux管道.重定向以及文本处理 1 Linux多命令协作:管道及重定向 管道和重定向 2 Linux命令行文本处理工具 文件浏览 基于关键字搜索-grep 基于列处理文本-cut 文本统计-wc ...
- linux管道、重定向和查看命令
目录 二.linux管道.重定向和查看命令 1.管道:| 2.tee 3.重定向 4.文件内容浏览 5.文件内容过滤:grep 6.命令搜索 7. find 查找文件---按照文件名称.大小.类型.权 ...
- Linux管道和重定向 ---多命令协作
管道及重定向就是Linux多命令协作的基础机制 Linux的Shell对数据流进行以下分类定义: stdin 标准输入 编号为:0 默认:键盘 stdout 标准输出 编号为:1 ...
- linux 管道和重定向
管道:| 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 用法: 命令1 | 命令2 | 命令3 | ........ 例如: 统计/usr/bin/目录下的文件 ...
- linux说明管道的作用,Linux管道及重定向的用途是什么
1.重定向在Linux中有时我们在命令的执行过程中,不想将执行结果显示到屏幕上,或者将其结果输出到其他位置 这时就需要重定向来解决这个问题了 首先了解一下Linux中的3种I/O设备: 0:标准输入 ...
- Linux中的管道与重定向
前言: 这篇博文主要参考了鸟哥的<鸟哥的Linux私房菜>和杨鹏(NetSnake)的<Linux服务器架设>这两本书,以及在网络上查阅的资料.此博文作为我阅读<鸟哥的L ...
- Linux多命令协作:管道及重定向
认识Linux中管道和重定向 如下图. 实践:重定向'>'的使用 转载于:https://www.cnblogs.com/mcgrady/p/7339770.html
- Linux链接文件、管道、重定向讲解
Linux链接文件.管道.重定向讲解 --链接文件-- 硬链接:在inode表中记录一个条目,所有的元数据和原始文件元数据相同. ·相当于两个名字. ·删除原始文件,另一个条目也能够找数据本身. ·不 ...
- Linux Shell重定向Linux管道
Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向:从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思. 标准的输入输出方向 输入方向就是数据从哪里流向程序.数据默认 ...
最新文章
- SAP MM T-code MD04的使用,是有前提的!
- 以太经典(ETC)逆势上涨,将逆袭反超以太坊(ETH)?
- Oops 的栈信息分析
- Highcharts图表-ajax-获取json数据生成图表
- controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......
- 英特尔cpu发布时间表_英特尔10nm芯片开始大规模出货,先进制程时间表浮出水面...
- 关于组策略软件限制策略规则
- 机器学习专题(二):2.1机器学习的数据
- linux vi代码高亮,linux Vi编辑器代码高亮设置及永久显示行号的方法
- 数字化方法基础(四)_矩阵操作
- AC双链路冷备份详解及配置原理
- flash cs4 如何新增自定义控件
- 一文读懂“语言模型”
- 数组分割 java_分割java数组
- 分页符怎么删除,word不要的页面删不掉
- 【摸鱼神器】— 五子棋
- PureMVC游戏框架解析 理解其中包含的设计模式
- 【BZOJ3503】【Cqoi2014】和谐矩阵 高斯消元,解异或方程组
- ios添加邮件收件服务器,全球邮企业邮箱在iPhone上使用的设置说明
- 从邮箱到云客服,SaaS行业发展到哪种程度了?