第3章 文件IO | 001 文件描述符

  1. 概述

在Linux系統中一切皆可以看成是文件,文件又可分為:普通文件、目錄文件、鏈接文件和設備文件。文件描述符(file descriptor)是內核為了高效管理已被打開的文件所創建的索引,其是一個非負整數(通常是小整數),用于指代被打開的文件,所有執行I/O操作的系統調用都通過文件描述符。程序剛剛啟動的時候,0是標準輸入,1是標準輸出,2是標準錯誤。如果此時去打開一個新的文件,它的文件描述符會是3。 POSIX標準要求每次打開文件時(含socket)必須使用當前進程中最小可用的文件描述符號碼,因此,在網絡通信過程中稍不注意就有可能造成串話。 標準文件描述符圖如下:
這里寫圖片描述

文件描述與打開的文件對應模型如下圖:
這里寫圖片描述


  1. 文件描述限制

在編寫文件操作的或者網絡通信的軟件時,初學者一般可能會遇到“Too many open files”的問題。這主要是因為文件描述符是系統的一個重要資源,雖然說系統內存有多少就可以打開多少的文件描述符,但是在實際實現過程中內核是會做相應的處理的,一般最大打開文件數會是系統內存的10%(以KB來計算)(稱之為系統級限制),查看系統級別的最大打開文件數可以使用sysctl -a | grep fs.file-max命令查看。與此同時,內核為了不讓某一個進程消耗掉所有的文件資源,其也會對單個進程最大打開文件數做默認值處理(稱之為用戶級限制),默認值一般是1024,使用ulimit -n命令可以查看。在Web服務器中,通過更改系統默認值文件描述符的最大值來優化服務器是最常見的方式之一。


  1. 文件描述符合打開文件之間的關系

每一個文件描述符會與一個打開文件相對應,同時,不同的文件描述符也會指向同一個文件。相同的文件可以被不同的進程打開也可以在同一個進程中被多次打開。系統為每一個進程維護了一個文件描述符表,該表的值都是從0開始的,所以在不同的進程中你會看到相同的文件描述符,這種情況下相同文件描述符有可能指向同一個文件,也有可能指向不同的文件。具體情況要具體分析,要理解具體其概況如何,需要查看由內核維護的3個數據結構。

** 1. 進程級的文件描述符表 **

** 2. 系統級的打開文件描述符表 **

** 3. 文件系統的i-node表 **

進程級的描述符表的每一條目記錄了單個文件描述符的相關信息。

  1. 控制文件描述符操作的一組標志。(目前,此類標志僅定義了一個,即close-on-exec標志)

  2. 對打開文件句柄的引用

內核對所有打開的文件的文件維護有一個系統級的描述符表格(open file description table)。有時,也稱之為打開文件表(open file table),并將表格中各條目稱為打開文件句柄(open file handle)。一個打開文件句柄存儲了與一個打開文件相關的全部信息,如下所示:

  1. 當前文件偏移量(調用read()和write()時更新,或使用lseek()直接修改)

  2. 打開文件時所使用的狀態標識(即,open()的flags參數)

  3. 文件訪問模式(如調用open()時所設置的只讀模式、只寫模式或讀寫模式)

  4. 與信號驅動相關的設置

  5. 對該文件i-node對象的引用

  6. 文件類型(例如:常規文件、套接字或FIFO)和訪問權限

  7. 一個指針,指向該文件所持有的鎖列表

  8. 文件的各種屬性,包括文件大小以及與不同類型操作相關的時間戳

下圖展示了文件描述符、打開的文件句柄以及i-node之間的關系,圖中,兩個進程擁有諸多打開的文件描述符。
這里寫圖片描述


  1. 文件描述符復制

在進程A中,文件描述符1和文件描述符20都指向同一個打開文件描述體(標號23)。這很可能是通過調用dup()系列函數形成的。

文件描述符復制,在某些場景下非常有用,比如:標準輸入/輸出重定向。在shell下,完成這個操作非常簡單,大部分人都會,但是極少人思考過背后的原理。

大概描述一下需要的幾個步驟,以標準輸出(文件描述符為1)重定向為例:

打開目標文件,返回文件描述符n;
關閉文件描述符1;
調用dup將文件描述符n復制到1;
關閉文件描述符n;


  1. 子進程繼承文件描述符

進程A的文件描述符2和進程B的文件描述符2都指向同一個打開文件描述體(標號73)。這種情形很可能發生在調用fork()派生子進程之后,比如A調用fork()派生出B。這時,B作為子進程,從父進程A繼承了文件描述符表,其中包括圖中標明的文件描述符2。這就是子進程繼承父進程打開的文件這句話的由來。

