prlimit64系统调用及示例

prlimit64 函数

1. 函数介绍

prlimit64 用于获取和设置进程的资源限制。它是 getrlimit 和 setrlimit 的增强版本,支持64位资源限制值。

2. 函数原型

1
2
3
4
#define _GNU_SOURCE
#include <sys/resource.h>
int prlimit64(pid_t pid, int resource, const struct rlimit64 *new_limit, struct rlimit64 *old_limit);

3. 功能

获取和/或设置指定进程的资源限制。可以用于控制进程使用的各种系统资源,如内存、文件描述符、CPU时间等。

4. 参数

  • pid_t pid: 目标进程ID(0表示当前进程)

  • int resource: 资源类型(如RLIMIT_AS, RLIMIT_NOFILE等)

  • *const struct rlimit64 new_limit: 新的资源限制(NULL表示不设置)

  • *struct rlimit64 old_limit: 保存旧的资源限制(NULL表示不获取)

5. 返回值

  • 成功: 返回0

  • 失败: 返回-1,并设置errno

6. 相似函数,或关联函数

  • getrlimit/setrlimit: 32位版本

  • ulimit: shell内置命令

  • getrusage: 获取资源使用情况

7. 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#define _GNU_SOURCE
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

/**
* 显示资源限制信息
*/
void display_resource_limit(int resource, const char *name) {
struct rlimit64 limit;

if (prlimit64(0, resource, NULL, &limit) == 0) {
printf("%-20s: ", name);
if (limit.rlim_cur == RLIM64_INFINITY) {
printf("无限制");
} else {
printf("软限制=%lld", (long long)limit.rlim_cur);
}

if (limit.rlim_max == RLIM64_INFINITY) {
printf(", 硬限制=无限制\n");
} else {
printf(", 硬限制=%lld\n", (long long)limit.rlim_max);
}
} else {
printf("%-20s: 获取失败 (%s)\n", name, strerror(errno));
}
}

/**
* 演示prlimit64获取资源限制
*/
int demo_prlimit64_get() {
printf("=== prlimit64 获取资源限制示例 ===\n");

// 显示常见的资源限制
display_resource_limit(RLIMIT_AS, "虚拟内存");
display_resource_limit(RLIMIT_CORE, "核心文件大小");
display_resource_limit(RLIMIT_CPU, "CPU时间");
display_resource_limit(RLIMIT_DATA, "数据段大小");
display_resource_limit(RLIMIT_FSIZE, "文件大小");
display_resource_limit(RLIMIT_NOFILE, "文件描述符数");
display_resource_limit(RLIMIT_NPROC, "进程数");
display_resource_limit(RLIMIT_STACK, "栈大小");

return 0;
}

/**
* 演示prlimit64设置资源限制
*/
int demo_prlimit64_set() {
struct rlimit64 old_limit, new_limit;
int result;

printf("\n=== prlimit64 设置资源限制示例 ===\n");

// 获取当前文件描述符限制
if (prlimit64(0, RLIMIT_NOFILE, NULL, &old_limit) == 0) {
printf("当前文件描述符限制: 软限制=%lld, 硬限制=%lld\n",
(long long)old_limit.rlim_cur, (long long)old_limit.rlim_max);
}

// 尝试设置新的文件描述符限制
new_limit.rlim_cur = 1024; // 软限制
new_limit.rlim_max = 2048; // 硬限制

result = prlimit64(0, RLIMIT_NOFILE, &new_limit, NULL);
if (result == 0) {
printf("成功设置新的文件描述符限制\n");

// 验证设置结果
if (prlimit64(0, RLIMIT_NOFILE, NULL, &old_limit) == 0) {
printf("设置后文件描述符限制: 软限制=%lld, 硬限制=%lld\n",
(long long)old_limit.rlim_cur, (long long)old_limit.rlim_max);
}
} else {
printf("设置文件描述符限制失败: %s\n", strerror(errno));
printf("注意:可能需要root权限或在硬限制范围内调整\n");
}

// 演示内存限制设置
printf("\n尝试设置虚拟内存限制:\n");
new_limit.rlim_cur = 100 * 1024 * 1024; // 100MB
new_limit.rlim_max = 200 * 1024 * 1024; // 200MB

result = prlimit64(0, RLIMIT_AS, &new_limit, NULL);
if (result == 0) {
printf("成功设置虚拟内存限制为100MB\n");
} else {
printf("设置虚拟内存限制失败: %s\n", strerror(errno));
}

return 0;
}

/**
* 演示资源限制的实际影响
*/
int demo_resource_limit_effect() {
struct rlimit64 limit;
int fd_array&#91;100];
int i, fd_count = 0;

printf("\n=== 资源限制实际影响演示 ===\n");

// 获取当前文件描述符限制
if (prlimit64(0, RLIMIT_NOFILE, NULL, &limit) == 0) {
printf("当前文件描述符软限制: %lld\n", (long long)limit.rlim_cur);
}

// 尝试打开大量文件来测试限制
printf("尝试打开文件...\n");
for (i = 0; i < 100; i++) {
char filename&#91;32];
snprintf(filename, sizeof(filename), "test_file_%d.txt", i);

int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
printf("在打开第 %d 个文件时失败: %s\n", i, strerror(errno));
printf("当前已打开 %d 个文件\n", fd_count);
break;
}

fd_array&#91;fd_count++] = fd;

if (i % 20 == 0) {
printf("已成功打开 %d 个文件\n", fd_count);
}
}

// 关闭所有打开的文件
for (i = 0; i < fd_count; i++) {
close(fd_array&#91;i]);
char filename&#91;32];
snprintf(filename, sizeof(filename), "test_file_%d.txt", i);
unlink(filename);
}

printf("清理完成\n");
return 0;
}

int main() {
if (demo_prlimit64_get() == 0) {
demo_prlimit64_set();
demo_resource_limit_effect();
printf("\n=== prlimit64 使用总结 ===\n");
printf("用途:控制进程资源使用,防止资源耗尽\n");
printf("注意:某些限制需要特权权限才能修改\n");
printf("常见资源类型:内存、文件描述符、CPU时间、进程数等\n");
}
return 0;
}

总结

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

这些系统调用提供了强大的文件I/O和资源管理功能:

文件I/O函数特点:

  1. pread/pwrite: 原子性的定位读写,线程安全2. preadv/pwritev: 分散/聚集I/O,一次系统调用处理多个缓冲区3. preadv2/pwritev2: 增强版本,支持额外控制标志

资源管理函数:

  1. prlimit64: 现代化的资源限制管理,支持64位值

使用建议:

  1. 选择合适的函数: 根据具体需求选择单缓冲区或多缓冲区版本2. 注意权限要求: 某些操作需要相应权限3. 错误处理: 始终检查返回值并处理错误4. 性能考虑: 合理使用分散/聚集I/O减少系统调用次数
data-ad-format="auto" data-full-width-responsive="true">