ulimit用於shell啓動進程所佔用的資源,能夠用來設置系統的限制html
語法格式node
ulimit [-acdfHlmnpsStvw] [size]linux
在/etc/security/limits.conf
文件中定義
限制。shell
命令參數 | 描述 | 例子 |
---|---|---|
-H | 設置硬資源限制,一旦設置不能增長。 | ulimit – Hs 64;限制硬資源,線程棧大小爲 64K。 |
-S | 設置軟資源限制,設置後能夠增長,可是不能超過硬資源設置。 | ulimit – Sn 32;限制軟資源,32 個文件描述符。 |
-a | 顯示當前全部的 limit 信息 | ulimit – a;顯示當前全部的 limit 信息 |
-c | 最大的 core 文件的大小, 以 blocks 爲單位 | ulimit – c unlimited; 對生成的 core 文件的大小不進行限制 |
-d | 進程最大的數據段的大小,以 Kbytes 爲單位 | ulimit -d unlimited;對進程的數據段大小不進行限制 |
-f | 進程能夠建立文件的最大值,以 blocks 爲單位 | ulimit – f 2048;限制進程能夠建立的最大文件大小爲 2048 blocks |
-l | 最大可加鎖內存大小,以 Kbytes 爲單位 | ulimit – l 32;限制最大可加鎖內存大小爲 32 Kbytes |
-m | 最大內存大小,以 Kbytes 爲單位 | ulimit – m unlimited;對最大內存不進行限制 |
-n | 能夠打開最大文件描述符的數量 | ulimit – n 128;限制最大可使用 128 個文件描述符 |
-p | 管道緩衝區的大小,以 Kbytes 爲單位 | ulimit – p 512;限制管道緩衝區的大小爲 512 Kbytes |
-s | 線程棧大小,以 Kbytes 爲單位 | ulimit – s 512;限制線程棧的大小爲 512 Kbytes |
-t | 最大的 CPU 佔用時間,以秒爲單位 | ulimit – t unlimited;對最大的 CPU 佔用時間不進行限制 |
-u | 用戶最大可用的進程數 | ulimit – u 64;限制用戶最多可使用 64 個進程 |
-v | 進程最大可用的虛擬內存,以 Kbytes 爲單位 | ulimit – v 200000;限制最大可用的虛擬內存爲 200000 Kbytes |
咱們可使用ulimit -a查看咱們系統的全部限制編程
固然咱們都知道linux大部分的命令設置都是臨時生效,並且ulimit命令只對當前終端生效小程序
若是須要永久生效的話,咱們有兩種方法,windows
一種是將命令寫至profile和bashrc中,至關於在登錄時自動動態修改限制緩存
還有一種就是在/etc/security/limits.conf中添加記錄(需重啓生效,而且在/etc/pam.d/中的seesion有使用到limit模塊)。安全
在/etc/security/limits.conf修改限制的格式以下bash
domino type item value
參數 | 描述 |
---|---|
domino | 是以符號@開頭的用戶名或組名,*表示全部用戶 |
type | 設置爲hard or soft |
item | 指定想限制的資源。如cpu,core nproc or maxlogins |
value | 是相應的 |
每一個進程的局部段描述表LDT都做爲一個獨立的段而存在,在全局段描述表GDT中要有一個表項指向這個段的起始地址,並說明該段的長度以及其餘一些 參數。除上以外,每一個進程還有一個TSS結構(任務狀態段)也是同樣。因此,每一個進程都要在全局段描述表GDT中佔據兩個表項。
段寄存器中用做GDT表下標的位段寬度是13位,因此GDT中能夠有213=8192個描述項。
除一些系統的開銷(例如GDT中的第2項和第3項分別用於內核 的代碼段和數據段,第4項和第5項永遠用於當前進程的代碼段和數據段,第1項永遠是0,等等)之外,尚有8180個表項可供使用,因此理論上系統中最大的 進程數量是8180/2=4090。
因此係統中理論上最大的進程數是4090
linux內核經過進程標識值(process identification value)-PID來標示進程,PID是一個數,類型位pid_t, 實際上就是int類型
爲了與老版本的Unix或者Linux兼容,PID的最大值默認設置位32768(short int 短整型的最大值)。
可使用cat /proc/sys/kernel/pid_max
來查看系統中可建立的進程數實際值
ulimit -u 65535
設置完之後,雖然咱們設置戶建立進程數的硬限制和軟限制都是65535,可是咱們還不能使用建立65535個進程
咱們在Linux還須要設置內核參數kernel.pid_max,這個參數我默認安裝都是32768,
因此即便使用root賬戶,卻不設置這個內核參數,整個系統最多能夠建立的進程數就是32768,因此咱們須要進行以下設置:
sysctl -w kernel.pid_max=65535
linux 系統中單個進程的最大線程數有其最大的限制 PTHREAD_THREADS_MAX
這個限制能夠在/usr/include/bits/local_lim.h
中查看
對 linuxthreads 這個值通常是 1024,對於 nptl 則沒有硬性的限制,僅僅受限於系統的資源
這個系統的資源主要就是線程的 stack 所佔用的內存,用 ulimit -s 能夠查看默認的線程棧大小,通常狀況下,這個值是8M=8192KB
能夠寫一段簡單的代碼驗證最多能夠建立多少個線程
include <stdio.h>
#include <stdlib.h> #include <pthread.h> void func() { } int main(void) { int i = 0; pthread_t thread; while ( 1 ) { if (pthread_create(&thread, NULL, func, NULL) != 0) { return; } i++; printf("i = %d\n", i); } return EXIT_SUCCESS; }
試驗顯示,在咱們的系統(Ubuntu-14.04-LTS-64bit)中linuxthreads 上最多能夠建立 381 個線程,以後就會返回 EAGAIN
而32位系統中,能夠穿件381個線程,這個值和理論徹底相符,由於 32 位 linux 下的進程用戶空間是 3G 的大小,也就是 3072M,用3072M/8M=384,可是實際上代碼段和數據段等還要佔用一些空間,這個值應該向下取整到 383,再減去主線程,獲得 382。
那爲何 linuxthreads 上還要少一個線程呢?這可太對了,由於 linuxthreads 還須要一個管理線程
爲了突破內存的限制,能夠有兩種方法
用ulimit -s 1024
減少默認的棧大小
調用pthread_create
的時候用pthread_attr_getstacksize
設置一個較小的棧大小
要注意的是,即便這樣的也沒法突破1024 個線程的硬限制,除非從新編譯 C 庫
/proc/sys/fs/file-max中指定了系統範圍內全部進程可打開的文件句柄的數量限制(系統級別, kernel-level).
The value in file-max denotes the maximum number of file handles that the Linux kernel will allocate).
當收到」Too many open files in system」這樣的錯誤消息時, 就應該曾加這個值了.
對於2.2的內核, 還須要考慮inode-max, 通常inode-max設置爲file-max的4倍. 對於2.4及之後的內核, 沒有inode-max這個文件了.
可使用cat /proc/sys/fs/file-max來查看當前系統中單進程可打開的文件描述符數目
186405
echo 1000000 > /proc/sys/fs/file-max
fs.file-max = 1000000
內核支持的最大file handle數量,即一個進程最多使用的file handle數
the maximum number of files that can be opened by process。
A process cannot use more than NR_OPEN file descriptors. 一個進程不能使用超過NR_OPEN文件描述符。
ulimit -n
固然默認查看的是軟資源限制值soft limit,若是想要查看系統硬件所能支持的單進程最大打開文件描述符號的數目,可使用ulimit -Hn
經過ulimit -Sn
設置最大打開文件描述符數的soft limit,注意soft limit不能大於hard limit(ulimit -Hn可查看hard limit)
另外ulimit -n默認查看的是soft limit,可是ulimit -n 1800000則是同時設置soft limit和hard limit。
對於非root用戶只能設置比原來小的hard limit。
上面的方法只是臨時性的,註銷從新登陸就失效了,並且不能增大hard limit,只能在hard limit範圍內修改soft limit。
若要使修改永久有效,則須要在/etc/security/limits.conf中進行設置(須要root權限),可添加以下兩行,表示用戶chanon最大打開文件描述符數的soft limit爲1800000,hard limit爲2000000。如下設置須要註銷以後從新登陸才能生效:
chanon soft nofile 102400 chanon hard nofile 409600
設置nofile的hard limit還有一點要注意的就是hard limit不能大於/proc/sys/fs/nr_open,假如hard limit大於nr_open,註銷後沒法正常登陸。
能夠修改nr_open的值:
echo 2000000 > /proc/sys/fs/nr_open
針對用戶打開最大文件數的限制, 在limits.conf對應的nofile,無論是man手冊仍是文件中說明都只是一句話
「maximum number of open files」,
它其實對應是單個進程能打開的最大文件數,一般爲了省事,咱們想取消它的限制
根據man手冊中,「values -1, unlimited or infinity indicating no limit」,-一、unlimited、infinity都是代表不作限制
但是當你實際給nofile設置成這個值,等你重啓就會發現沒法登陸系統了。
因而可知,nofile是有一個上限的,同時用ulimit測試:
ulimit -n unlimited
bash: ulimit: open files: cannot modify limit: 不容許的操做
寫一個簡單的for循環得出:
for V in `seq 100000 10000000`;do ulimit -n $V;[[ $? != 0 ]]&&break;done
再執行ulimit -n ,能夠看到1048576就是nofile的最大值了,但爲何是這個值?
1024∗1024=1048576,固然這並無什麼卵用。
再跟蹤一下咱們就會發現這個值實際上是由內核參數nr_open定義的:
cat /proc/sys/fs/nr_open
到此咱們就要提及nr_open,與file-max了,網上在說到設置最大文件數時偶爾有些帖子也說到要修改file-max,字面上看file-max確實像是對應最大文件數,而在linux內核文檔中它們兩的解釋是:
執行:grep -r MemTotal /proc/meminfo | awk ‘{printf(「%d」,$2/10)}’,能夠看到與file-max是相近的;
file-handles(即文件句柄),而後相比而言在UNIX/LINUX中咱們接觸更可能是file discriptor(FD,即文件描述符),彷佛file-handle在windows中是一個相似file discrptor的東東,可是咱們討論的是linux,再google一下,咱們能夠精確到c語言中這兩個概念的區別,
據他們的討論file-handle應該是一個高層的對象,使用fopen,fread等函數來調用,而FD是底層的一個對象,能夠經過open,read等函數來調用。
到此,咱們應該能夠下一個大體的結論了,file-max是內核可分配的最大文件數,nr_open是單個進程可分配的最大文件數,因此在咱們使用ulimit或limits.conf來設置時,若是要超過默認的1048576值時須要先增大nr_open值(sysctl -w fs.nr_open=100000000或者直接寫入sysctl.conf文件)。固然百萬級別的單進程最大file-handle打開數應該也夠用了吧。。
全部進程打開的文件描述符數不能超過/proc/sys/fs/file-max
單個進程打開的文件描述符數不能超過user limit中nofile的soft limit
nofile的soft limit不能超過其hard limit
nofile的hard limit不能超過/proc/sys/fs/nr_open
以下內容轉載自
在2.4內核的典型系統上(AS3/RH9),線程是用輕量進程實現的,每一個線程要佔用一個進程ID,在服務器程序上,若是遇到高點擊率訪問,會形成進程表溢出,系統爲了維護溢出的進程表,會有間歇的暫停服務現象,而2.6內核就不會發生因爲大量線程的建立和銷燬致使進程表溢出的問題
就是說,線程函數必須調用pthread_exit()結束,不然直到主進程函數退出才釋放,特別是2.6內核環境,線程建立速度飛快,一不當心馬上內存被吃光,這一點反卻是2.4內核環境好,由於2.4內核建立的是進程,並且線程建立速度比2.6內核慢幾個數量級。特別提醒,在64位CPU,2.6內核建立線程的速度更加瘋狂,要是太快的話,加上usleep ()暫停一點點時間比較好
只有那些不須要互斥量的程序才能最大限度的利用線程編程帶來的好處,不然只會更慢,2.6內核是搶佔式內核,線程間共享衝突發生的概率遠比2.4內核環境高,尤爲要注意線程安全,不然就算是單CPU也會發生莫名其妙的內存不一樣步(CPU的高速緩存和主存內容不一致),Intel的新CPU爲了性能使用NUMA架構,在線程編程中必定要注意揚長避短。
頗有趣,在默認的ulimit參數下,不修改內核頭文件
AS3 512M內存最多1000併發持續鏈接
CentOS4.3 512M內存最多300併發持續鏈接
彷佛是CentOS不如AS3,這裏主要緣由是ulimit的配置形成,兩個系統默認的配置差距很大,要想單進程維持更多線程接收併發鏈接,就要儘可能縮小 ulimit -s的參數,插更多的內存條,單進程服務器上2000併發一點都不難,POSIX默認的限制是每進程64線程,但NTPL並不是純正POSIX,沒必要理會這個限制,2.6內核下真正的限制是內存條的插槽數目(也許還有買內存的錢數)
最近幾天的編程中,注意到在32位x86平臺上2.6內核單進程建立最大線程數=VIRT上限/stack,與總內存數關係不大,32位x86系統默認的VIRT上限是3G(內存分配的3G+1G方式),默認 stack大小是10240K,所以單進程建立線程默認上限也就300(3072M / 10240K),用ulimit -s 修改stack到1024K則使上限升到大約3050。我手頭沒有64位系統,不知道2.6內核在64位上單進程建立線程上限(其實是本人懶得在同事的機器上裝fc4_x86_64)。
前些天買了一套廉價的64位x86系統(64位賽楊+雜牌915主板),安裝了CentOS4.3的x86_64版本,跑了一遍下面的小程序,獲得的結果是:在ulimit -s 4096的狀況下,單進程最大線程數在16000多一點,用top看
VIRT 的上限是64G,也就是36位, cat /proc/cpuinfo的結果是:address sizes : 36 bits physical, 48 bits virtual, 和我想象的標準64位系統不一樣, 我一直覺得64位系統的內存空間也是64位的
單位裏某BSD FANS用AMD64筆記本跑小程序測試線程建立速度(線程建立後當即phread_detach()而後緊跟着pthread_exit(),共計 100萬個線程),一樣源碼OpenBSD居然比FreeBSD快了3倍,何時OpenBSD也變得瘋狂起來了?
測試單進程建立線程上限C源碼(test.c)
參考