在LINUX下的進程資源的限制(STRUCT RLIMIT)

在Linux系統中,Resouce limit指在一個進程的執行過程中,它所能得到的資源的限制,比如進程的core file的最大值,虛擬內存的最大值等。

Resouce limit的大小可以直接影響進程的執行狀況。其有兩個最重要的概念:soft limit 和 hard limit。

struct rlimit {
rlim_t rlim_cur;
rlim_t rlim_max;
};
soft limit是指內核所能支持的資源上限。比如對於RLIMIT_NOFILE(一個進程能打開的最大文件 數,內核默認是1024),soft limit最大也只能達到1024。對於RLIMIT_CORE(core文件的大小,內核不做限制),soft limit最大能是unlimited。
hard limit在資源中只是作爲soft limit的上限。當你設置hard limit後,你以後設置的soft limit只能小於hard limit。要說明的是,hard limit只針對非特權進程,也就是進程的有效用戶ID(effective user ID)不是0的進程。具有特權級別的進程(具有屬性CAP_SYS_RESOURCE),soft limit則只有內核上限。

我們可以來看一下下面兩條命令的輸出。

sishen@sishen:~$ ulimit -c -n -s
core file size (blocks, -c) 0
open files (-n) 1024
stack size (kbytes, -s) 8192
sishen@sishen:~$ ulimit -c -n -s -H
core file size (blocks, -c) unlimited
open files (-n) 1024
stack size (kbytes, -s) unlimited

-H表示顯示的是hard limit。從結果上可以看出soft limit和hard limit的區別。unlimited表示no limit, 即內核的最大值。
對於resouce limit的讀取修改,有兩種方法。


使用shell內建命令ulimit 
使用getrlimit和setrlimit API 

ulimit是改變shell的resouce limit,並達到改變shell啓動的進程的resouce limit效果(子進程繼承)。
usage:ulimit [-SHacdefilmnpqrstuvx [limit]]
當不指定limit的時候,該命令顯示當前值。這裏要注意的是,當你要修改limit的時候,如果不指定-S或者-H,默認是同時設置soft limit和hard limit。也就是之後設置時只能減不能增。所以,建議使用ulimit設置limit參數是加上-S。
getrlimit和setrlimit的使用也很簡單,manpage裏有很清楚的描述。
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
需要注意的是你在setrlimit,需要檢查是否成功來判斷新值有沒有超過hard limit。如下例:
if (getrlimit(RLIMIT_CORE, &rlim)==0) {
rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim_new)!=0) {
rlim_new.rlim_cur = rlim_new.rlim_max =
rlim.rlim_max;
(void) setrlimit(RLIMIT_CORE, &rlim_new);
}
}

 

setrligetrlimit和setrlimit函數

 每個進程都有一組資源限制,其中某一些可以用getrlimit和setrlimit函數查詢和更改。

#include 
#include 
int getrlimit(int resource,struct rlimit *rlptr);
int setrlimit(int resource,const struct rlimit rlptr);
Both return: 0 if OK,nonzero on error兩個函數

  返回:若成功爲0,出錯爲非0

  對這兩個函數的每一次調用都指定一個資源以及一個指向下列結構的指針。

struct rlimit{
rlim rlim ur;/* 軟限制:當前限制 */
rlim rlim ax;/* 硬限制:rlimcur的最大值 */
};

 

  這兩個函數不屬於POSIX.1,但SVR4和4.3+BSD提供它們。SVR4在上面的結構中使用基本系統數據類型rlim。其它系統則將這兩個成員定義爲整型或長整型。

  進程的資源限制通常是在系統初啓時由0#進程建立的,然後由後續進程繼承。在SVR4中,系統默認值可以查看文件/etc/conf/cfd/mtune在4.3+BSD中,系統默認值分散在多個頭文件中。

  在更改資源限制時,須遵循下列三條規則:

  1.任何一個進程都可將一個軟限制更改爲小於或等於其硬限制。
2.任何一個進程都可降低其硬限制值,但它必須大於或等於其軟限制值。這種降低,對普通用戶而言是不可逆反的。
3.只有超級用戶可以提高硬限制。

  一個無限量的限制由常數RLIM NFINITY指定。

  這兩個函數的resource參數取下列值之一。注意並非所有資源限制都受到SVR4和4.3+BSD的支持。

  RLMITCORE(SVR4及4.3+BSD)core文件的最大字節數,若其值爲0則阻止創建core文件。
RLIMIT PU(SVR4及4.3+BSD)CPU時間的最大量值(秒),當超過此軟限止時,向該進程發送SIGXCPU信號。
RLIMIT ATA(SVR4及4.3+BSD)數據段的最大字節長度。這是圖7.3中初始化數據、非初始化數據以及堆的總和。
RLIMIT SIZE(SVR4及4.3+BSD)可以創建的一個文件的最大字節長度。當超過此軟限制時,則向該進程發送SIGFSZ信號。
RLIMIT EMLOCK(4.3+BSD)鎖定在存儲器地址空間(尚末實現)。
RLIMIT OFILE(SVR4)每個進程最多打開的文件數。更改此限制將影響到sysconf函數在參數-sc-OPEN-MAX中返回的值(2.5.4節)。見程序2.3。
RLIMIT PROC(4.3+BSD)每個實際用戶ID所擁有的最大子進程數。更改此限制將影響到sysconf函數在參數 CHILDMAX中返回的值(2.5.4節)。
RLIMIT FILE(4.3+BSD)與SVR4的RLIMIT OFILE相同。
RLIMIT SS(4.3+BSD)最大駐內存集字節長度(RSS)。如果物理存儲器供子應求,則系統核將從進程處取回超過RSS的部分。
RLIMIT TACK(SVR4及4.3+BSD)棧的最大字節長度。見圖7.3。
RLIMIT MEM(SVR4)可映照地址空間的最大字節長度。這影響到mmap函數(12.9節)。

  資源限制影響到調用進程並由其子進程繼承。這就意味着爲了影響一個用戶的所有後續進程,需將資源限制 設置構造在shell之中。確實,Bourne Shell和Kornshell具有內部ulimit命令,CShell具有內部limit命令。(umask和chdir也必須是shell內部的)。

  較早的BourmeShell,例如由貝克萊提供的一種,不支持ulimit命令。較新的KornShell的ulimit命令具有-H和-s選擇項,以分別檢查和修改硬和軟的限制,但它們尚末編寫入文檔。

簡單的用例:

#include<sys/time.h>
#include<sys/resource.h>
#include<unistd.h>
int main()
{
        struct rlimit limit;
        char p = '1';
        limit.rlim_cur = RLIM_INFINITY;
        limit.rlim_max = RLIM_INFINITY;
        if(setrlimit(RLIMIT_CORE, &limit))
        {
                printf("set limit failed\n");
        }

        printf("p = %s\n",p);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章