Linux:基礎IO---文件描述符

文章目錄

      • 1. 前言
        • 1.1 C語言文件知識回顧
      • 2. 文件
        • 2.1 文件基礎知識
      • 3. 被打開的文件
        • 3.1 以C語言為主,先回憶一下C文件接口
        • 3.2 過渡到系統,認識文件系統調用
        • 3.3 訪問文件的本質
        • 3.4 重定向&&緩沖區

  • 序:在深入了解了進程的內容后,我們對于進程的學習將會告一個段落,現在我將對Linux中的基礎IO部分的內容進行一個梳理,本章節將圍繞文件描述符來走進文件的部分,進而了解對于基礎IO這個宏觀的理解。

1. 前言

1.1 C語言文件知識回顧

文件分為程序文件和數據文件
文件名 == 文件路徑+文件名主干+文件后綴

數據文件:

  • 文本文件
  • 二進制文件

流:

我們程序的數據需要輸出到各種外部設備,也需要從外部設備獲取數據,不同的外部設備的輸?輸出操作各不相同,為了方便程序員對各種設備進行方便的操作,我們抽象出了流的概念,我們可以把流想象成流淌著字符的河。

C程序針對文件、畫面、鍵盤等的數據輸?輸出操作都是通過流操作的。

?般情況下,我們要想向流里寫數據,或者從流中讀取數據,都是要打開流,然后操作。

標準流:

那為什么我們從鍵盤輸入數據,向屏幕上輸出數據,并沒有打開流呢?

那是因為C語言程序在啟動的時候,默認打開了3個流:

? stdin - 標準輸?流,在?多數的環境中從鍵盤輸?,scanf函數就是從標準輸?流中讀取數據。
? stdout - 標準輸出流,?多數的環境中輸出?顯?器界?,printf函數就是將信息輸出到標準輸出
流中。

? stderr - 標準錯誤流,?多數環境中輸出到顯?器界?。

這是默認打開了這三個流,我們使用scanf、printf等函數就可以直接進行輸入輸出操作的。

stdin、stdout、stderr 三個流的類型是: FILE * ,通常稱為文件指針。

C語言中,就是通過 FILE* 的文件指針來維護流的各種操作的。

C語言提供的一些有關文件操作的接口函數:

在這里插入圖片描述

scanf:從標準輸入流上讀取格式化的數據
fscanf:從指定的輸入流上讀取格式化的數據
sscanf:在字符串中讀取格式化的數據

printf:把數據以格式化的形式打印在標準輸出流上
fprintf:把數據以格式化的形式打印在指定的輸出流上
sprintf:把格式化的數據轉化成字符串

2. 文件

2.1 文件基礎知識

共識原理:

1. 文件 == 內容+屬性

2. 文件分為打開的文件和沒打開的文件

3. 打開的文件----->誰打開的?自然是進程。(本質是研究進程和文件的關系)

4. 沒打開的文件----->在哪里放著呢?在磁盤上放著。我們最關心什么問題呢?沒有被打開的文件非常多。文件如何被分門別類的放置好----->我們要快速的進行增刪查改(快速找到文件)

問題一:文件是如何存儲的呢?

1. 文件被打開必須先被加載到內存里
2. 進程:打開的文件=1:n
基于上面兩點,操作系統內部一定存在大量的被打開的文件!

問題二:那么OS要不要管理這些被打開的文件呢?怎么管理呢???

一定是先描述,再組織!!!-----在內核中,一個被打開的文件都必須有自己的文件打開對象,該對象包含了文件的很多屬性struct XXX(文件屬性)

3. 被打開的文件

首先,確認我們的研究對象是被打開的文件

3.1 以C語言為主,先回憶一下C文件接口

問題一:當前路徑是什么?

