文档章节

unix/linux中的dup()系统调用

猫七猫七
 猫七猫七
发布于 2017/05/31 11:07
字数 1118
阅读 16
收藏 0

在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 < 0)
 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 <unistd.h>

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函数,但对于其真正对作用不太了解。这个例子,很好对说明其一个作用对功能->辅助重定向

本文转载自:http://www.blogjava.net/lihao336/archive/2011/12/13/366231.html

共有 人打赏支持
猫七猫七
粉丝 0
博文 3
码字总数 513
作品 0
温州
man综述--系统调用和库函数的关系

Tips: 用man查询函数时候有些并不能直接man + 函数名查到,例如:man fopen man 2 open 所以可以用man+数字+函数名来试试,具体的内容可以查看 /usr/local/share/man/下面对应的目录 _ Linu...

AlphaJay
2011/07/28
0
0
linux常用文件I/O操作之文件共享的实现方式

1、文件共享的三种实现方式 1、什么是文件共享: (1)文件共享就是同一个文件(同一个文件指的是同一个inode,同一个pathname)被多个独立的读写体(几乎可以理解为多个文件描述符)去同时(一...

捕风的xiao_k
06/26
0
0
我闻到了linux新内核的坏味道

最近翻出了linux2.6.27的邮件列表,发现大牛们在讨论一个问题,就是说该如何扩展系统调用,是对每个需要扩展的系统调用都封装一个新的系统调用,还是添加仅仅一个系统调用来封装所有的需要扩...

晨曦之光
2012/04/10
78
0
I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)

1、I/O重定向的概念与原因 及 标准输入、输出的标准错误的定义 所以的Unix I/O重定向都基于标准数据流的原理。三个数据了分别如下: 1)标准输入——需要处理的数据流 2)标准输出——结果数...

木子叶
2014/08/06
0
0
Linux 系统编程笔记

Linux/Unix常用底层库 unistd.h unix standard stdlib.h standard library fcntl.h file control sys.h system stdio.h standard input/output dirent.h directory entries string.h string ......

海涛
2016/08/08
39
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

nginx访问日志-日志切割-静态文件不记录日志和过期时间

nginx访问日志: vim /usr/local/nginx/conf/nginx.conf #搜索log_format 该字段定义日志格式,默认如下: #combined_realip日志格式的名字,可随意定义; 定义访问日志: 需在虚拟主机配置文...

ZHENG-JY
3分钟前
0
0
180.mariadb 主从复制

参考:https://blog.csdn.net/chengxuzaza/article/details/62042920 睡觉睡觉,明天写 1.效果 当主库中数据有变化的时候,从库就自动同步 2. 环境要求 至少两台 linux服务器 (教程:https...

Lucky_Me
13分钟前
0
0
erlng file id3v1 id3v1.1

%% ---%% Excerpted from "Programming Erlang",%% published by The Pragmatic Bookshelf.%% Copyrights apply to this code. It may not be used to create training material, %% ......

xueyuse0012
14分钟前
1
0
RabbitMq的安装

环境Centos6.5 32位 JDK 1.7.8 Jdk的卸载 rpm -qa|grep jdk yum –y remove 上边的安装包 JDK的安装 Rpm –ivh jdk安装包 配置环境变量 export JAVA_BIN=/usr/java/jdk1.7.0_80/bin export J......

DemonsI
18分钟前
0
0
http和https协议

HTTPS全称为Hypertext Transfer Protocol over Secure Socket Layer,中文含义为“超文本传输协议在安全加密字层”,简单来说就是加密数据传输,通俗的说就是安全连接。 HTTPS安全超文本传输...

寰宇01
24分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部