gpt4 book ai didi

c - 为什么 setrlimit(RLIMIT_NPROC) 在以 root 身份运行时不起作用,但在以普通用户身份运行时却工作正常?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:14:36 35 4
gpt4 key购买 nike

我编写了以下 C 程序来限制该程序可以创建的最大进程数(在 Linux 上)。该程序使用了setrlimit(),预计该程序最多可以创建4个进程。

// nproc.c
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>

int main(void)
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 4;
setrlimit(RLIMIT_NPROC, &rlim);
for (int i = 0; i < 3; ++i) printf("%d\n", fork());
sleep(1);
return 0;
}

当我以普通用户身份编译并运行这个程序时,它给出了以下输出:

$ ./nproc
-1
-1
-1

-1 表示 fork() 失败并且 rlimit 正常工作以限制程序可以创建的最大进程数。但是当我以 root 身份运行这个程序时,它给出了以下输出:

$ sudo ./nproc
25926
25927
25928
0
0
25929
0
25930
25931
0
0
0
25932
0

我们可以看到所有的 fork() 都成功了,而 rlimit 没有正常工作。问题出在哪里?

最佳答案

以下建议代码:

  1. 干净地编译
  2. 未能执行所需的功能(?为什么?)
  3. 包含所有需要的头文件
  4. 只有“父进程”尝试创建子进程
  5. 注意:OP 和提议的程序都在不等待子进程完成的情况下退出。 IE。主程序应该为每个启动的子进程调用 wait()wait_pid()
  6. 注意:对 sleep(1) 的调用使输出保持井井有条。然而,在 sleep 期间,子进程完成并退出,所以实际上在任何时候都只有 1 个子进程在运行,所以即使对 setrlimit() 的调用有如果成功,则“fork()”循环可以永远运行。

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>

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

#include <sys/types.h>
#include <unistd.h>

int main( void )
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 4;

if( getrlimit(RLIMIT_NPROC, &rlim) == -1 )
{
perror( "getrlimit failed" );
exit( EXIT_FAILURE );
}

if( setrlimit(RLIMIT_NPROC, &rlim) == -1 )
{
perror( "setrlimit failed" );
exit( EXIT_FAILURE );
}

for (int i = 0; i < 4; ++i)
{
pid_t pid = fork();
switch( pid )
{
case -1:
perror( "fork failed" );
exit( EXIT_FAILURE );
break;

case 0:
printf( "child pid: %d\n", getpid() );
exit( EXIT_SUCCESS );
break;

default:
printf( "parent pid: %d\n", getpid() );
break;
}
sleep(1);
}
return 0;
}

程序运行结果:

fork failed: Resource temporarily unavailable

这表明调用 setrlimit()

时出现问题

来自手册页:

RLIMIT_NPROC
This is a limit on the number of extant process (or, more pre‐
cisely on Linux, threads) for the real user ID of the calling
process. So long as the current number of processes belonging
to this process's real user ID is greater than or equal to this
limit, fork(2) fails with the error EAGAIN.

The RLIMIT_NPROC limit is not enforced for processes that have
either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.

因此,对 setrlimit() 的调用限制了线程的数量,而不是子进程的数量

但是,如果我们在调用 getrlimit() 之后立即添加几个打印语句,并在调用 setrlimit() 之后再次添加,结果是:

    if( getrlimit(RLIMIT_NPROC, &rlim) == -1 )
{
perror( "getrlimit failed" );
exit( EXIT_FAILURE );
}

printf( "soft limit: %d\n", (int)rlim.rlim_cur );
printf( "hard limit: %d\n\n", (int)rlim.rlim_max );

if( setrlimit(RLIMIT_NPROC, &rlim) == -1 )
{
perror( "setrlimit failed" );
exit( EXIT_FAILURE );
}


if( getrlimit(RLIMIT_NPROC, &rlim) == -1 )
{
perror( "getrlimit failed" );
exit( EXIT_FAILURE );
}

printf( "soft limit: %d\n", (int)rlim.rlim_cur );
printf( "hard limit: %d\n\n", (int)rlim.rlim_max );

那么结果是:

soft limit: 27393
hard limit: 27393

soft limit: 27393
hard limit: 27393

parent pid: 5516
child pid: 5517
parent pid: 5516
child pid: 5518
parent pid: 5516
child pid: 5519
parent pid: 5516
child pid: 5520

这表明调用:setrlimit() 实际上并没有改变子进程的限制

注意:我运行的是 ubuntu linux 18.04

关于c - 为什么 setrlimit(RLIMIT_NPROC) 在以 root 身份运行时不起作用,但在以普通用户身份运行时却工作正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54849394/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com