linux 输入输出流和文件描述符浅析

File descriptors 是一个整数 表内存管理的对象,该对象可以由进程进行读写。

一个进程可以获取File descriptors通过打开文件 目录 或者设备,通过创建管道

或者复制一个已经存在的descriptors,

文件描述符将文件 管道 设备都抽象化为一样的东西,都像字节流.文件描述符作为索引映射到

进程表中。每一个进程都有文件描述符的私有化控件,从0开始。进程读取文件 文件描述符为0

写入文件描述符为1 写错误信息到文件标识符为2.

while((fd = open("console", O_RDWR)) >= 0){

8508             if(fd >= 3){

8509                     close(fd);

8510                     break;

8511                 }

8512         }

上面代码说明 shell对于控制台 总是要保证文件描述符的三种情况

(0标准输入 1标准输出,2标准错误流)都同时打开.

read函数从文件中读取字节

write函数向文件中写入字节

read(fd, buf, n) 从fd标识的文件中,读取n个字节存入到buf缓冲区中去

返回读取字节数量。read函数会持续从文件中读取字节,当读到文件末尾返回0 标识文件

读取结束。

write(fd, buf, n)从缓冲区读n个字节写入到fd标识的文件中,返回写入的字节数n,

比n少,就会有错误发生。

下面代码:从标准输入流读取字节 写入到标准输出流

char buf[512];

int n;

for(;;){

n = read(0, buf, sizeof buf);//0表示 输入流 从fd=0的文件中 读取sizeof buf个字节 存入缓冲区中

if(n == 0)//n =0 读取字节失败

break;

if(n < 0){//发生错误

fprintf(2, "read error\n");

exit();

}

if(write(1, buf, n) != n){//将buf缓冲区的数据 前n个字节 读入1 标准输出流中

fprintf(2, "write error\n");//如果写入的返回值 和n不等 则写入文件失败

exit();

}

}

Here is a simplified version of the code a shell runs for the

command cat <input.txt:

char *argv[2];

argv[0] = "cat";

argv[1] = 0;

if(fork() == 0) {

close(0);

open("input.txt", O_RDONLY);

exec("cat", argv);

}

子进程close(0) 将文件为0的fd收回 ,这样open函数保证"input.txt"返回的fd为0 是最小的。

此时 exec函数 让cat函数从input.txt 读取 fd=0标识标准输入流也就是从文件读取字节

流到内存中去。

重定向代码如下:

struct redircmd {

8376         int type;

8377         struct cmd *cmd;

8378        char *file;

8379         char *efile;

8380         int mode;

8381         int fd;

8382         };

//下面代码在runcmd函数中

8430 case REDIR:

8431         rcmd = (struct redircmd*)cmd;

8432         close(rcmd->fd);//关闭当前文件描述符

8433         if(open(rcmd->file, rcmd->mode) < 0){//打开新的文件描述符 打开失败返回小于0的数

8434             printf(2, "open %s failed\n", rcmd->file);

8435             exit();

8436         }

8437         runcmd(rcmd->cmd);//继续调用本函数 开始重新判断

8438         break;

对于shell执行 脚本命令的主循环关键代码如下

if(fork1() == 0)

8525         runcmd(parsecmd(buf));//之所以这里运用runcmd 而不是直接调用exec函数来执行

8526         wait();                            //为了应付各种情况的发生。

8527         }

8528     exit();

8529

父子进程中可以共享文件偏移量的如下面代码

if(fork() == 0) {

write(1, "hello ", 6);

exit();

} else {

wait();

write(1, "world\n", 6);

}

子进程将"hello "6个字节的字符串写入到标准输出流,退出

父进程 开始运行时候直接进入等待状态,等到hello 写完以后子进程退出后。

它开始将world 写入到标准输出流中去。最后打印出来 为hello world

说明父子进程公用一个文件描述符的偏移量。

类似的命令有(echo hello; echo world)>output.txt.

dup函数复制一个fd 并且返回的新的fd,和原来的fd公用一个文件偏移量。

例如下面代码 也会输出hello world!

fd = dup(1);

write(1, "hello ", 6);

write(fd, "world\n", 6);

进程之间的文件描述符,或者通过dup函数创建的文件描述符,都公用一个文件偏移量。

或者也可以说明代表一个特定的文件流。只有这两种情况,调用open函数打开同一个文件

返回的两个fd不会公用一个文件偏移量的。

Dup allows shells

to implement commands like this: ls existing-file non-existing-file > tmp1

2>&1. The 2>&1 tells the shell to give the command a file descriptor 2 that

is a duplicate of descriptor 1.

Both the name of the existing file and the error message for the

non-existing file will show up in the file tmp1. The xv6 shell doesn’t support

I/O redirection for the error file descriptor, but now you know how to implement it.

2>&1命令表示文件描述符2 是文件描述符1调用dup(1)的返回值。这样就会把existing-file non-existing-file

写入到同一个文件temp中去了。错误流不支持重定向 现在通过dup就可以实现它了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 23:58:55

linux 输入输出流和文件描述符浅析的相关文章

linux专题一之文件描述符、重定向、管道符、tee命令

