在linux纷繁复杂的内核代码中,sys_dup()的代码也许称得上是最简单的之一了,但是就是这么一个简单的系统调用,却成就了unix/linux系统最著名的一个特性:输入/输出重定向。

sys_dup()的主要工作就是用来“复制”一个打开的文件号,使两个文件号都指向同一个文件。既然说简单,我们就首先来看一下它的代码(定义在fs/fcntl.c中):

1 asmlinkage long sys_dup(unsigned int fildes)

2 {

3     int ret = -EBADF;

4     struct file * file = fget(fildes);

5

6     if (file)

7         ret = dupfd(file, 0);

8     return ret;

9 }

10

而sys_dup()的主体是dupfd()(定义在同一个文件中):

1 static int dupfd(struct file *file, int start)

2 {

3     struct files_struct * files = current->files;

4     int ret;

5

6     ret = locate_fd(files, file, start);

7     if (ret

8         goto out_putf;

9     allocate_fd(files, file, ret);

10     return ret;

11

12 out_putf:

13     write_unlock(&files->file_lock);

14     fput(file);

15     return ret;

16 }

17

注:dup和dup2的原型如下:

#include

int dup(int file_descriptor);

int dup2(int file_descriptor1, int file_descriptor2)

dup返回的文件描述符总是取最小的可用值

dup2返回的文件描述符或者与file_descriptor2相同,或者是第一个大于该参数的可用值。

而这么一个简单的系统调用是如何完成重定向这个艰巨的任务的呢?我们不妨先看个例子。

当我们在shell下输入如下命令:“echo hello!”,这条命令要求shell进程执行一个可执行文件echo,参数为“hello!”。当shell接收到命令之后,先找到 bin/echo,然后fork()出一个子进程让他执行bin/echo,并将参数传递给它,而这个进程从shell继承了三个标准文件,即标准输入 (stdin),标准输出(stdout)和标准出错信息(stderr),他们三个的文件号分别为0、1、2。而至于echo进程的工作很简单,就是将参数“hello!”写到标准输出文件中去,通常都是我们的显示器上。但是如果我们将命令改成“echo hello! > foo”,则在执行时输出将会被重定向到磁盘文件foo中(注:重定向于文件描述符有关)。我们假定在此之前该shell进程只有三个标准文件打开,文件号分别为0、1、2,以上命令行将按如下序列执行:

(1) 打开或创建磁盘文件foo,如果foo中原来有内容,则清除原来内容,其文件号为3。

(2) 通过dup()复制文件stdout,即将文件号1出的file结构指针复制到文件号4处,目的是将stdout的file指针暂时保存一下

(3) 关闭stdout,即1号文件,但是由于4号文件对stdout也同时有个引用,所以stdout文件并未真正关闭,只是腾出1号文件号位置。

(4) 通过dup(),复制3号文件(即磁盘文件foo),由于1号文件关闭,其位置空缺,故3号文件被复制到1号,即进程中原来指向stdout的指针指向了foo。

(5) 通过系统调用fork()和exec()创建子进程并执行echo,子进程在执行echo前夕关闭3号和4号文件,只留下0、1、2三个文件,请注意,这 时的1号文件已经不是stdout而是磁盘文件foo了。当echo想向stdout文件写入“hello!”时自然就写入到了foo中。

(6) 回到shell后,关闭指向foo的1号与3号文件文件,再用dup()和close()将2号恢复至stdout,这样shell就恢复了0、1、2三个标准输入/输出文件。

由此可见,当echo程序(或其他)在运行的时候并不知道stdout(对于stdin和stderr同样)指向什么,进程与实际输出文件或设备的结合是在运行时由其父进程“包办”的。这样就简化了子进程的程序设计,因为在设计时只要跟三个逻辑上存在的文件打交道就可以了。可能有人会觉得这很像面向对象中 的多态和重载,没有什么新奇之处,但是如果你活在30甚至40年前,可能你会改变你的看法。

之前了解dup和dup2函数,但对于其真正对作用不太了解。这个例子,很好对说明其一个作用对功能->辅助重定向

linux dup作用,unix/linux中的dup()系统调用相关推荐

  1. linux中ftok的作用,Unix/Linux编程之ftok函数用法

    linux 中ftok函数的用法 1.函数作用: 系统建立IPC通讯(如消息队列.共享内存时)必须指定一个ID值.通常情况下,该id值通过ftok函数得到 2.函数原型: #include #incl ...

  2. php linux脚本文件,Unix/Linux中如何直接执行PHP脚本文件?

    使用Linux系统的服务器都有搭建完整的PHP环境,因此有些用户会用PHP去写一些执行自动化任务的脚本,可是发现每次执行PHP脚本都需要使用php myscript.php的方式,感觉有点麻烦.其实我 ...

  3. unix和linux命令_Linux / Unix系统中SSH命令的用法

    unix和linux命令 Any security-minded Linux user will always use SSH protocol when connecting to servers. ...

  4. linux access() rpm,Unix/LINUX rpm 命令示例

    RPM - Red Hat 的软件管理工具 Rpm是Linux中管理系统软件的.rpm命令可以用来安装.管理.卸载软件包.这里列一些常用的rpm管理命令: 列出说有安装的软件包 #rpm -qa 示例 ...

  5. 查看linux机器性能,Unix Linux 查看机器性能

    1.显示cpu数量: hp-unix:ioscan -C processor | grep processor | wc -l Solais:psrinfo -v | grep "Statu ...

  6. unix linux 命令参考,Unix/Linux 命令参考

    文件命 令 ls – 列出目录 ls -al – 使用格式化列出隐藏文件 cd dir - 更改目录到 dir cd – 更改到 home 目录 pwd – 显示当前目录 mkdir dir – 创建 ...

  7. unix/linux编程实践,Unix/Linux编程实践教程–cp在OS X的实现

    环境:OS X10.12.4 书中的代码对于OS X是适用的.值得提一嘴的是,其实OS X的open是可以在文件不存在的时候自动创建的,man 2 open时,就可以看到这个说明. The oflag ...

  8. linux下 get,Unix/Linux下 getrusage 的用法

    #include int getrusage(int who, struct rusage *r_usage); 利用getrusage可以得到进程的相关资源信息.如:用户开销时间,系统开销时间,接收 ...

  9. linux io函数,unix/Linux低级IO函数的用法有哪些? 爱问知识人

    内容包括: open() ,尤其是各种常见的参数,到底是什么意思, 比如常用创建一个空文件: fd = open("/tmp/xx.txt",O_RDWR | O_CREAT | ...

最新文章

  1. WinDbg安装与使用
  2. Putty的设置保存
  3. 田刚:怀念陈省身先生
  4. android本地socket正常,【报Bug】Android 本地打包 websocket 出错
  5. Qt做发布版,解决声音和图片、中文字体乱码问题
  6. NET 连接池救生员
  7. vs2005 编码转换后编译的时候会出错,”error c101008a“,处理方法
  8. 从苏宁电器到卡巴斯基第34篇:番外篇——晒一晒病毒分析师的桌面(上)
  9. 天线设计-电感计算以及天线匹配
  10. 恩智浦 飞思卡尔Freescale Kinetis KEA128学习笔记3--GPIO模块(一)
  11. 数据挖掘实例(航空公司客户价值分析)
  12. 【实用技巧】 修改度娘的提取码
  13. 面向万物智联的云原生网络
  14. 地图 svg中国地图、echarts百度迁徙图
  15. 高德地图的circle圈
  16. 【情报工具】分享15款保护隐私的搜索引擎
  17. 搭建Nginx-rtmp流媒体服务器+使用ffmpeg推流
  18. 三人行网络教育计算机二,三人行老师电脑版
  19. Sublime text代码补全插件(支持Javascript、JQuery、Bootstrap框架)
  20. 数据库查询时出现 unknown column

热门文章

  1. 树莓派 3B+ HDMI 分辨率改不了 和一些坑坑洼洼
  2. surface go 安装纯AndroidX86系统
  3. 初学者如何3步入门选吉他,附上新手购琴常见问题和吉他品牌推荐
  4. Elasticsearch:Hadoop 大数据集成 (Hadoop => Elasticsearch)
  5. mysql simpleconsumer_SimpleMessageListenerContainer:Consumer raised exception
  6. IBM DS3400换电池后报错Individual Drive –Degraded path
  7. Maven基础-认识Maven
  8. (数据结构基础)Among the following threaded binary trees (the threads are represented by dotted curves),……
  9. 如何玩好微信十亿流量?微趋道教你小程序推广最全攻略!
  10. PS——使用 快速选择工具、魔法棒 抠图