一、打开文件内核数据结构

1、一个进程打开两个文件

文件状态标志:读、写、追加、同步、非阻塞等

2、一个进程两次打开同一文件

3、两个进程打开同一文件

示例程序:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
/*************************************************************************
    > File Name: file_share.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(int argc, char *argv[])
{
    int fd1, fd2;
    char buf1[1024] = {0};
    char buf2[1024] = {0};
    /* 进程控制块PCB
     * struct task {
     * ...
     * struct files_struct *files;
     * }
     * 同一个进程两次打开同一个文件,一个进程拥有的一个文件描述符表其中一个fd索引对应的指针指向一个
     * 文件表(包括文件状态(读写追加同步非阻塞等),当前文件偏移量,
     * 文件引用次数(当有两个fd指向同个文件表时引用计数为2,见dup,也可用于重定向),
     * 文件操作指针, V节点指针等)不共享,
     * V节点表(包括V节点信息(struct stat), i节点信息等)共享
     */
    /* 两个进程打开同一个文件的情况与上类同*/
    fd1 = open("test.txt", O_RDONLY);
    if (fd1 == -1)
        ERR_EXIT("open error");
    read(fd1, buf1, 5);
    printf("buf1=%s\n", buf1);

fd2 = open("test.txt", O_RDWR);
    if (fd2 == -1)
        ERR_EXIT("open error");
    read(fd2, buf2, 5);
    printf("buf2=%s\n", buf2);
    write(fd2, "AAAAA", 5);

memset(buf1, 0, sizeof(buf1));
    read(fd1, buf1, 5);
    printf("buf1=%s\n", buf1);
    close(fd1);
    close(fd2);

return 0;
}

假设test.txt文件的内容是 ABCDEhello

测试如下:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_share 
buf1=ABCDE
buf2=ABCDE
buf1=AAAAA

test.txt文件内容变成 ABCDEAAAAA

分析:由上图分析可知,一个进程两次打开同一文件,文件表是不共享的,即各有自己的文件偏移量和打开文件标志,所以两次read不同的fd都是从头开始读取,但V节点表是共享的,在fd2写入(同个文件表的read和write是共享偏移的)更改了inode指向的硬盘数据块,再次read
fd1得到的也是更改后的值。

二、I/O重定向

当我们执行了dup(3)之后,系统选择一个空闲的文件描述符即4,这样就有两个文件描述符指向同个文件表,所以引用计数为2。利用dup等函数可以进行重定向的步骤是先close输入输出文件描述符,然后执行dup(fd),
这样输入输出文件描述符也指向fd指向的文件,这样就实现了重定向。此外dup2, fcntl
函数也可以实现,其实不使用这些函数,而直接close(0/1/2)完再open也可以实现。如下使用cat命令实现复制文件的功能:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
/*************************************************************************
    > File Name: process_.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(int argc, char *argv[])
{
    close(0);
    open("Makefile", O_RDONLY);
    close(1);
    open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);

execlp("cat", "cat", NULL);

return 0;
}

现在标准输入是文件Makefile,标准输出是文件test.txt ,将当前进程替换成cat,则cat会从标准输入读而后输出到标准输出,即完成了copy的功能。

dup/fcntl 函数示例程序如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
/*************************************************************************
    > File Name: file_dup.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

/* dup dup2 fcntl */
int main(int argc, char *argv[])
{
    int fd;
    fd = open("test2.txt", O_WRONLY);
    if (fd == -1)
        ERR_EXIT("open error");
    /*
        close(1);
        dup(fd);
    */
    //  dup2(fd, 1);

close(1);
    if (fcntl(fd, F_DUPFD, 0) < 0) //从0开始搜索可用的fd
        ERR_EXIT("fcntl error");
    printf("hello\n"); // 输出重定向到test2.txt
    return 0;
}

参考:《APUE》

文件的内核结构file和dup实现重定向的更多相关文章

  1. 文件描述符与FILE

    1. 文件描述符(重点) 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件.链接文件和设备文件.文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创 ...

  2. android内核读取file文件

    内核读取file文件的方法: char* file_read(const char * file_path) { struct file *file = NULL; //保存打开文件的文件指针变量 s ...

  3. Linux基础系列—Linux体系结构和Linux内核结构

    /** ****************************************************************************** * @author    暴走的小 ...

  4. linux下各文件夹的结构说明及用途介绍

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令.   /dev:设备特殊文件.   /etc:系统管理和配置文件.   /etc/rc.d:启动的配 置文件和脚本.   /ho ...

  5. 【转】linux下各文件夹的结构说明及用途介绍

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...

  6. Linux下各文件夹的结构说明及用途介绍(转载)

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...

  7. linux下各文件夹的结构说明及用途介绍:Linux目录结构介绍

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...

  8. VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)

    VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)-软件开发-鸡啄米 http://www.jizhuomi.com/software/143.html   鸡啄米在上一讲中 ...

  9. c语言_文件操作_FILE结构体解释_涉及对操作系统文件FCB操作的解释_

    1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...

随机推荐

  1. Python中filter、map、reduce、lambda 的用法

    Python内置了一些非常有趣但非常有用的函数,充分体现了Python的语言魅力! filter(function, sequence):对sequence中的item依次执行function(ite ...

  2. 基于jQuery的Cookie操作插件--简单而又没有兼容性问题!

    在网页客户端,我们经常会遇到读取或者设置cookie的情况,如果用纯生的js我们可能会遇到一些兼容性带来的麻烦,这里给大家介绍一个比较实用jquery操作cookie的插件,插件的源代码如下: 1 2 ...

  3. [置顶] Java中字符串为什么不以\0结尾

    其实这个问题没有什么好说的,Java里面一切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间用以标明字符串的结束了. 学过C ...

  4. Qtcreator中常用快捷键总结

    F1        查看帮助F2        跳转到函数定义(和Ctrl+鼠标左键一样的效果)Shift+F2    声明和定义之间切换F4        头文件和源文件之间切换Ctrl+1     ...

  5. COM的一些基本概念

      Windows lets you share code at the binary level using DLLs. After all, that's how Windows apps fun ...

  6. 将浮点数保持几位小数,尾数舍入的Format函数

    select format(hours,2) from pos.daywork

  7. Vector 多字段排序的Java实现

    要求实现: Vector 多字段排序,其中首元素不参与排序,第一二三字段升序,空排到前面. //这里是Vector的元素定义 public class AVectorElement { private ...

  8. 修复损坏的 shapefile

    一.SHP文件 Shapefile文件(简称SHP)作为ESRI一种经典的数据格式,被很多其他软件所支持,如CAD.MapGIS等,虽然也有一些限制(如无法进行拓扑分析.字段长度为10个字符等),但其 ...

  9. whereis 命令(转)

    原文:http://www.cnblogs.com/peida/archive/2012/11/09/2761928.html whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b) ...

  10. Windows删除无效服务

    W+R运行:regedit http://os.51cto.com/art/201208/354989.htm