本节讨论一下几个问题: 1. 文件描述符. 2. 重定向. 3. 管道符 4. tee的用法. 1. 文件描述符. 在linux系统中一切皆文件.文件夹和设备都是文件.如何用来区别不同的文件呢?这里的区别不是我们在windows下看到的后缀名不同来区别.也不是我们在linux下用ls 命令看到的不同文件的列表.这里的文件描述符主要讨论的是对文件操作的一个标识符.无操作就无标识符.   比如两个进程同时在对同一个文件进行读操作. 如何区分这两个读操作呢?这就需要文件文件描述符来区别了.每一次打开一

字符集修改、Linux时间同步、调整文件描述符

字符集 UTF-8:非定长,1-4字节,广泛支持,应用最广 GBK:定长,双字节,不是国际标准,支持的系统少 [[email protected] ~]# cat /etc/sysconfig/i18n LANG="en_US.UTF-8" SYSFONT="latarcyrheb-sun16" 先备份: [[email protected] ~]# cp /etc/sysconfig/i18n /etc/sysconfig/i18n.wuyike.20170411

[转] linux系统文件流、文件描述符与进程间关系详解

http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html linux(unix)进程与文件的关系错综复杂,本教程试图详细的阐述这个问题. 包括: 1.linux多/单进程与多/单文件对于文件流和描述符在使用时的关联情况及一些需要注意的问题. 2.fork,vfork流缓冲等对文件操作的影响. 1.linux文件系统结构 首先补充一点基础知识,了解一下linux文件系统.如下图所示: 图1 磁盘,分区和文件系统 应该明白,上图所示结构是硬盘中文件存放

[性能分析]linux文件描述符(转)

1.什么是文件和文件描述符 Linux中文件可以分为4种:普通文件.目录文件.链接文件和设备文件.1.普通文件是用户日常使用最多的文件,包括文本文件.shell脚本.二进制的可执行和各种类型的数据.ls -lh 来查看某个文件的属性,可以看到有类似 -rw-r--r-- ,值得注意的是第一个符号是 - ,这样的文件在Linux中就是普通文件.这些文件一般是用一些相关的应用程序创建,比如图像工具.文档工具.归档工具... .... 或 cp工具等.这类文件的删除方式是用rm 命令:2.目录文件在l

[性能分析]linux文件描述符

1.什么是文件和文件描述符 Linux中文件可以分为4种:普通文件.目录文件.链接文件和设备文件.1.普通文件是用户日常使用最多的文件,包括文本文件.shell脚本.二进制的可执行和各种类型的数据.ls -lh 来查看某个文件的属性,可以看到有类似 -rw-r--r-- ,值得注意的是第一个符号是 - ,这样的文件在Linux中就是普通文件.这些文件一般是用一些相关的应用程序创建,比如图像工具.文档工具.归档工具... .... 或 cp工具等.这类文件的删除方式是用rm 命令:2.目录文件在l

linux 最大文件描述符fd

使用四种框架分别实现百万websocket常连接的服务器 著名的 C10K 问题提出的时候, 正是 2001 年.这篇文章可以说是高性能服务器开发的一个标志性文档,它讨论的就是单机为1万个连接提供服务这个问题,当时因为硬件和软件的**,单机1万还是一个非常值得挑战的目标.但是时光荏苒,随着硬件和软件的飞速发展,单机1万的目标已经变成了最简单不过的事情.现在用任何一种主流语言都能提供单机1万的并发处理的能力.所以现在目标早已提高了100倍,变成C1000k,也就是一台服务器为100万连接提供服务.

Shell的文件描述符操作,包括标准输入,标准输出,自定义文件描述符

Abstract: 1) Linux Shell 命令的标准输入.标准输出.标准错误,及其重定位: 2)Linux Shell 操作自定义文件描述符: 文件描述符是与文件相关联的一些整数,他们保持与已打开文件的关联.众所周知的文件描述符是标准输入stdin.标准输出stdout.标准错误stderr,我们可以重定位这些文件描述符关联文件的内容到另外一个文件文件描述符. 1. Linux Shell 命令的标准输入.标准输出.标准错误 当我们在编写 shell 脚本时,我们会非常频繁地操作执行命令

18 shell 重定向以及文件描述符

1.对重定向的理解 2.硬件设备和文件描述符 文件描述符到底是什么 3.Linux Shell 输出重定向 4.Linux Shell 输入重定向 5.结合Linux文件描述符谈重定向 6.Shell 对文件描述符的操作 7.改变当前shell环境的重定向目标 8.示例 1.对重定向的理解 Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向:从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思. 输入方向就是数据从哪里流向程序.标准输入方向是指数据从键盘流向程序,

shell 重定向以及文件描述符

1.对重定向的理解 Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向:从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思. 输入方向就是数据从哪里流向程序.标准输入方向是指数据从键盘流向程序,如果改变了它的方向,数据就从其它地方流入,这就是输入重定向. 输出方向就是数据从程序流向哪里.标准输出方向是指数据从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向. 2.硬件设备和文件描述符 计算机的硬件设备有很多,常见的输入设备有键盘.鼠标.麦