每個進程都有一組資源限制,其中一些可以用getrlimit和setrlimit函數查詢和更改。
#include <sys/resource.h> int getrlimit( int resource, struct rlimit *rlptr ); int setrlimit( int resource, const struct rlimit *rlptr ); 兩個函數返回值:若成功則返回0,若出錯則返回非0值
進程的資源限制通常是在系統初始化時由進程0建立的,然后由每個后續進程繼承。每種實現都可以用自己的方法對各種限制做出調整。
對這兩個函數的每一次調用都會指定一個資源以及一個指向下列結構的指針。
struct rlimit { rlim_t rlim_cur; /* soft limit: current limit */ rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */ };
在更改資源限制時,須遵循下列三條規則:
(1)任何一個進程都可將一個軟限制值更改為小於或等於其硬限制值。
(2)任何一個進程都可降低其硬限制值,但它必須大於或等於其軟限制值。這種降低對普通用戶而言是不可逆的。
(3)只有超級用戶進程可以提高硬限制值。
常量RLIM_INFINITY指定了一個無限量的限制。
這兩個函數的resource參數取下列值之一:
RLIMIT_AS 進程可用存儲區的最大總長度(字節)。這回影響sbrk函數和mmap函數。
RLIMIT_CORE core文件的最大字節數,若其值為0則阻止創建core文件。
RLIMIT_CPU CPU時間的最大量值(秒),當超過此軟限制時,向該進程發送SIGXCPU信號。
RLIMIT_DATA 數據段的最大字節長度。這是初始化數據、非初始化數據以及堆的總和。
RLIMIT_FSIZE 可以創建的文件的最大字節長度。當超過此軟限制時,則向該進程發送SIGXFSZ信號。
RLIMIT_LOCKS 一個進程可持有的文件鎖的最大數(此數也包括Linux特有的文件租借數)。
RLIMIT_MEMLOCK 一個進程使用mlock(2)能夠鎖定在存儲器中的最大字節長度。
RLIMIT_NOFILE 每個進程能打開的最大文件數。更改此限制將影響到sysconf函數在參數_SC_OPEN_MAX中的返回值。
RLIMIT_NPROC 每個實際用戶ID可擁有的最大子進程數。更改此限制將影響到sysconf函數在參數_SC_CHILD_MAX中返回的值。
RLIMIT_RSS 最大駐內存集的字節長度(resident set size in bytes, RSS)。如果物理存儲器供不應求,則內核將從進程處取回超過RSS的部分。
RLIMIT_SBSIZE 用戶在任一給定時刻可以占用的套接字緩沖區的最大長度(字節)。(Linux 2.4.22不支持)
RLIMIT_STACK 棧的最大字節長度。
RLIMIT_VMEM 這是RLIMIT_AS的同義詞。(Linux 2.4.22不支持)
資源限制影響到調用進程並由其子進程繼承。這就意味着為了影響一個用戶的所有后續進行,需將資源限制的設置構造在shell之中。Bsh、Bash和Ksh具有內置的ulimit命令,Csh具有內置的limit命令。
程序7-8 打印當前資源限制
[root@localhost apue]# cat prog7-8.c #include "apue.h" #if defined(BSD) || defined(MACOS) #include <sys/time.h> #define FMT "%10lld " #else #define FMT "%10ld " #endif #include <sys/resource.h> #define doit(name) pr_limits(#name, name) static void pr_limits(char *, int); int main(void) { #ifdef RLIMIT_AS doit(RLIMIT_AS); #endif doit(RLIMIT_CORE); doit(RLIMIT_CPU); doit(RLIMIT_DATA); doit(RLIMIT_FSIZE); #ifdef RLIMIT_LOCKS doit(RLIMIT_LOCKS); #endif #ifdef RLIMIT_MEMLOCK doit(RLIMIT_MEMLOCK); #endif doit(RLIMIT_NOFILE); #ifdef RLIMIT_NPROC doit(RLIMIT_NPROC); #endif #ifdef RLIMIT_RSS doit(RLIMIT_RSS); #endif #ifdef RLIMIT_SBSIZE doit(RLIMIT_SBSIZE); #endif doit(RLIMIT_STACK); #ifdef RLIMIT_VMEM doit(RLIMIT_VMEM #endif exit(0); } static void pr_limits(char *name, int resource) { struct rlimit limit; if(getrlimit(resource, &limit) < 0) err_sys("getrlimit error for %s", name); printf("%-14s ", name); if(limit.rlim_cur == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_cur); if(limit.rlim_max == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_max); putchar((int)'\n'); }
注意,在doit宏中使用了(也只能在宏中使用)ISO C的字符串創建運算符(#),以便為每個資源名產生字符串值。例如:
doit(RLIMIT_CORE);
這將由C預處理器擴展為:
pr_limits(“RLIMIT_CORE”, RLIMIT_CORE);
在Linux下運行此程序,得到:
[root@localhost apue]# ./prog7-8 RLIMIT_AS (infinite) (infinite) RLIMIT_CORE 0 (infinite) RLIMIT_CPU (infinite) (infinite) RLIMIT_DATA (infinite) (infinite) RLIMIT_FSIZE (infinite) (infinite) RLIMIT_LOCKS (infinite) (infinite) RLIMIT_MEMLOCK 32768 32768 RLIMIT_NOFILE 1024 1024 RLIMIT_NPROC 8192 8192 RLIMIT_RSS (infinite) (infinite) RLIMIT_STACK 10485760 (infinite)
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關於本書可參考:http://www.apuebook.com/。