當然了,進程A通過Unix套接字將一個文件描述符傳遞給B也會出現類似的情形,但一般文件描述符數值是不一樣的。同時為2要非常湊巧才發生。


  1. 總結

  1. 由于進程級文件描述符表的存在,不同的進程中會出現相同的文件描述符,它們可能指向同一個文件,也可能指向不同的文件

  2. 兩個不同的文件描述符,若指向同一個打開文件句柄,將共享同一文件偏移量。因此,如果通過其中一個文件描述符來修改文件偏移量(由調用read()、write()或lseek()所致),那么從另一個描述符中也會觀察到變化,無論這兩個文件描述符是否屬于不同進程,還是同一個進程,情況都是如此。

  3. 要獲取和修改打開的文件標志(例如:O_APPEND、O_NONBLOCK和O_ASYNC),可執行fcntl()的F_GETFL和F_SETFL操作,其對作用域的約束與上一條頗為類似。

  4. 文件描述符標志(即,close-on-exec)為進程和文件描述符所私有。對這一標志的修改將不會影響同一進程或不同進程中的其他文件描述符


  1. 參考資料

  1. Linux中的文件描述符與打開文件之間的關系
  2. Linux文件描述符
    ?
    ?
#include"apue.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/times.h>
int main ()
{struct tms time_buf_head , time_buf_end ;long   tck = 0 ;clock_t time_head , time_end ;tck = sysconf (_SC_CLK_TCK);   time_head = times (& time_buf_head);  printf ("head_time is : %f \n ", time_head / (double )tck); //system ("./time_test.exe");system ("sleep 2" );   time_end = times ( & time_buf_end );  printf ("end_time is : %f \n ", time_end / (double )tck );printf ("user time is : %f \n ", ((time_buf_end . tms_utime - time_buf_head . tms_utime) /( double )tck));  printf ("systime time is : %f \n ", ((time_buf_end . tms_stime - time_buf_head . tms_stime) / (double )tck));printf ("child user time is : %f \n ", ((time_buf_end . tms_cutime - time_buf_head . tms_cutime) / (double )tck));printf ("child sys time is : %f \n ", ((time_buf_end . tms_cstime - time_buf_head . tms_cstime) / (double )tck));return 0;
}

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

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

相關文章

java提取圖片中的文字,深入分析

第一個暴擊&#xff1a;Spring 上一份Spring的手繪思維腦圖&#xff08;就像是個知識大綱總結&#xff09;&#xff0c;預覽一下Spring的知識點&#xff0c;心里有個譜。不過這邊我是采用的截圖方式&#xff0c;為了把全部的內容都截取出來&#xff0c;所以整個就比較小&#…

Leetcode | 513. Find Bottom Left Tree Value

題目&#xff1a;翻轉二叉樹 方法①&#xff1a;深度優先遍歷(鏈接) /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ cla…

java基礎入門傳智播客答案,GitHub已標星16k

選擇 在現在這個浮躁而又拜金的社會&#xff0c;我相信很多人做技術并非出于熱愛&#xff0c;只是被互聯網的高薪吸引&#xff0c;畢竟技術崗位非常枯燥&#xff0c;不僅要面對奇奇怪怪的需求&#xff0c;還要不停的充實自己避免被淘汰。所以想要吃好技術這碗飯并不容易。 我…

563. 二叉樹的坡度

給定一個二叉樹&#xff0c;計算整個樹的坡度。 一個樹的節點的坡度定義即為&#xff0c;該節點左子樹的結點之和和右子樹結點之和的差的絕對值。空結點的的坡度是0。 整個樹的坡度就是其所有節點的坡度之和。 示例: 輸入: 1/ \2 3 輸出: 1 解釋: 結點的坡度 2 : 0 …

java基礎入門第二版二手,細節爆炸

一面&#xff1a;70分鐘 突擊電話面試 正思考著項目功能模塊&#xff0c;阿里面試官打來了電話&#xff0c;開始了阿里一面。 阿里面試官自我介紹&#xff0c;介紹了5分鐘左右&#xff0c;部門的情況&#xff0c;主要的業務 提問開始 會哪些操作系統 Linux會一點說一下操作指…

進程通訊:管道

管道&#xff0c;通常指無名管道&#xff0c;是 UNIX 系統IPC最古老的形式。 1、特點&#xff1a; 它是半雙工的&#xff08;即數據只能在一個方向上流動&#xff09;&#xff0c;具有固定的讀端和寫端。它只能用于具有親緣關系的進程之間的通信&#xff08;也是父子進程或者兄…

java基礎入門答案譚曉芳,原理+實戰講解

One&#xff1a;JVM實踐思維圖&#xff08;完整版&#xff09; Two&#xff1a; 走近Java 概述 Java技術體系Java發展史Java虛擬機家族&#xff1a;&#xff08;Sun Classic/Exact VM、HotSpot VM、Mobile/Embedded VM、BEA JRockit/IBM J9 VM、BEA Liquid VM/Azul VM、Apache…

Leetcode 102. 二叉樹的層次遍歷

