目录

  • 一、管道和重定向命令
    • 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);}
}

  • 补充
  1. pipe创建的是匿名管道,实质是一个队列 写时入队,读时出队
  2. 一般创建管道再创建子进程
  3. 匿名管道只能单向通信来保证准确性
  4. 只有有亲缘关系的进程才能用匿名管道通信
  5. 进程操作
    若管道中无数据,则会被阻塞,直到有数据写入
    所有进程都关闭了写端,此时read就会返回0
  6. 进程操作
    若管道已满,则会被阻塞
    如果所有进程关闭了读端,此时写操作会出现段错误

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 -- 管道和重定向相关推荐

  1. Linux入门-7 Linux管道、重定向以及文本处理

    Linux管道.重定向以及文本处理 1 Linux多命令协作:管道及重定向 管道和重定向 2 Linux命令行文本处理工具 文件浏览 基于关键字搜索-grep 基于列处理文本-cut 文本统计-wc ...

  2. linux管道、重定向和查看命令

    目录 二.linux管道.重定向和查看命令 1.管道:| 2.tee 3.重定向 4.文件内容浏览 5.文件内容过滤:grep 6.命令搜索 7. find 查找文件---按照文件名称.大小.类型.权 ...

  3. Linux管道和重定向 ---多命令协作

    管道及重定向就是Linux多命令协作的基础机制 Linux的Shell对数据流进行以下分类定义: stdin     标准输入  编号为:0   默认:键盘 stdout   标准输出  编号为:1  ...

  4. linux 管道和重定向

    管道:| 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 用法: 命令1 | 命令2 | 命令3 | ........ 例如: 统计/usr/bin/目录下的文件 ...

  5. linux说明管道的作用,Linux管道及重定向的用途是什么

    1.重定向在Linux中有时我们在命令的执行过程中,不想将执行结果显示到屏幕上,或者将其结果输出到其他位置 这时就需要重定向来解决这个问题了 首先了解一下Linux中的3种I/O设备: 0:标准输入 ...

  6. Linux中的管道与重定向

    前言: 这篇博文主要参考了鸟哥的<鸟哥的Linux私房菜>和杨鹏(NetSnake)的<Linux服务器架设>这两本书,以及在网络上查阅的资料.此博文作为我阅读<鸟哥的L ...

  7. Linux多命令协作:管道及重定向

    认识Linux中管道和重定向 如下图. 实践:重定向'>'的使用 转载于:https://www.cnblogs.com/mcgrady/p/7339770.html

  8. Linux链接文件、管道、重定向讲解

    Linux链接文件.管道.重定向讲解 --链接文件-- 硬链接:在inode表中记录一个条目,所有的元数据和原始文件元数据相同. ·相当于两个名字. ·删除原始文件,另一个条目也能够找数据本身. ·不 ...

  9. Linux Shell重定向Linux管道

    Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向:从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思. 标准的输入输出方向 输入方向就是数据从哪里流向程序.数据默认 ...

最新文章

  1. SAP MM T-code MD04的使用,是有前提的!
  2. 以太经典(ETC)逆势上涨,将逆袭反超以太坊(ETH)?
  3. Oops 的栈信息分析
  4. Highcharts图表-ajax-获取json数据生成图表
  5. controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......
  6. 英特尔cpu发布时间表_英特尔10nm芯片开始大规模出货,先进制程时间表浮出水面...
  7. 关于组策略软件限制策略规则
  8. 机器学习专题(二):2.1机器学习的数据
  9. linux vi代码高亮,linux Vi编辑器代码高亮设置及永久显示行号的方法
  10. 数字化方法基础(四)_矩阵操作
  11. AC双链路冷备份详解及配置原理
  12. flash cs4 如何新增自定义控件
  13. 一文读懂“语言模型”
  14. 数组分割 java_分割java数组
  15. 分页符怎么删除,word不要的页面删不掉
  16. 【摸鱼神器】— 五子棋
  17. PureMVC游戏框架解析 理解其中包含的设计模式
  18. 【BZOJ3503】【Cqoi2014】和谐矩阵 高斯消元,解异或方程组
  19. ios添加邮件收件服务器,全球邮企业邮箱在iPhone上使用的设置说明
  20. 从邮箱到云客服,SaaS行业发展到哪种程度了?

热门文章

  1. Java中的四种访问权限:public、protected、包访问、private
  2. 利用机器学习方法进行岩相分类
  3. 2008珠三角考察记录
  4. PD QC AFC 受电端协议芯片
  5. 【一起学Java-第二篇】Java语言开发环境
  6. 移动端网页重构指南 – CSS篇
  7. 内存管理:内存空间的扩充
  8. C#算法题目自己的解答 约德尔测试
  9. buuctf逆向simple rev
  10. RelativeLayout