Linux環境下句柄的理解
在Linux下,咱們使用ulimit -n 命令能夠看到單個進程可以打開的最大文件句柄數量(socket鏈接也算在裏面)。系統默認值1024。
對於通常的應用來講(象Apache、系統進程)1024徹底足夠使用。可是如何象squid、mysql、java等單進程處理大量請求的應用來講就有點捉襟見肘了。若是單個進程打開的文件句柄數量超過了系統定義的值,就會提到「too many files open」的錯誤提示。java
備註:
Root用戶打開文件數(文件句柄數)受限於:
cat /proc/sys/fs/file-max
1405418
非root用戶打開文件數受限於:
Ulimit -nmysql
如何知道當前進程打開了多少個文件句柄呢?
0、查看當前進程總數
lsof -nNPi | wc -l
-N指打開網絡文件
-n 不將IP轉換爲hostname
-i 用以顯示符合條件的進程狀況 算法
一、查看當前每一個進程打開文件句柄數的最大的幾個進程
lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|head -n 10
1093 4829 #個數 進程pid
1093 26946
1093 26912sql
二、在系統訪問高峯時間以root用戶執行上面的腳本,可能出現的結果以下:數據庫
131 24204
57 24244
57 24231
56 24264
備註:其中第一行是打開的文件句柄數量,第二行是進程號。
系統限定的最大打開文件數
cat /proc/sys/fs/file-max
1405418數組
三、獲得進程號後,咱們能夠經過ps命令獲得進程的詳細內容。
ps -aef|grep 24204
mysql 24204 24162 99 16:15 ? 00:24:25 /usr/sbin/mysqld
哦,原來是mysql進程打開最多文件句柄數量。可是他目前只打開了131個文件句柄數量,遠遠底於系統默認值1024。
備註:
若是是其餘程序,須要看看該程序是哪一個用戶啓動,而後切換到該用戶下,
su - 用戶
Ulimit -n服務器
Root用戶打開文件數不受ulimit -n影響網絡
可是若是系統併發特別大,尤爲是squid服務器,頗有可能會超過1024。這時候就必需要調整系統參數,以適應應用變化。Linux有硬性限制和軟性限制。能夠經過ulimit來設定這兩個參數。併發
四、方法以下,以root用戶運行如下命令:
ulimit -HSn 4096
以上命令中,H指定了硬性大小,S指定了軟性大小,n表示設定單個進程最大的打開文件句柄數量。設定句柄數量後,系統重啓後,又會恢復默認值。若是想永久保存下來,作一下修改
tail -n 5 /etc/security/limits.conf socket
概念理解:
1.句柄就是一個標識符,只要得到對象的句柄,咱們就能夠對對象進行任意的操做。
2.句柄不必定是指針。操做系統用句柄能夠找到一塊內存,這個句柄多是標識符,例如map的key,也多是指針,看操做系統怎麼處理的了。
fd算是在某種程度上替代句柄吧;
Linux 有相應機制,但沒有統一的句柄類型,各類類型的系統資源由各自的類型來標識,由各自的接口操做。
3.在操做系統層面上,文件操做也有相似於FILE的一個概念,在Linux裏,這叫作文件描述符(File Descriptor),而在Windows裏,叫作句柄(Handle)(如下在沒有歧義的時候統稱爲句柄)。用戶經過某個函數打開文件以得到句柄,此後用戶操縱文件皆經過該句柄進行。
設計這麼一個句柄的緣由在於句柄能夠防止用戶隨意讀寫操做系統內核的文件對象。不管是Linux仍是Windows,文件句柄老是和內核的文件對象相關聯的,但如何關聯細節用戶並不可見。內核能夠經過句柄來計算出內核裏文件對象的地址,但此能力並不對用戶開放。
下面舉一個實際的例子,在Linux中,值爲0、一、2的fd分別表明標準輸入、標準輸出和標準錯誤輸出。在程序中打開文件獲得的fd從3開始增加。 fd具體是什麼呢?在內核中,每個進程都有一個私有的「打開文件表」,這個表是一個指針數組,每個元素都指向一個內核的打開文件對象。而fd,就是這 個表的下標。當用戶打開一個文件時,內核會在內部生成一個打開文件對象,並在這個表裏找到一個空項,讓這一項指向生成的打開文件對象,並返回這一項的下標 做爲fd。因爲這個表處於內核,而且用戶沒法訪問到,所以用戶即便擁有fd,也沒法獲得打開文件對象的地址,只可以經過系統提供的函數來操做。
在C語言裏,操縱文件的渠道則是FILE結構,不難想象,C語言中的FILE結構一定和fd有一對一的關係,每一個FILE結構都會記錄本身惟一對應的fd。
句柄在程序設計中,句柄是一種特殊的智能指針 。當一個應用程序 要引用其餘系統(如數據庫、操做系統 )所管理的內存 塊或對象 時,就要使用句柄。句柄與普通指針 的區別在於,指針包含的是引用對象 的內存地址 ,而句柄則是由系統所管理的引用標識,該標識能夠被系統從新定位到一個內存地址 上。這種間接訪問對象 的模式加強了系統對引用對象 的控制。現在,內存 容量的增大和虛擬內存 算法使得更簡單的指針 越發受到青睞,而指向另外一指針的那類句柄受到冷淡。儘管如此,許多操做系統 仍然把指向私有對象 的指針以及進程傳遞給客戶端 的內部數組 下標稱爲句柄。