博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
unix/linux中的dup()系统调用 --对上篇dup() dup2()例子的解释
阅读量:2351 次
发布时间:2019-05-10

本文共 1835 字,大约阅读时间需要 6 分钟。

在linux纷繁复杂的内核代码中,sys_dup()的代码也许称得上是最简单的之一了,但是就是这么一个简单的系统调用,却成就了unix/linux系统最著名的一个特性:输入/输出重定向
sys_dup()的主要工作就是用来“复制”一个打开的文件号,使两个文件号都指向同一个文件。既然说简单,我们就首先来看一下它的代码(定义在fs/fcntl.c中):
187 asmlinkage long sys_dup(unsigned int fildes)
188 {
189 int ret = -EBADF;
190 struct file * file = fget(fildes);
191
192 if (file)
193 ret = dupfd(file, 0);
194 return ret;
195 }
而sys_dup()的主体是dupfd()(定义在同一个文件中):
116 static int dupfd(struct file *file, int start)
117 {
118 struct files_struct * files = current->files;
119 int ret;
120
121 ret = locate_fd(files, file, start);
122 if (ret < 0)
123 goto out_putf;
124 allocate_fd(files, file, ret);
125 return ret;
126
127 out_putf:
128 write_unlock(&files->file_lock);
129 fput(file);
130 return ret;
131 }
而这么一个简单的系统调用是如何完成重定向这个艰巨的任务的呢?我们不妨先看个例子。
当我们在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年前,可能你会改变你的看法。

转载地址:http://kshvb.baihongyu.com/

你可能感兴趣的文章
相约成都,周五众多知名企业再聚SDCC,约吗?一块启程(附参会名单及会前提醒)...
查看>>
React开发实践:如何做出好用的Switch组件
查看>>
HTML5 手势检测原理和实现
查看>>
十大案例,带你使用D3.js实现数据可视化
查看>>
创建敏捷产品蓝图的十个技巧
查看>>
使用GitLab来实现IOS项目的持续集成CI
查看>>
前端技术专家民工精髓V:如何增强单页应用的体验
查看>>
CSDN博文精选 微信小程序全方位解析
查看>>
致CSDN社区专家:年度盛典SDCC 2016诚邀您的加入
查看>>
在2016年学JavaScript是一种什么样的体验?
查看>>
年终技术盛会筹备中 SDCC 2016正公开征集演讲嘉宾
查看>>
微信小程序官方文档解读:如何才能避开小程序的规则“雷区”
查看>>
JavaScript运动详解:匀速运动、变速运动和曲线运动
查看>>
微信小程序架构分析系列文章
查看>>
聚焦热门框架、前端架构、工程化……,SDCC 2016前端开发专题讲师、议题大揭底...
查看>>
SDCC 2016讲师、知名JavaScript专家周爱民议题公布:有前端思想的物联网系统架构...
查看>>
Stackla前端团队Leader蒋定宇:国外前端开发者的别样人生
查看>>
从产品、技术到投资 微信小程序的全面解读
查看>>
从产品、技术到投资 小程序的全面解读
查看>>
从产品、技术到投资 小程序的全面解读
查看>>