當前路徑,就是當前進程的當前路徑cwd(current work direction)

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main(){printf("pid:%d\n",getpid());int fd=open("loggggg.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return -1;}close(fd);sleep(1000);return 0;
}

當我們執行完后,發現我們在當前路徑下,創建了loggggg.txt文件。
在這里插入圖片描述
在這里插入圖片描述

int main()
{printf("pid:%d\n",getpid());chdir("/home/zby/");int fd=open("loggggg.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return -1;}close(fd);sleep(1000);return 0;
}

問題二:如果我更改了當前進程的cwd,是不是就可以把文件新建到其他目錄?

事實確實是如此的!!!

當我調用系統接口,改變當前進程的路徑的時候,再去創建文件,發現創建文件的路徑也隨之改變
在這里插入圖片描述
在這里插入圖片描述

C程序啟動的時候會默認打開三個標準輸入輸出文件
實際上,默認打開這三個標準輸入輸出流不是c語言的特性,是操作系統的特性,進程會默認打開鍵盤,顯示器,顯示器!!!

在這里插入圖片描述

3.2 過渡到系統,認識文件系統調用

文件其實是在磁盤上,磁盤是外部設備,訪問磁盤文件其實就是在訪問硬件!

幾乎所有的庫,只要是訪問硬件設備,必定要封裝系統調用!(printf/fprintf/fscanf/fwrite/fread/fgets/gets/…----庫函數系統調用接口)

open( )函數

在這里插入圖片描述

#define ONE_FLAG 000000001<<0
#define TWO_FLAG 000000001<<1
#define THREE_FLAG 000000001<<2
#define FOUR_FLAG 000000001<<3void flag(int flag)
{if(flag&ONE_FLAG){printf("ONE_FLAG ");}if(flag&TWO_FLAG){printf("TWO_FLAG ");}if(flag&THREE_FLAG){printf("THREE_FLAG ");}if(flag&FOUR_FLAG){printf("FOUR_FLAG ");}printf("\n");
}int main()
{flag(ONE_FLAG);flag(ONE_FLAG|TWO_FLAG);flag(ONE_FLAG|TWO_FLAG|THREE_FLAG);flag(ONE_FLAG|TWO_FLAG|THREE_FLAG|FOUR_FLAG);return 0;
}

上面的代碼演示結果如下:

在這里插入圖片描述

這里強調一下位圖的使用,open的第二個參數也是如此。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

這里只展示了常用的幾個宏。

3.3 訪問文件的本質

文件描述符:

文件描述符0 1 2分別表述標準輸入(stdin)、標準輸出(stdout)、標準錯誤(stderr)。
在OS接口層面,只認fd ,即文件描述符。

FILE * fopen( )中的FILE是C語言提供的一個結構體,既然操作系統只認文件描述符,那么該結構體中一定封裝了文件描述符fd。
例如: stdin -> _ fileno(stdin的fd)

close:將該文件描述符所對應的數組下標所指向的對象置空,并且引用計數減一。(一個文件是可以被多個用戶使用的,如:stdout和stderr都是指向顯示器文件。)

在這里插入圖片描述

上面的代碼是用戶層,下面的組織形式是OS層。

當我們訪問一個文件時,系統是通過該進程的task_struct結構體內的file_struct * file的結構體指針指向的文件描述符表,用該下標fd訪問對應文件的PCB結構體,然后對磁盤將內容存放到文件緩沖區內,當我們要訪問時,就將文件緩存區的文件內容拿出來用!!!

其中,read的本質是拷貝文件緩沖區的內容。

fd文件描述符的本質也是文件指針數組的下標

對文件內容,做任何操作,都必須把文件先加載(磁盤------>內存的拷貝)到內核對應的文件緩沖區內!!!

3.4 重定向&&緩沖區

文件描述符的的分配原則:從下標0開始,最小的,沒有被使用的數組位置作為最新的fd文件描述符給用戶

重定向:更改文件描述符的指針指向----->(數組下標不變)
dup2:進行重定向的系統調用
重定向:打開文件的方式+dup2

進程歷史打開的文件與進行各種重定向關系都和未來進行程序替換無關!!!
程序替換不影響文件訪問

問題一:問題一:stdout和stderr都是指向顯示屏,有什么區別,為什么有了“1”,還要有“2”???

讓我們看下面一段代碼:

#include<stdio.h>
int main(){fprintf(stdout,"i am normal\n");fprintf(stdout,"i am normal\n");fprintf(stdout,"i am normal\n");fprintf(stdout,"i am normal\n");fprintf(stdout,"i am normal\n");fprintf(stderr,"i am error\n");fprintf(stderr,"i am error\n");fprintf(stderr,"i am error\n");fprintf(stderr,"i am error\n");fprintf(stderr,"i am error\n");return 0;
}

演示結果如下:
在這里插入圖片描述

此時我們沒看出什么,但當我們將這些內容都輸入到一個文件中就會發生變化
在這里插入圖片描述

這是為什么呢?讓我們接著看!!!
當運行該段代碼的時候在這里插入圖片描述

發現兩個分離了在這里插入圖片描述

當我們直接將結果輸入到log.txt文件當中時,默認是將文件描述符1所指向的文件內容傳到log.txt中,所以打印到stderr文件中的內容不會打印到log.txt中去,而為什么stderr和stdout都指向顯示器,是因為,當程序運行后的顯示中可能會有錯誤信息,而當打印的信息很繁雜的時候,就需要將這些錯誤信息統一起來!!!所以,結論:是為了將錯誤信息單獨拉出來。

問題二:如何理解“一切皆文件”?

在這里插入圖片描述

當我們的使用系統調用接口read時,傳一個文件描述符fd,操作系統就會通過該進程teak_struct內的files指針找到一個文件描述符表,找到對應的文件的PCB結構,調用里面的f_ops指針,指向operationfunc的結果體,然后調用里面的函數指針int(&readp)(),該函數指針指向對應的硬件設備,不同的硬件設備提供不同的read和write接口,但在operationfunc里面都是統一的接口,從而調用對應的read接口!!!
(用統一的文件接口來訪問不同的硬件設備 == 一切皆文件)

其中的各種struct file就是虛擬文件系統(VFS),所以不同的硬件對應的讀寫方式肯定是不一樣的,但是它們都有自己的 read 和 write 方法。也就是說,這里的硬件可以統一看作成一種特殊的文件。比如這里設計一種結構:struct file,它包括文件的屬性、文件的操作或方法等,Linux 說一切皆文件,Linux 操作系統就必須要能夠保證這點。在 C 語言中,怎么讓一個結構體既有屬性又有方法呢?函數指針。此時每一個硬件都對應這樣一個結構,硬件一旦數量很多,操作系統就需要對它們進行管理 —— 先描述,再組織。所謂的描述就是 struct file;而組織就是要把每一個硬件對應的結構體關聯起來,并用 file header 指向。所以在操作系統的角度,它所看到的就是一切皆文件,也就是說所有硬件的差異經過描述就變成了同一種東西,只不過當具體訪問某種設備時,使用函數指針執行不同的方法達到了不同的行為。現在就能理解為什么可以把鍵盤、顯示器這些設備當作文件,因為本質不同,設備的讀寫方法是有差異的,但我們可以通過函數指針讓不同的硬件包括普通文件在操作系統看來是同樣的方法、同樣的文件。所以,一切皆文件。

總結:

本篇文章從C語言入手,從C語言的文件接口出發,逐漸過渡到系統對于文件的調用,本文的研究對象是已經被打開的文件,我們用先描述,再組織6個字,創建文件結構體對文件進行管理,然后通過幾個細致的例子和對問題的講解,說出我對重定向和緩沖區的理解!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/74182.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/74182.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/74182.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025年十大AI工具對比

2025年十大AI工具對比 以下是2025年各大AI工具的詳細對比&#xff0c;涵蓋性能、功能、用戶評價等方面&#xff0c;并以表格形式呈現。數據來源于多個權威來源&#xff0c;確保信息全面且準確。 對比表格 排名AI工具名稱主要功能性能特點用戶評價適用場景1DeepSeek多模態AI、…

JDK 24 發布,新特性解讀!

一、版本演進與技術格局新動向 北京時間3月20日&#xff0c;Oracle正式發布Java SE 24。作為繼Java 21之后的第三個非LTS版本&#xff0c;其技術革新力度遠超預期——共集成24項JEP提案&#xff0c;相當于Java 22&#xff08;12項&#xff09;與Java 23&#xff08;12項&#…

批量圖片壓縮工具,高效減小文件大小并保持質量

在處理大量圖片時&#xff0c;如何高效壓縮文件大小并保持畫質是個常見難題。今天為大家推薦一款專業工具——JPGC&#xff0c;它專為圖片批量處理設計&#xff0c;能快速壓縮JPG/JPEG格式圖片&#xff0c;在減小文件體積的同時盡可能保留畫質&#xff0c;尤其適合處理數碼相機…

【002安卓開發方案調研】之Kotlin+Jetpack開發方案

基于2025年國內移動開發領域的現狀&#xff0c;結合Jetpack Compose的技術特性和生態發展&#xff0c;以下是對KotlinJetpack Compose開發安卓應用的綜合分析&#xff1a; 一、技術與生態成熟度評估 1. 技術成熟度 聲明式UI與開發效率 Jetpack Compose采用聲明式編程模型&…

軟考中級-軟件設計師 準備

軟考中級-軟件設計師 準備 一、軟考相關1.1、考試時間1.2、考試時長1.3、題型和分值&#xff1a; 二、軟考備考2.1、相關書籍2.2、推薦課程&#xff1a;B站up主zst_20012.3、學習路線 一、軟考相關 1.1、考試時間 一年有兩次軟考&#xff0c;一般是五月末和十一月的中旬 以下…

【數據挖掘】Python基礎環境安裝配置

【數據挖掘】Python基礎環境安裝配置 一、摘要二、安裝Python3.13.2三、安裝Jupyter Notebook四、安裝Numpy和Pandas以及matplotlib五、安裝scikit-learn庫和seaborn庫 一、摘要 本文主要介紹如何在Windows上安裝Python3.13.2&#xff0c;然后基于該Python版本安裝Jupyter not…

給語言模型增加知識邏輯校驗智能,識別網絡中的信息投毒行為模式

目前階段&#xff0c;現在的LLM缺少一個形式邏輯校驗模型。 網絡系統上不斷增長的信息相當部分不再純粹是人類生成&#xff0c;而是也由各種模型生成輸出&#xff0c;模型后續從網絡系統上取得信息&#xff0c;AI生態系統陷入了信息熵增循環&#xff0c;AI模型生態系統的計算輸…

OpenLayers集成天地圖服務開發指南

以下是一份面向GIS初學者的OpenLayers開發詳細教程&#xff0c;深度解析代碼&#xff1a; 一、開發環境搭建 1.1 OpenLayers庫引入 <!-- 使用CDN引入最新版OpenLayers --> <link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/ollatest/ol.c…

【免費】2000-2019年各省地方財政房產稅數據

2000-2019年各省地方財政房產稅數據 1、時間&#xff1a;2000-2019年 2、來源&#xff1a;國家統計局、統計年鑒 3、指標&#xff1a;行政區劃代碼、地區、年份、地方財政房產稅 4、范圍&#xff1a;31省 5、指標說明&#xff1a;房產稅是對個人和單位擁有的房產征收的一種…

在Ubuntu 22.04 中安裝Docker的詳細指南

在Ubuntu 22.04 中安裝Docker的詳細指南 一、引言 Docker是一個開源的應用容器引擎&#xff0c;它可以讓開發者將應用程序及其依賴項打包到一個可移植的容器中&#xff0c;然后發布到任何流行的Linux機器上&#xff0c;也可以實現虛擬化。在Ubuntu 22.04上安裝Docker能為開發、…

macOS 使用 iconv 轉化文件編碼

文章目錄 使用方式支持的編碼類型iconv 更多用法 使用方式 iconv -f GB2312 -t UTF-8 分治算法.txt > 分治算法2.txt 支持的編碼類型 可以使用 下面命令 查看編碼類型 iconv -lPS : ISO-8859 有很多種分支&#xff0c;iconv 支持 ISO-8859-1、ISO-8859-10&#xff0c;但…

操作系統核心問題解析(目的/定位、管理思想:先描述,再組織、 庫函數與系統調用的關系)

1. 目的/定位 核心作用&#xff1a;操作系統是計算機系統的資源管理者和用戶/應用程序的服務提供者。 資源管理&#xff1a;統一管理CPU、內存、磁盤、外設等硬件資源&#xff0c;避免沖突、提高利用率&#xff08;如多任務調度、虛擬內存&#xff09;。 服務接口&#xff1a…

使用Python將視頻轉化為gif

使用Python將視頻轉化為gif 一、前言二、準備三、測試 一、前言 最近想把喜歡的視頻片段作成gif&#xff0c;就試著用Python做了下&#xff0c;感覺效果還行&#xff0c;這里做個記錄。 二、準備 先下載安裝對應的庫&#xff0c;命令如下&#xff1a; pip install moviepy …

Python模塊化設計 ——函數調用

1.以下代碼的輸出結果是()。 def young(age): if 25 <=age<=30: print(“作為一個老師,你很年輕”) elif age <25: print(“作為一個老師,你太年輕了”) elif age>=60: print(“作為一個老師,你可以退休了”) else: print(“作為一個老師,你很有愛心”) young(42) …

在 Linux下使用 Python 3.11 和 FastAPI 搭建帶免費證書的 HTTPS 服務器

在當今數字化時代&#xff0c;保障網站數據傳輸的安全性至關重要。HTTPS 協議通過使用 SSL/TLS 加密技術&#xff0c;能夠有效防止數據在傳輸過程中被竊取或篡改。本教程將詳細介紹如何在 Ubuntu 22.04 系統上&#xff0c;使用 Python 3.11 和 FastAPI 框架搭建一個帶有免費 SS…

MySQL 事務(Transaction)詳解

MySQL 事務&#xff08;Transaction&#xff09;詳解 1. 什么是事務&#xff1f; 事務&#xff08;Transaction&#xff09;是一組要么全部執行&#xff0c;要么全部回滾的 SQL 語句&#xff0c;用于保證數據一致性。事務一般用于銀行轉賬、訂單支付等操作&#xff0c;確保多個…

SPI 機制與 Spring Boot AutoConfiguration 對比解析

一、架構效率革命性提升 1.1 類加載效率躍升 Spring Boot 2.7引入的AutoConfiguration.imports采用清單式配置加載&#xff0c;對比傳統SPI機制&#xff1a; 傳統SPI掃描路徑&#xff1a;META-INF/services/** Spring Boot新方案&#xff1a;META-INF/spring/org.springfram…

【 <二> 丹方改良:Spring 時代的 JavaWeb】之 Spring Boot 中的異常處理:全局異常與自定義異常

<前文回顧> 點擊此處查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、開篇整…

思源配置阿里云 OSS 踩坑記

按照正常的配置IAM&#xff0c;賦予OSS權限&#xff0c;思源筆記還是無法使用&#xff0c;缺少ListBuckets權限。 正常配置權限&#xff0c;又無法覆蓋&#xff0c;因此需要手動配置權限。 {"Version": "1","Statement": [{"Effect":…

Debezium日常分享系列之:Debezium Charts

Debezium日常分享系列之&#xff1a;Debezium Charts 最近&#xff0c;圍繞 Debezium 圖表發生了一些變化&#xff0c;所以我在這里解釋這些變化是什么以及背后的理由。正如您從我們的最新公告中了解到的&#xff0c;我們將發布 Debezium 管理平臺的第一個版本。 Debezium 管理…