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

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. 几行JavaScript代码搞定Iframe 自动适应

    场景:Iframe嵌入flash,希望flash能随着页面的resize而resize. 主要代码: 代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTM ...

  2. IOS基本数据类型之枚举

    枚举是C语言中的一种基本数据类型,通过枚举可以声明一组常数,来代表不同的含义,它实际上就是一组整型常量的集合. 枚举是非常常用的一种类型,在现实生活中也很常见.比如有四个季节,在不同的季节需要显示不同 ...

  3. android_orm框架之greenDAO(一)

    目录: 一.概述 二.下载并解压greenDAO相关资源 三.应用greenDAO框架 1.创建Java工程 2.添加类库支持 3.创建类 四.代码分析 五.使用greenDAO 六.源码下载 一.概 ...

  4. mysql 数据库远程访问设置方法

    摘自: http://www.iteye.com/topic/418151 mysql数据库远程访问设置方法 1.修改localhost更改 "mysql" 数据库里的 " ...

  5. Oracle查询client编码集

    Oracle查询client编码集 SQL> select userenv('language') from dual; USERENV('LANGUAGE') ---------------- ...

  6. 免费的HTML模板引导 - lonely

    ​在线演示 本地下载 今天和大家分享另一款模板-Lonely.它可以被用在一些个人或者类似简单一些的网站上,动画效果的滚动非常特别!

  7. C#.NET常见问题(FAQ)-如何把写好的类编译成dll文件

    1 新建一个类库项目   2 直接改写这个Class1.cs文件   3 记得要添加Windows.Forms引用   4 我直接把在别的项目中做好的cs文件搞到这里来,连文件名也改了(FilesDi ...

  8. Nginx负载均衡简易方法

    做个简单的测试,一个Nginx, 通过FastCGI协议和另外两台服务器上的基于CppCMS开发的web server通信.配置方法很简单: 首先,必须在nginx.conf文件开头,server 配 ...

  9. MySQL单列索引和组合索引(联合索引)的区别详解

    发现index merge局限性,优化器会自动判断是否使用 index merge 优化技术,查询还是需要组合索引[推荐阅读:对mysql使用索引的误解] MySQL单列索引和组合索引(联合索引)的区 ...

  10. 微信小程序-开发入门(一)

    微信小程序已经火了一段时间了,之前一直也在关注,就这半年的发展来看,相对原生APP大部分公司还是不愿意将主营业务放到微信平台上,以免受制于腾讯,不过就小程序的应用场景(用完即走和二维码分发等)还是很值 ...