Linux标准输入、重定向与参数传递

按惯例,每当运行一个新程序时,所有shell都为其打开3个文件描述符,即标准输入、标准输出以及标准错误。如果不做特殊处理,例如就像简单的命令ls,则这三个描述符都链接向终端。大多数shell都提供一种方法,使其中一个或所有这3个描述符都能重新定向到某个文件。

——《UNIX环境高级编程(第三版)》

也就是说,我们可以用文件内容来替代从终端输入的内容,也可以用文件来代替终端接收程序输出的内容。于是,我写了个简单的求两数和的小程序测试重定向功能:

#include <stdio.h>
int main(int argc,char** argv)
{
int a,b;
a=argv[1][0]-'0';
b=argv[2][0]-'0';
printf("The sum is %d\n.",a+b);
exit(0);
}

编译,测试:

gcc add.c -o add
./add 1 2

输出:

The sum is 3.

没有问题。

继续测试重定向,测试文件input的内容只有两个数字:

1 2

输入命令:

./add < input

得到的输出却是:

Segmentation fault (core dumped)

奇怪,为什么重定向不起作用了,文件中的内容和我在命令行中输入的内容完全一样,为什么却引起了错误?

然后我想明白了,标准输入、标准输出、标准错误对于程序来说,都是文件,它们确实默认被链接到终端上了。但是这并不是说从终端输入的所有内容都属于标准输入,当我们输入命令

./add 1 2

时,这条语句不属于标准输入,而是作为一条“命令”传给命令解释器的,而其后跟随的两个数字“1 2”自然也不属于标准输入,而是属于“命令”的一部分——作为参数一起传递给命令解释器(Command Interpreter)的。

同时,源文件中的main函数括号中的 argc 和 argv 所接收的也不是标准输入的内容,而是由命令解释器传递过来的参数"1" "2"。整个程序压根就没有从标准输入获取数据,只是接收了命令解释器传过来的“参数”,做的运算也是基于“参数”的。

基于这两点,之前的错误就好理解了,当我们输入:

./add < input

时,程序 add 对应的标准输入的确被重定向为了文件 input,但是由于它不从标准输入读内容,所以这个重定向对它来说没有意义。又由于这条语句中没有向add传递其程序中所需要的参数,在运行过程中当需要用到两个参数时就会找不到,于是发生"Segmentation fault" 的错误。

意识到这一点后,重写一下源代码,把两个加数的来源改一下:

#include <stdio.h>
int main(void)
{
int a,b;
scanf("%d %d",&a,&b); //这才是从标准输入中获取数据
printf("The sum is %d.\n",a+b);
exit(0);
}

编译:

gcc add.c -o add

运行,并输入两个加数、得到结果:

./add
1 2
The sum is 3.

再测试重定向:

./add < input
The sum is 3.

这样一来就OK了。

有个问题:为什么其他程序就可以通过重定向来正常运行?比如:

cat input
cat < input

输出都是input文件的内容:

1 2

为什么cat就可以同时适用这两个方法?这两条命令其实机制不一样,第一条是cat程序接收命令解释器传来的参数字符串"input",然后根据这个字符串参数在目录中搜索到名为"input"的文件,再获取内容,进而运行。而第二条则是通过重定向把cat的标准输入替换成input文件,cat直接从这个文件中获取其内容,进而运行。因此,虽然这两条命令使用的是相同的程序、读取的是相同的文件、输出的是同样的结果,但程序获取文件内容的途径是完全不一样的。

总结:

  • 标准输入、标准输出、标准错误都被程序当做文件,且自动链接到终端上。

  • 但并非所有从终端输入的内容都属于标准输入,有时只是作为命令的参数来传递给程序的。Linux下程序获取内容有两种方式:一种是从文件输入(从终端或控制台手动输入也属于文件),一种是在程序启动的同时就从命令解释器直接传递(注意,叫“传递”而不是叫“输入”)过来的命令参数,它们有时可以完成相同的效果,但这完全是两种机理。

  • 那么,从终端输入的内容,什么时候是“标准输入”、什么时候是“参数传递”呢?

    • 答:伴随程序启动时就附在命令后面的内容属于参数,当程序启动之后才从终端输入的才叫“标准输入”(标准输入本质上就是一种文件)。
    • 因为,所谓的“标准输入”、“标准输出”、“标准错误”等文件描述符,都是相对于程序而言的,只有当程序启动之后它们才被建立。也就是说,虽然都叫“标准输入/输出/错误”、虽然都是从终端输入/输出,但不同程序的“标准输入”是不一样的,只不过都被默认链接到终端上了而已。
    • 比如,假设你在前台运行程序A,当你在终端上把程序A调到后台运行,把程序B调到前台时,你从终端上输入的内容已经不再属于A而是属于B了。这是因为你把A调到后台之后,A的标准输入就与终端断开了联系,而B的标准输入开始与终端建立起联系来,于是,你的输入的内容自然不归A而归B了。

