21.1 进程资源限制
在操作系统中,我们能够通过函数getrlimit()、setrlimit()分别获得、设置每个进程能够创建的各种系统资源的限制使用量。
21.1.1 函数
1 #include <sys/resource.h> 2 int getrlimit(int resource, struct rlimit *rlp);
- 函数功能:获得资源限制,存放在 rlp 指向的结构体中
- 函数参数:
- @resource:见下面的说明
- @rlp:指向结构体 rlimit 的指针
- 返回值:成功返回0,失败返回非0
1 #include <sys/resource.h> 2 int setrlimit(int resource, const struct rlimit *rlp);
- 函数功能:通过 rlp 指向的结构体去修改 resource 指定的资源限制
- 函数参数:
- @resource:资源限制,可能的选择有
- RLIMIT_AS :进程的最大虚内存空间,字节为单位。即进程可用存储区大小
- RLIMIT_CORE :内核转存文件的最大长度。即core 文件最大字节数
- RLIMIT_CPU :最大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的默认行为是终止进程的执行。然而,可以捕捉信号,处理句柄可将控制返回给主程序。如果进程继续耗费CPU时间,核心会以每秒一次的频率给其发送SIGXCPU信号,直到达到硬限制,那时将给进程发送 SIGKILL信号终止其执行。
- RLIMIT_DATA :进程数据段的最大值。
- RLIMIT_FSIZE :进程可创建的文件的最大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情况下将终止进程的执行。
- RLIMIT_LOCKS :进程可建立的锁和租赁的最大值。即文件锁的最大数
- RLIMIT_MEMLOCK :进程可锁定在内存中的最大数据量,字节为单位。即使用 mlock 能否再再存储器中锁定的最大字节数
- RLIMIT_MSGQUEUE :进程可为POSIX消息队列分配的最大字节数。
- RLIMIT_NICE :进程可通过setpriority() 或 nice()调用设置的最大完美值。
- RLIMIT_NOFILE :指定比进程可打开的最大文件描述词大一的值,超出此值,将会产生EMFILE错误。即能打开的最大文件数
- RLIMIT_NPROC :用户可拥有的最大进程数。即每个用户 ID 可拥有的最大子进程数
- RLIMIT_RTPRIO :进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。
- RTLMIT_RSS :最大驻内存集的字节长度
- RLIMIT_SIGPENDING :用户可拥有的最大挂起信号数。
- RLIMIT_STACK :最大的进程堆栈,以字节为单位。即栈的最大长度
- @rlp:指向结构体 rlimit 的指针
- @resource:资源限制,可能的选择有
- 返回值:成功返回0,出错返回 非0
rlimit 结构体:
1 struct rlimit { 2 __kernel_ulong_t rlim_cur; //软资源限制:用户可以修改的资源限制 3 __kernel_ulong_t rlim_max; //硬资源限制:系统中标配的限制,用户可以修改,root 用户除外 4 };
21.1.2 资源限制修改规则
- 进程资源限制的配置文件
- /etc/security/limits.conf
- Linux 中进程资源的初始化由 0 号进程建立,并被后续进程继承
- 资源限制的修改规则
- 硬资源限制必须大于等于软资源限制
- 任何一进程可以降低或者提升其软资源限制,但必须小于等于其硬资源限制
- 任何一进程可以降低其硬件资源限制,但必须大于其软资源限制,普通用户不可逆进行此操作(即提高操作)
- 只有超级用户可以提高硬资源限制
21.2 例子
21.2.1 获得系统中软硬资源的上限
process_limit.c
1 #include <sys/resource.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #define RLIMIT(name) get_limit(#name, name) 7 8 void get_limit(char *name, int resource) 9 { 10 struct rlimit limit; 11 if(getrlimit(resource, &limit) < 0) { 12 perror("getrlimit error"); 13 return; 14 } 15 16 printf("%-15s", name); 17 18 if(limit.rlim_cur == RLIM_INFINITY) { 19 printf(" infinity"); 20 } else { 21 printf("%10ld", limit.rlim_cur); 22 } 23 24 if(limit.rlim_max == RLIM_INFINITY) { 25 printf(" infinity"); 26 } else { 27 printf("%10ld", limit.rlim_max); 28 } 29 30 printf(" "); 31 } 32 33 int main(void) 34 { 35 RLIMIT(RLIMIT_AS); 36 RLIMIT(RLIMIT_CORE); 37 RLIMIT(RLIMIT_CPU); 38 RLIMIT(RLIMIT_DATA); 39 RLIMIT(RLIMIT_FSIZE); 40 RLIMIT(RLIMIT_LOCKS); 41 RLIMIT(RLIMIT_MEMLOCK); 42 RLIMIT(RLIMIT_MSGQUEUE); 43 RLIMIT(RLIMIT_NICE); 44 RLIMIT(RLIMIT_NOFILE); 45 RLIMIT(RLIMIT_NPROC); 46 RLIMIT(RLIMIT_RTPRIO); 47 RLIMIT(RLIMIT_RSS); 48 RLIMIT(RLIMIT_SIGPENDING); 49 RLIMIT(RLIMIT_STACK); 50 51 52 return 0; 53 }
编译运行如下:
21.2.2 修改最大文件数
limit_nofile.c
1 #include <sys/resource.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <string.h> 7 8 #define MODE S_IRWXU | S_IRWXG | S_IRWXO 9 10 int open_file(const char *filename) 11 { 12 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, MODE); 13 if(fd < 0) { 14 perror("open error"); 15 exit(1); 16 } 17 18 return fd; 19 } 20 21 int main(int argc, char *argv[]) 22 { 23 struct rlimit limit; 24 limit.rlim_cur = 4; //设置软资源限制 25 limit.rlim_max = 1024; //设置硬资源限制 26 27 //设置文件打开的最大数 28 //(注意:0 标准输入 1 标准输出 2 标准错误 已经打开) 29 if(setrlimit(RLIMIT_NOFILE, &limit) < 0) { 30 perror("setrlimit error"); 31 exit(1); 32 } 33 34 int fd1, fd2; 35 fd1 = open_file("s1.txt"); 36 fd2 = open_file("s2.txt"); 37 38 close(fd1); 39 close(fd2); 40 41 return 0; 42 }
编译执行:
因为 0,1,2 是已经打开的,所以最多还能打开 4-3 = 1 和 1024 - 3 = 1021 个文件。