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


前言

在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指的文件中。


总结

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

本文版权归QU快排Www.seoGurubLog.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ▲61910465