給定一個二叉樹&#xff0c;返回其按層次遍歷的節點值。 &#xff08;即逐層地&#xff0c;從左到右訪問所有節點&#xff09;。 例如: 給定二叉樹: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其層次遍歷結果&#xff1a; [ [3], [9,20], [15,7…

java基礎常問面試題,面試必問

一、首先本職工作一定要做好做精 本人之前在干兼職的時候&#xff0c;也忽視過本職工作&#xff0c;從而導致自己落后平均技術水平&#xff0c;雖然之后迎頭趕上&#xff0c;但這不能不算是個遺憾。前在接一些活的時候就感覺技術的重要性了&#xff0c;如果當年我技術再好些&a…

Leetcode | 107. Binary Tree Level Order Traversal II

題目&#xff1a;二叉樹的層次遍歷 II 1. 代碼①&#xff1a;深度優先搜索(鏈接&#xff09; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NUL…

java基礎教程哪個好,吐血整理

RabbitMQ&#xff1a; 優點&#xff1a;輕量&#xff0c;迅捷&#xff0c;容易部署和使用&#xff0c;擁有靈活的路由配置 缺點&#xff1a;性能和吞吐量較差&#xff0c;不易進行二次開發 RocketMQ&#xff1a; 優點&#xff1a;性能好&#xff0c;穩定可靠&#xff0c;有活…

java基礎教程哪個好,面試必會

如何才可以進大廠&#xff1f; 答案其實也很簡單&#xff0c;能力學歷。不知道大家有沒有發現&#xff0c;大廠的一些部門對于學歷要求已經放低了&#xff0c;阿里的一些部門同樣也招大專學歷的程序員&#xff0c;當然肯定也是因為他的能力足夠出色。 對于準備秋招的你來說&a…

java基礎教程第三版耿祥義,后臺開發JAVA崗

Java虛擬機內存模型 Java虛擬機內存模型中定義的訪問操作與物理計算機處理的基本一致&#xff01; Java中通過多線程機制使得多個任務同時執行處理&#xff0c;所有的線程共享JVM內存區域main memory&#xff0c;而每個線程又單獨的有自己的工作內存&#xff0c;當線程與內存區…

501. 二叉搜索樹中的眾數

給定一個有相同值的二叉搜索樹&#xff08;BST&#xff09;&#xff0c;找出 BST 中的所有眾數&#xff08;出現頻率最高的元素&#xff09;。 假定 BST 有如下定義&#xff1a; 結點左子樹中所含結點的值小于等于當前結點的值結點右子樹中所含結點的值大于等于當前結點的值左…

java基礎案例教程黑馬程序員案例答案,真香

掌握核心知識 1、90%幾率面試被問&#xff0c;吃透原理&#xff0c;面試不慌&#xff08;Spring原理&#xff09; 2、大廠必問Redis&#xff0c;趕緊碼起來&#xff08;Redis核心原理&#xff09; 3、MySQL從入門到實戰都在這篇&#xff0c;面試笑談優化 當然核心知識不止這三…

java基礎的三個框架,進階學習資料!

阿里巴巴一面 自我介紹這個就不說了&#xff0c;開頭必問的說一下StringBuilder 和 StringBufferSpring bean加載&#xff0c;實例化的過程Spring AOP源碼看過嗎java內存模型說一下如果給你一個map&#xff0c;里面有很多很多對象&#xff0c;那么這個map存放在哪了解GC算法嗎…

實驗3 | 由遍歷序列構造二叉樹

二叉樹構造定理&#xff1a; 定理7.1&#xff1a;任何n&#xff08;n>0&#xff09;個不同結點的二又樹&#xff0c;都可由它的中序序列和先序序列唯一地確定。 定理7.2&#xff1a;任何n&#xff08;n&#xff1e;0&#xff09;個不同結點的二又樹&#xff0c;都可由它的…

萬字總結!java讓字符串反轉

Java基礎 JDK 和 JRE 有什么區別&#xff1f; 和 equals 的區別是什么&#xff1f;兩個對象的 hashCode()相同&#xff0c;則 equals()也一定為 true&#xff0c;對嗎&#xff1f;final 在 java 中有什么作用&#xff1f;java 中的 Math.round(-1.5) 等于多少&#xff1f;Stri…

String | 344. Reverse String

題目&#xff1a;反轉字符串 方法1&#xff1a; class Solution { public:string reverseString(string s) {int m (s.size() -1) / 2;for(int i 0; i < m; i){char c s[i];s[i] s[s.size() -1 - i];s[s.size() -1 - i] c;}return s; } }; 方法2&#xff1a;…

萬字總結!springcloud分布式限流

正文 作為后端開發&#xff0c;日常操作數據庫最常用的是寫操作和讀操作。讀操作我們下邊會講&#xff0c;這個分類里我們主要來看看寫操作時為什么會導致 SQL 變慢。 刷臟頁 臟頁的定義是這樣的&#xff1a;內存數據頁和磁盤數據頁不一致時&#xff0c;那么稱這個內存數據頁…