文件描述符?文件流指针?


前言

在C标准库的I/O中我们提到文件流指针 ,在系统调用i/O接口中提到了文件描述符。这次来看看这两个东西有什么区别


一、文件描述符是什么?

由上图可知,文件描述符就是从0开始的小整数 。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体 ,表示一个已经打开的文件对象,而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files(在pcb中) ,然后这个指针指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标 。所以 ,只要拿着文件描述符 ,就可以找到对应的文件。

我们尝试打印一下这个文件描述符的值;

然后我们再关闭1号描述符(stdout);

因为关闭了标准输出stdout,1号位置空出来,fd便会占据1号位置 ,数据并非写入到标准输出流,而是写入到当前“1 ”号描述符指向的my*file文件的缓冲区,由于“换行刷新缓冲“只能在stdout有效所以不打印;
然后我们再手动刷新缓冲区 ,1就会被打印出来。

然后我们再关闭“0”或者“2”号描述符;

此时我们便可以得出一个重要的结论暨文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符 。

二、文件描述符和文件流指针的关系

文件流指针:库函数IO接口的操作句柄FILE *fp;
文件描述符:系统调用IO接口的操作句柄 int fd。
库函数与系统调用接口的关系:库函数封装了系统调用接口。
文件流指针的标准输入输出和错误:stdin 、stdout、stderr 。
我们看一下源码:

stdin、stdout 、stderr这三个都是struct _IO_FILE 类型的指针 。

上图中将结构体重定义为FILE ,就是文件流指针。

文件流指针归根究底就是个结构体,里面包含了一个成员变量,就是文件描述符 ,相当于文件流指针是对文件描述符的一层封装。
例如我们使用fopen时,实际上是把open返回的fd赋给了在文件流指针的结构体中封装的_fileno 。

三 、重定向

代码如下(示例):上面我们举的关闭1号描述符的例子中,本来应该输出到显示器上的内容 ,却输出到了我们指定的文件中 ,其中fd = 1,这种现象就叫做“输出重定向 ”,字面意思可以大概理解为把stdout用新的文件替代了。
常见的重定向有:> (清空重定向);>>(追加重定向)
举个栗子:

实质就是改变了数据流向。

重定向的原理:通过改变文件描述符对应位置的文件描述信息 ,进而改变所操作的文件,实现数据流向的改变 。


dup2系统调用接口:

dup2(old fd, new fd);让new fd成为old fd的复制版。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    //close(1);   
    int fd = open("./_file_test.txt",O_CREAT|O_RDWR|O_TRUNC,0664);
    if(fd<0)
    {
        perror("open error");
        return -1;
    }
    dup2(fd,1);//
    printf("fd = %d\n",fd);//打印文件描述符的值
    fflush(stdout);
    close(fd);
    return 0;
}

1复制了fd的描述信息 ,所以1也指向fd指向的文件。也不会打印在显示屏上,而是将数据写入fd指的文件中 。


总结

文件流指针是结构体,文件描述符是数组下标 ,重定向就是改变数据流向

本文版权归趣快排营销www.SEOguruBLOG.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ㊣61910465