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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
| #define _GNU_SOURCE // 启用 GNU 扩展 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/resource.h> // 包含 setrlimit, getrlimit, struct rlimit #include <string.h> #include <errno.h> #include <signal.h> #include <sys/time.h> // 包含 timeval, 用于 CPU 时间限制 #include <fcntl.h> // 包含 open
// 信号处理函数,用于捕获因资源限制而产生的信号 void signal_handler(int sig) { printf("\nCaught signal %d\n", sig); if (sig == SIGXCPU) { printf("CPU time limit (soft) reached. Exiting gracefully.\n"); exit(EXIT_FAILURE); } else if (sig == SIGXFSZ) { printf("File size limit reached. Write operation failed.\n"); // 可以选择继续运行或退出 } }
// 打印特定资源的当前限制 void print_resource_limit(const char* resource_name, int resource) { struct rlimit rl; if (getrlimit(resource, &rl) == 0) { printf("%-15s: Soft = ", resource_name); if (rl.rlim_cur == RLIM_INFINITY) printf("unlimited"); else printf("%ld", (long)rl.rlim_cur);
printf(", Hard = "); if (rl.rlim_max == RLIM_INFINITY) printf("unlimited"); else printf("%ld", (long)rl.rlim_max); printf("\n"); } else { perror("getrlimit"); } }
int main() { struct rlimit rl; struct sigaction sa;
printf("--- Demonstrating setrlimit ---\n"); printf("PID: %d\n", getpid());
// 1. 显示初始的一些资源限制 printf("\n--- Initial Resource Limits ---\n"); print_resource_limit("CPU Time", RLIMIT_CPU); print_resource_limit("File Size", RLIMIT_FSIZE); print_resource_limit("Data Segment", RLIMIT_DATA); print_resource_limit("Stack Size", RLIMIT_STACK); print_resource_limit("Virtual Memory", RLIMIT_AS); print_resource_limit("Open Files", RLIMIT_NOFILE); print_resource_limit("Max Processes", RLIMIT_NPROC); print_resource_limit("Core File Size", RLIMIT_CORE);
// 2. 设置 CPU 时间限制 printf("\n--- Setting CPU Time Limit ---\n"); rl.rlim_cur = 5; // 软限制:5 秒 rl.rlim_max = 10; // 硬限制:10 秒 if (setrlimit(RLIMIT_CPU, &rl) == 0) { printf("Set CPU time limit: Soft = %lds, Hard = %lds\n", (long)rl.rlim_cur, (long)rl.rlim_max); // 设置信号处理函数以捕获 SIGXCPU memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); if (sigaction(SIGXCPU, &sa, NULL) == -1) { perror("sigaction SIGXCPU"); } } else { perror("setrlimit RLIMIT_CPU"); }
// 3. 设置最大打开文件数限制 printf("\n--- Setting Open File Descriptor Limit ---\n"); rl.rlim_cur = 10; // 软限制:最多 10 个文件描述符 rl.rlim_max = 20; // 硬限制:最多 20 个文件描述符 if (setrlimit(RLIMIT_NOFILE, &rl) == 0) { printf("Set open file limit: Soft = %ld, Hard = %ld\n", (long)rl.rlim_cur, (long)rl.rlim_max); } else { perror("setrlimit RLIMIT_NOFILE"); }
// 4. 设置最大文件大小限制 printf("\n--- Setting File Size Limit ---\n"); rl.rlim_cur = 1024 * 1024; // 软限制:1MB rl.rlim_max = 2 * 1024 * 1024; // 硬限制:2MB if (setrlimit(RLIMIT_FSIZE, &rl) == 0) { printf("Set file size limit: Soft = %ld bytes, Hard = %ld bytes\n", (long)rl.rlim_cur, (long)rl.rlim_max); // 设置信号处理函数以捕获 SIGXFSZ sa.sa_handler = signal_handler; if (sigaction(SIGXFSZ, &sa, NULL) == -1) { perror("sigaction SIGXFSZ"); } } else { perror("setrlimit RLIMIT_FSIZE"); }
// 5. 设置虚拟内存限制 (RLIMIT_AS) printf("\n--- Setting Virtual Memory Limit ---\n"); rl.rlim_cur = 50 * 1024 * 1024; // 软限制:50 MB rl.rlim_max = 100 * 1024 * 1024; // 硬限制:100 MB if (setrlimit(RLIMIT_AS, &rl) == 0) { printf("Set virtual memory limit: Soft = %ld bytes (%.2f MB), Hard = %ld bytes (%.2f MB)\n", (long)rl.rlim_cur, (double)rl.rlim_cur / (1024*1024), (long)rl.rlim_max, (double)rl.rlim_max / (1024*1024)); } else { perror("setrlimit RLIMIT_AS"); }
// 6. 设置 core dump 大小为 0,禁用它 printf("\n--- Disabling Core Dump ---\n"); rl.rlim_cur = 0; rl.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rl) == 0) { printf("Disabled core dump generation.\n"); } else { perror("setrlimit RLIMIT_CORE"); }
// 7. 验证设置后的限制 printf("\n--- Resource Limits After setrlimit ---\n"); print_resource_limit("CPU Time", RLIMIT_CPU); print_resource_limit("File Size", RLIMIT_FSIZE); print_resource_limit("Virtual Memory", RLIMIT_AS); print_resource_limit("Open Files", RLIMIT_NOFILE); print_resource_limit("Core File Size", RLIMIT_CORE);
// 8. 演示资源限制的效果
// --- 演示 RLIMIT_FSIZE --- printf("\n--- Testing RLIMIT_FSIZE (File Size Limit) ---\n"); const char* test_filename = "test_limited_file.txt"; int fd = open(test_filename, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) { perror("open test file"); } else { char data[1024]; memset(data, 'A', sizeof(data)); ssize_t written; long total_written = 0; // 尝试写入超过 1MB 的数据 while (total_written < 2 * 1024 * 1024) { written = write(fd, data, sizeof(data)); if (written == -1) { perror("write"); printf("Write failed after writing approximately %ld bytes. File size limit likely reached.\n", total_written); break; } total_written += written; } close(fd); printf("Finished writing (or failed) to file.\n"); // 清理测试文件 unlink(test_filename); }
// --- 演示 RLIMIT_AS --- printf("\n--- Testing RLIMIT_AS (Virtual Memory Limit) ---\n"); printf("Attempting to allocate large chunks of memory until limit is hit...\n"); size_t chunk_size = 10 * 1024 * 1024; // 10MB long allocated_mb = 0; char *ptr; while (1) { ptr = malloc(chunk_size); if (ptr == NULL) { printf("malloc failed after allocating approximately %ld MB. Memory limit likely reached.\n", allocated_mb); break; } // Touch the memory to ensure it's actually allocated memset(ptr, 0, chunk_size); allocated_mb += chunk_size / (1024 * 1024); printf("Allocated %ld MB so far...\n", allocated_mb); // 添加一点延迟,方便观察 sleep(1); }
// --- 演示 RLIMIT_CPU (放在最后,因为它会终止程序) --- printf("\n--- Testing RLIMIT_CPU (CPU Time Limit) ---\n"); printf("Entering infinite loop. Should be killed by SIGKILL after 10 seconds (hard limit).\n"); printf("You might see 'CPU time limit (soft) reached' message first (after 5s), then termination.\n"); while(1) { // 空循环,消耗 CPU 时间 }
// 程序通常不会执行到这里,因为 RLIMIT_CPU 会终止它 printf("Program finished normally (unexpected).\n"); return 0; }
|