码字不易,倘若觉得分享有益,就点个赞再走呗~

Linux标准输入、重定向与参数传递的更多相关文章

  1. Linux标准输入、输出和错误和文件重定向(转) --- good

    标准输入.输出和错误 当我们在shell中执行命令的时候,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件.由于文件描述符不容易记忆,shell同时也给出了相应的文件名.下面就是这些文 ...

  2. Linux标准输入、输出和错误和文件重定向 专题

    当我们在shell中执行命令的时候,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件.由于文件描述符不容易记忆,shell同时也给出了相应的文件名. 下面就是这些文件描述符及它们通常所 ...

  3. linux --stdin 管道 标准输入重定向

    linux --stdin 标准输入重定向 --stdin This option is used to indicate that passwd should read the new passwo ...

  4. Linux Shell 重定向与管道【转帖】

    by 程默 在了解重定向之前,我们先来看看linux 的文件描述符. linux文件描述符:可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以 ...

  5. 全面理解Linux输入输出重定向

    全面理解Linux输入输出重定向 本教程通过视频方式讲解shell操作,理解感念,教程通俗易懂,比起看一大堆文档要舒服的多.本次教程主要讲解  Linux Shell 中支持输入输出重定向,用符号&l ...

  6. 十句话教你学会Linux数据流重定向

    1.看到重定向一下子就想起了web里面的redirect,没错,但是Linux数据流重定向的作用不是跳到另一个网页,而是用来存储重要的屏幕信息.将不必要的屏幕信息输出到文件里或者“黑洞”里.将错误信息 ...

  7. Linux数据流重定向与管道

    数据流重定向简单来说就是把原本应该输出到某处(比如说屏幕)的数据,重定向其输出目的地,到其他的地方(比如文件). linux中的输入与输出: 标准输入(stdin):默认从键盘输入 标准输出(stdo ...

  8. Linux shell 重定向学习笔记

    在了解重定向之前,我们先来看看linux 的文件描述符. linux文件描述符:可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读 ...

  9. linux命令重定向>、>>、 1>、 2>、 1>>、 2>>、 <

    重定向命令其实用得不少吧,只是重来都没有仔细看过,这波正好又用到 又有空总结一波. 先看>和>>: 他们俩其实唯一的区别就是>是重定向到一个文件,>>是追加内容到文 ...

随机推荐

  1. dynamic creat svg in js

    dynamic creat svg in js SVG title https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title < ...

  2. vue2.0用法以及环境配置

    一.配置环境搭建 1.安装node.js (可以去官网看) 2.安装git (推荐看廖雪峰文章,点击查看) 3.安装vue: cmd:npm install vue //最新稳定版本 npm inst ...

  3. 嵌入式开发板使用网口和nfs进行文件共享

    如果你的开发板有网口,类似于这玩意. 那么,你可以去买根网线,类似于这玩意. 然后你就可以将你的电脑和开发板用网线连起来,通过nfs(网络文件系统)来进行文件夹共享,文件夹共享就相当于挂载,nfs是利 ...

  4. Github Action 快速上手指南

    前言 各位读者,新年快乐,我是过了年匆忙赶回上海努力搬砖的蛮三刀. Github之前更新了一个Action功能(应该是很久以前了),可以实现很多自动化操作.用来替代用户自己设置的自动化脚本(比如:钩子 ...

  5. Zookeeper从入门到删库跑路

    导语 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等.Zookeeper是hadoop的一个子项 ...

  6. 【Notes】现代图形学入门_01

    跟着闫令琪老师的课程学习,总结自己学习到的知识点 课程网址GAMES101 B站课程地址GAMES101 课程资料百度网盘[提取码:0000] 计算机图形学概述 计算机图形学是一门将模型转化到屏幕上图 ...

  7. HashMap什么时候进行扩容?

    Threshold:table数组元素个数size的大小超过threshold且且Node<K,V>[] table数组长度没有超过64时时table数组扩容.当hashmap中的元素个数 ...

  8. Django-1.11中文文档——操作关联对象

    关联对象参考 写在最前面--基础示例模型如下: from django.db import models class Blog(models.Model): name = models.CharFie ...

  9. 微信小程序自定义头部导航栏

    <!--index.wxml--> <view> <navbar id='index_header' background='{{background}}' pageNa ...

  10. Java跨平台原理与Java虚拟机(JVM)

    Java跨平台原理(字节码文件.虚拟机) C/C++语言都直接编译成针对特定平台机器码.如果要跨平台,需要使用相应的编译器重新编译. Java源程序(.java)要先编译成与平台无关的字节码文件(.c ...