已打开的文件描述符在fork和exec调用后保留下来,我们可以利用对进程这方面知识点的理解来改变程序的行为。

这个例子涉及一个过滤程序:它从标准输入读取数据,然后向标准输出写数据,同时在输入和输出之间对数据做些有用的转换。

过滤程序upper.c

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
int ch;
while( EOF != (ch=getchar()))
{
putchar(toupper(ch));
}
exit(); }

upper.c执行效果:

如果我们利用shell从定向把一个文件的内容全部转为大写,如下所示:

如果我们想在另一个程序中使用这个过滤程序会发生什么呢?下一个例子useupper.c接受一个文件名做命令行参数,若果对它调用不正确,他将会响应一个错误信息。

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
char *filename;
int i;
if(argc != )
{
fprintf(stderr,"usage :useupper file\n");
exit();
}
filename = argv[];
//重新打开标准输入,并再次检查有无错误发生,然后用execl调用upper程序。
for (i = ;i<argc;i++)
{
printf("the argv[%d] is %s\n",i,argv[i]);
}
if(!freopen(filename,"r",stdin))
{
fprintf(stderr,"can't redirect stdin from file %s!\n",filename);
exit();
} execl("./upper","upper",);
//execl会替换当前的进程。如果没有发生错误,剩下的语句不会执行。
perror("could not exec ./upper");
exit();
}

分析一下这个程序的流程:

运行时我们应该给他提供一个文件,让他把文件的内容全部转换为大写。这项工作由upper程序完成,但它不会处理文件名参数。注意,我们不需要upper程序的源代码。我们可以利用这种方法

运行任何可执行程序。

useupper程序用freopen函数先关闭标准输入,然后将文件流stdin与程序参数给定的文件名关联起来。接下来,它调用execl用upper程序替换掉正在运行的进程代码。有hi那我IE已打开的文件描述符会在execl调用

之后保留下来,所以upper程序的运行情况和他在shell提示符下运行情况完全一致。 

ps:

1.
stdout(Standardoutput)标准输出
stdin(Standardinput)标准输入
stderr(Standarderror)标准错误

2.int fprintf (FILE* stream, const char*format, [argument])

FILE*stream:文件指针
const char* format:输出格式
argument  :附加参数列表
 
作用:
fprintf( )会根据参数format 字符串来转换并格式化数据, 然后将结果输出到参数stream 指定的文件中, 直到出现字符串结束('\0')为止。
 

3.FILE *freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream);

freopen是被包含于C标准库头文件<stdio.h>中的一个函数,用于重定向输入输出流。该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。

形参说明:

filename:需要重定向到的文件名或文件路径。
mode:代表文件访问权限的字符串。例如,"r"表示“只读访问”、"w"表示“只写访问”、"a"表示“追加写入”。
stream:需要被重定向的文件流。
返回值:如果成功,则返回该指向该输出流的文件指针,否则返回为NULL。

4.perror()

perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno(这里的说法不准确,errno是一个宏,该宏返回左值) 的值来决定要输出的字符串。
在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

以上内容来自《Linux程序设计第四版》PS部分来自百度百科

Linuc学习3-输入和输出重定向的更多相关文章

  1. 从0开始的Python学习015输入与输出

    简介 在之前的编程中,我们的信息打印,数据的展示都是在控制台(命令行)直接输出的,信息都是一次性的没有办法复用和保存以便下次查看,今天我们将学习Python的输入输出,解决以上问题. 复习 得到输入用 ...

  2. Shell 基础 -- 输入、输出重定向

    一.文件描述符 文件描述符是一个非负的整数,Linux 中每个运行中的程序(进程),都有一些与之关联的文件描述符,你可以使用文件描述符来访问打开的文件或设备.在标准 I/O 库中,与文件描述符对应的是 ...

  3. C++学习42 输入和输出的概念

    我们经常用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上.从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件.除了以终端为对象进行输入和输出外,还经常 ...

  4. perl学习笔记——输入与输出

    读取标准输入 用<STDIN>进行标准输入:chomp($line=<STDIN>); 如果读到文件尾,行输入操作符就会返回undef.便可利用这一性质跳出循环. while( ...

  5. Erlang学习记录:输入和输出

    输入和输出 输入和输出功能都被定义在io模块 输出功能非常常用,由于erlang项目没有可断点调试的IDE(或者说根本不需要),所以所有的调试操作都是由io输出 来调试的 io:get_line/1. ...

  6. Python学习--02输入和输出

    命令行输入 x = input("Please input x:") y = raw_input("Please input x:") 使用input和raw_ ...

  7. perl学习(5) 输入和输出

    1.1. 从标准输入设备输入 <STDIN> 行输入操作在到达文件的结尾时将返回undef,在while循环的条件中不能使用chomp: while (defined($line = &l ...

  8. python语言学习5——输入和输出

    输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字. 注意点: 字符串用的是单引号 碰到逗号输出时就会输出一个空格 输入 python提供了一个input(),可以让用户输入一个字 ...

  9. Python学习笔记-输入与输出

    一.Python提供了raw_input()和input()两个函数实现数据输入. 1.raw_input() 接收字符串类型的输入数据. str1=raw_input("请输入字符串:&q ...

随机推荐

  1. 转 理解vuex -- vue的状态管理模式

    转自:https://segmentfault.com/a/1190000012015742 vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 ...

  2. beta阶段成果展示博客

    跟着我们一一点一点揭开蒙娜丽莎的微笑 - 本次beta阶段之前,我们团队,对其他组在事后诸葛亮期间对我们的评价进行深刻的审视,特别是缺点方面,开了好几次的站立会议,专门讨论beta的主要方向和任务.最 ...

  3. 交换机、linux光衰查询

    RX收光,TX发光 一.交换机 命令: display interface transceiver brief 结果: ...... HW6851 10GE1/0/15 transceiver dia ...

  4. selenium 关键字驱动部分设计思路

    1 说明: 1.以下的代码亲测直接可用, 2.设计思路来自博客园的 张飞_ :http://www.cnblogs.com/zhangfei/p/5330994.html   /   http://w ...

  5. pygame学习笔记(3)——时间、事件、文字

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 1.运动速率    上节中,实现了一辆汽车在马路上由下到上行驶,并使用了pygame.time.delay(200 ...

  6. [学习]Windows server 使用控制台时容易卡死的解决方法

    公司使用Windows server 下面的 cmd 命令行 控制台打开某一个 bat 文件的方式 进行后台使用.. 但是经常发现在winserver 2016 时 遇到卡死的情况, 今天中午我再进行 ...

  7. QVariant相当于一个包含大多数Qt数据类型的联合体(源码解读)

    将数据存储为一个Private结构体类型的成员变量d: <qvariant.cpp> 1 QVariant::QVariant(Type type) 2 { create(type, 0) ...

  8. Hibernate 注解之 @Temporal

    因为数据库中有个 Date类型的数据,在从数据库中获取数据[就是getXxx方法,当然,自动装配的时候可以直接写在字段上,但也只是针对getXxx方法,不会自动赋值]的时候可以利用这个 @Tempor ...

  9. MT【157】至少一个小于1

    若函数$f(x)=x^2+ax+b$有两个不等实数根$x_1,x_2$,且$1<x_1<x_2<3$,那么$f(1),f(3)中$    (      )A.只有一个小于1 B.至少 ...

  10. Beta 反(tu)思(cao) && 获小黄衫感言

    写在前面 终于要结束了...我的心情就像走在沙漠中的人看到了一片绿洲一样,身体很疲惫,心情是自由自在~ 这是一篇总结反思的博客 (为了附加分),顺便把早该写的获小黄衫感言一起发了. Beta 反思 做 ...