文件句柄、文件描述符與進程和多線程的那些事

傳送門:PYTHON多線程處理文件node

文件句柄(摘抄的一些概念,幫助理解):linux

句柄是WONDOWS用來標識被應用程序所創建或使用的對象的惟一整數,WINDOWS使用各類各樣的句柄標識諸如應用程序實例,窗口,控制,位圖,GDI對象等等。WINDOWS句柄有點象C語言中的文件句柄。安全

若是想更透徹一點地認識句柄,我能夠告訴你們,句柄是一種指向指針的指針。咱們知道,所謂指針是一種內存地址。應用程序啓動後,組成這個程序的各對象是住留在內存的。若是簡單地理解,彷佛咱們只要獲知這個內存的首地址,那麼就能夠隨時用這個地址訪問對象。可是,若是您真的這樣認爲,那麼您就大錯特錯了。咱們知道,Windows是一個以虛擬內存爲基礎的操做系統。在這種系統環境下,Windows內存管理器常常在內存中來回移動對象,依此來知足各類應用程序的內存須要。對象被移動意味着它的地址變化了。若是地址老是如此變化,咱們該到哪裏去找該對象呢?多線程

爲了解決這個問題,Windows操做系統爲各應用程序騰出一些內存儲地址,用來專門登記各應用對象在內存中的地址變化,而這個地址(存儲單元的位置)自己是不變的。Windows內存管理器在移動對象在內存中的位置後,把對象新的地址告知這個句柄地址來保存。這樣咱們只需記住這個句柄地址就能夠間接地知道對象具體在內存中的哪一個位置。這個地址是在對象裝載(Load)時由系統分配給的,當系統卸載時(Unload)又釋放給系統。
函數

句柄是操做系統在生成對象時分配給對象的惟一標識。 經過句柄能夠獲取操做系統提供的服務。句柄不一樣於指針,若是你獲得一個對象的指針,那你就能夠在此對象上隨心所欲了。因而系統不給你指針,而給用戶一個加了限制的,用於跟蹤對象的指針的標識——句柄。系統使用句柄向外提供服務就相對安全了。
spa

總結:操作系統

一、不管是文件句柄(Windows中概念),仍是文件描述符(linux中概念),其最終目的都是用來定位打開的文件在內存中的位置,只是它們映射的方式不同。.net

二、文件句柄定位到的是文件對象,而非文件。而文件對象是對這個文件的一些狀態、屬性的封裝,例如讀取到的文件位置等。線程

三、關於在進程、線程下,這個時候用文件句柄很差闡述,能夠把文件句柄理解成下圖中的文件描述符,以下圖:指針


每一個進程有各自獨立的文件描述符,打開不一樣的文件也都會有不一樣的打開文件表,而且指向不一樣的v-node表項。

此時沒有共享文件,而且每一個描述符對應一個不一樣的文件。

不一樣的進程屢次open一個文件,則會產生不一樣的打開文件表項,但最終指向的是同一個文件的v-node標項。

此時,多個描述符也能夠經過不一樣的文件表表項來引用同一個文件。例如,若是以同一個filename調用open函數兩次,就會發生這種狀況。關鍵思想是:每一個描述符都有它本身的文件位置,因此對不一樣描述符的讀操做能夠從文件的不一樣位置獲取數據。

若是在多線程中打開同一個文件(不一樣於在主線程中打開一個文件,並將fd=open(file)的fd參數傳給線程),則每一個線程會有各自的文件描述符,按照上一條關鍵思想,這每一個線程也會有保存本身的讀取位置,互不影響。

深刻理解計算機系統裏還有這麼段話:由於每一個進程都有本身HANDLE的存儲空間);若是是同一個進程的線程,由於同基於I/O多路複用的流同樣,多個線程運行在單一進程的上下文中,共享這個進程虛擬地址空間的整個內容,包括它的代碼、數據、堆、共享庫和打開的文件(句柄)。這個應該也是指的進程已經打開文件,則線程共享打開的文件。


若是在調用fork以前父進程已經打開文件,則fork後子進程有一個父進程描述符表的副本。父子進程共享相同的打開文件集合,所以共享相同的文件位置。

這個狀況跟主線程已經open文件,並把fd傳給啓動的線程的狀況是同樣的。


另外關注上述圖片表的解釋以下:



這下清楚很多,可是昨天關於Python中myFile = open('fileLoc','r')的狀況還不能照搬理解,由於Python的封裝,open後返回的是文件對象,至於文件對象的本質,還須要進一步研究。


感謝秦師兄、自習室二期小夥伴們的熱烈討論。

上述內容若是與事實有出入,請必定提出異議。


相關文章
相關標籤/搜索