Linux 文件描述符到底是什麼東西

  • 這篇博客很長,希望你能看完,是我自己對文件描述符的一些理解,希望能幫助到你

文件描述符

什麼是文件描述符

  • 文件描述符是操作系統在進行進程文件管理時,所引入的一種管理方法,這種管理方法是 先描述文件的一系列信息,然後再通過這個文件描述符,進行文件的一些列讀寫操作

文件描述符在進程中是如何存儲的

  • 在進程的PCB中,有專門寸出文件描述符的位置。
  • 在PCB中,有一個*files 的指針,這個指針指向一個名叫 files_struct 的指針數組,這裏這個指針數組裏存儲的就是指向不同文件的指針,既然是一個數組,那就可以通過下標進行數組元素的訪問,所以,這裏數組的下標的值,就是文件描述符的值。
    在這裏插入圖片描述
  • 在linux中,一切皆文件,在計算機當中,我們最常接觸的就是標準輸入和標準輸出,還有標準錯誤輸出,這三個在linux中都是以文件的形式存在的,一個進程在開闢的時候,會自動打開這三個文件,存放在 0 1 2 的下標的位置,所以,這三個對應 標準輸入,標準輸出,標準錯誤輸出。
  • 我們如果在進程中打開文件的時候,系統就會在這個進程的files_struct中添加進對應的文件的指針,然後返回這個文件指針對應的文件描述符,也就是這個文件的下標。我們在進行文件讀寫操作的時候,如果我們調用的是系統提供的讀寫操作接口的話,就勢必需要使用文件描述符進行操作。(注意,是系統提供的接口,我們在學習語言的時候,其實是通過語言所提供的接口,而非操作系統所提供的接口)這裏我畫了一個圖,幫助你理解系統調用和函數庫調用
  • 在這裏插入圖片描述
  • 系統調用接口,正是繞過了語言所提供的庫函數接口,實現了直接面向操作系統的文件操作

文件描述符的一系列操作

  • 如果要直接用文件描述符對文件進行讀寫操作的話,就需要調用系統提供的接口,系統提供的接口主要有一下幾個
  • 文件的打開接口
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

int open(const char* pathname, int flag);
int open(const char* pathname, int flag, mode_t mode);
//參數介紹
flag:
	O_RDONLY:只讀打開
	O_WRONLY:只寫打開
	O_RDWR :讀寫打開
	O_CREAT:若文件不存在,就創建一個文件
	O_APPEND:追加寫
	注意,以上三個文件,通過‘|’操作符進行組合,達到對應的目的,至於爲什麼是‘|’,你可以理解爲,不同的flag對應不同的 二進制位的1,通過‘|’,可以將這些flag結合起來,達到對應的目的。
	返回值:如果成功,返回對應的文件描述符,如果失敗,返回-1
	mode就是權限,對應的0000這四個位的權限,一般設置爲0644,如果不進行設置的話,就會隨機生成文件的權限。
  • 文件的讀寫接口
#include<unistd.h>

ssize_t write(int fd, const void* buf,size_t count);
ssize_t read(int fd,void *buf,size_t count);
int close(int fd);
off_t lseek(int fd,off_t offset,int whence);

這裏的fd,就是文件對應的文件描述符,可以看到,系統所提供的這幾個接口,都是通過文件描述符,
對文件進行的操作。
//////////////////////////////
在write和read函數中,buf就是緩衝區,write通過緩衝區向文件裏寫數據,read通過緩衝區,
將從文件裏讀到的數據寫入到緩衝區裏,然後帶回來。 
write和read 的 count都是一次要讀或寫的期望個數。read的期望數量可以大於你讀到的數據的長度,
讀到文件的結尾就會自動停止,但是寫的話,最多不能超過你所寫的數據的長度。
  • 以上就是文件讀寫操作的一些接口,如何使用這些接口,看接下來的代碼
 
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>

int main()
{
    char buf[100];
    int fd_wr = open("hello.txt",O_WRONLY|O_CREAT,0644);//以只寫的方式打開文件,
                //如果文件不存在,就創建一個文件。主意路徑名,如果你沒有寫絕對路徑的話,
                //就會在當前程序所在的目錄下創建文件。
	char *msg = "hello world\n";
 	if(fd_wr < 0)//判斷文件是否打開成功
 	{
     perror("open file");
 	}
 	write(fd_wr,msg,strlen(msg));//向文件裏寫數據
 	close(fd_wr);//關閉文件
//////////////////////////////////////////////////////////////////////////////////
 	int fd_rd = open("hello.txt",O_RDONLY);//以只讀方式打開文件
 	if(fd_wr < 0)//判斷文件是否打開成功
 	{
    	 perror("open file");
 	}
 	ssize_t s = read(fd_rd,buf,sizeof(buf));//將文件裏的數據讀入到buf中,並返回讀到的字節數
 	buf[s] = '\0';//最讀到的字符串最後加0,結尾,方便打印
 	printf("%s",buf);                                                                                                                      
 	close(fd_rd);//關閉文件
 	return 0;
}
  • 以上,便是對文件的基本讀寫操作,在操作系統中,如果想對文件進行操作的話,利用的就是文件描述符,如果你在輸出的時候,向標準輸出文件中寫數據的話,系統就會將數據寫到顯示器上,但是,有一點要注意,就是在寫完之後,需要將標準輸出中緩衝區內的數據刷出來,才能直觀的看到所寫入的數據

注意事項

  • 文件描述符在分配的時候,並不是按照你打開的文件的順序進行分配的,而是,從目前能分配的最小的文件描述符進行分配,比如說:你如果關閉了這個進程的標準輸入和標準輸出,這兩個文件的文件描述符就會被釋放,然後,再次打開一個新的文件的時候,就會給這個文件分配一個0的文件描述符,佔有標準輸入的文件描述符的位置。
  • 在進行文件讀寫操作過後,一定要記得關閉文件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章