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


本文出至:http://my.oschina.net/iuranus/blog/330397?fromerr=x1SVuj0Z

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

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

如果想更透徹一點地認識句柄,我可以告訴大家,句柄是一種指向指針的指針。我們知道,所謂指針是一種內存地址。應用程序啟動后,組成這個程序的各對象是住留在內存的。如果簡單地理解,似乎我們只要獲知這個內存的首地址,那么就可以隨時用這個地址訪問對象。但是,如果您真的這樣認為,那么您就大錯特錯了。我們知道,Windows是一個以虛擬內存為基礎的操作系統。在這種系統環境下,Windows內存管理器經常在內存中來回移動對象,依此來滿足各種應用程序的內存需要。對象被移動意味着它的地址變化了。如果地址總是如此變化,我們該到哪里去找該對象呢?

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

句柄是操作系統在生成對象時分配給對象的唯一標識。 通過句柄可以獲取操作系統提供的服務。句柄不同於指針,如果你得到一個對象的指針,那你就可以在此對象上為所欲為了。於是系統不給你指針,而給用戶一個加了限制的,用於跟蹤對象的指針的標識——句柄。系統使用句柄向外提供服務就相對安全了。

總結:

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

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

3、關於在進程、線程下,這個時候用文件句柄不好闡述,可以把文件句柄理解成下圖中的文件描述符,如下圖:

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

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

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

此時,多個描述符也可以通過不同的文件表表項來引用同一個文件。例如,如果以同一個filename調用open函數兩次,就會發生這種情況。關鍵思想是:每個描述符都有它自己的文件位置,所以對不同描述符的讀操作可以從文件的不同位置獲取數據。

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

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

 

如果在調用fork之前父進程已經打開文件,則fork后子進程有一個父進程描述符表的副本。父子進程共享相同的打開文件集合,因此共享相同的文件位置。

這個情況跟主線程已經open文件,並把fd傳給啟動的線程的情況是一樣的。

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM