Linux 軟限制和硬限制


每個進程的實際實現都有一組資源限制, 可以用getrlimit, setrlimit獲取或設置

1. getrlimit和setrlimit

getrlimit和setrlimit, 能分別獲取/設置當前進程的系統資源限制

#include <sys/time.h>
#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);

int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit);
  • 參數
    resource 資源編號, 具體含義見下表描述
    rlim 類型struct rlimit的參數, 用於記錄/設置軟限制(rlim_cur)和硬限制(rlim_max)
struct rlimit {
               rlim_t rlim_cur;  /* Soft limit */
               rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
           };
  • 返回值
    成功返回0; 失敗, 返回-1, errno被設置

  • 附resource所有可能取值

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不支持)

2. 軟限制和硬限制

軟限制: 對進程的資源數的限制的當前值, 可用getrlimit讀取, setrlimit設置, 參數struct rlimitr.lim_cur. 軟限制是限制的當前值, 小於等於 硬限制, 實際進程可以調用setrlimit增長到硬限制值. 也就是說, 軟限制對進程並不是真正的限制.
硬限制: 對進程的資源數的限制的最大值, 也可以用getrlimit讀取/setrlimit設置, 參數struct rlimitr.rlim_max. 硬限制是絕對上限值, 進程增長資源數不會超過硬限制.

3. 實驗驗證

1) 以打開的文件數限制為例, 對應resource = RLIMIT_NOFILE
首先, 打印其軟限制和硬限制.
然后, 通過open(O_CREAT | O_RDWR)方式打開文件, 一直到硬限制為止, 觀察輸出及錯誤情況.

#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FILENAMEMAX   100

int main() 
{
    struct rlimit lim;
    long int i;
    int fd;
    char filename[FILENAMEMAX];

    getrlimit(RLIMIT_NOFILE, &lim);
    printf("Soft limit = %ld, Hard limit = %ld\n", lim.rlim_cur, lim.rlim_max);

    for (i = 0; i < lim.rlim_max; ++i) {
        snprintf(filename, sizeof(filename), "%d_%ld", getpid(), i);
        fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0664);

        if (fd < 0) {
            fprintf(stderr, "open file %s error\n", filename);
            exit(1);
        }
        else {
            printf("open file %s success\n", filename);
        }
        // close(fd);
    }
}

輸出結果見下, 可以知道成功打開了1021個文件(0~1020號), 到第1021個文件時, . 不過, 為什么不是軟限制1024個呢?
因為每個進程啟動的時候, 已經默認打開了stdin, stdout, stderr這3個文件.

Soft limit = 1024, Hard limit = 4096
open file 17921_0 success
open file 17921_1 success
open file 17921_2 success
open file 17921_3 success
...
open file 17921_1018 success
open file 17921_1019 success
open file 17921_1020 success
open file 17921_1021 error

2) 在1)的基礎上, 修改軟限制, 使軟限制 = 硬限制

在printf和for之間, 添加setrlimit語句, 修改軟限制

    getrlimit(RLIMIT_NOFILE, &lim);
    printf("Soft limit = %ld, Hard limit = %ld\n", lim.rlim_cur, lim.rlim_max);

    /* 修改軟限制 */
    lim.rlim_cur = lim.rlim_max;
    setrlimit(RLIMIT_NOFILE, &lim);

    for (i = 0; i < lim.rlim_max; ++i) {
        ...
    }

再次運行, 程序可以打開4096個文件(包括stdin/stdout/stdout 3個文件)

...
open file 19449_4090 success
open file 19449_4091 success
open file 19449_4092 success
open file 19449_4093 error

參考

進程環境之getrlimit和setrlimit函數 | 博客園


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM