檔案控制程式碼、檔案描述符與程式和多執行緒的那些事

chenfeng發表於2016-01-13

檔案控制程式碼(摘抄的一些概念,幫助理解):

控制程式碼是WINDOWS用來標識被應用程式所建立或使用的物件的唯一整數,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傳給啟動的執行緒的情況是一樣的。


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

檔案控制程式碼、檔案描述符與程式和多執行緒的那些事


這下清楚不少,但是昨天關於Python中myFile = open('fileLoc','r')的情況還不能照搬理解,因為Python的封裝,open後返回的是檔案物件,至於檔案物件的本質,還需要進一步研究。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15498/viewspace-1976009/,如需轉載,請註明出處,否則將追究法律責任。

相關文章