我想在linuxSCHED_FIFO
实时类下运行一个程序。我更愿意将用户的硬限制RTPRIO
设置为 0,并以编程方式提高单个进程的硬限制。广泛声称,如果我允许该过程CAP_SYS_RESOURCE
允许它提高硬限制,例如man setrlimit 2:
软限制是内核对相应资源强制执行的值。硬限制充当软限制的上限:非特权进程只能将其软限制设置为从 0 到硬限制的范围内的值,并且(不可逆地)降低其硬限制。特权进程(在 Linux 下:具有 CAP_SYS_RESOURCE 能力的进程)可以对任一限制值进行任意更改。
但是,我似乎无法让它为我工作。这是测试代码:
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>
#define PRIORITY (50)
int main(int argc, char **argv) {
struct sched_param param;
struct rlimit rl;
int e, min_fifo, max_fifo;
min_fifo = sched_get_priority_min(SCHED_FIFO);
max_fifo = sched_get_priority_max(SCHED_FIFO);
printf("For policy SCHED_FIFO min priority is %d, max is %d.\n",
min_fifo, max_fifo);
if ((min_fifo>PRIORITY)||(max_fifo<PRIORITY)) {
printf("Desired priority of %d is out of range.\n", PRIORITY);
return 1;
}
if (getrlimit(RLIMIT_RTPRIO, &rl) != 0) {
e = errno;
printf("Failed to getrlimit(): %s.\n", strerror(e));
return 1;
}
printf("RTPRIO soft limit is %d, hard is %d.\n",
(int) rl.rlim_cur, (int) rl.rlim_max);
// Adjust hard limit if necessary
if (rl.rlim_max < PRIORITY) {
rl.rlim_max = PRIORITY;
if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) {
e = errno;
printf("Failed to raise hard limit for RTPRIO to %d: %s.\n",
(int) rl.rlim_max, strerror(e));
return 1;
}
printf("Raised hard limit for RTPRIO to %d.\n", (int) rl.rlim_max);
}
// Adjust soft limit if necessary
if (rl.rlim_cur < PRIORITY) {
rl.rlim_cur = PRIORITY;
if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) {
e = errno;
printf("Failed to raise soft limit for RTPRIO to %d: %s.\n",
(int) rl.rlim_cur, strerror(e));
return 1;
}
printf("Raised soft limit for RTPRIO to %d.\n", (int) rl.rlim_cur);
}
// Set desired priority with class SCHED_FIFO
param.sched_priority = PRIORITY;
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
e = errno;
printf("Setting policy failed: %s.\n", strerror(e));
return 1;
} else {
printf("Set policy SCHED_FIFO, priority %d.\n", param.sched_priority);
}
return 0;
}
这在没有特殊权限的情况下按预期工作,硬限制为 99:
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 99.
Raised soft limit for RTPRIO to 50.
Set policy SCHED_FIFO, priority 50.
$
它使用 sudo 以 0 的硬限制按预期工作:
$ sudo ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Raised hard limit for RTPRIO to 50.
Raised soft limit for RTPRIO to 50.
Set policy SCHED_FIFO, priority 50.
$
但是,当 setuid root 时,它不能按预期工作:
$ sudo chown root ./rtprio
$ sudo chgrp root ./rtprio
$ sudo chmod ug+s ./rtprio
$ ls -l ./rtprio
-rwsrwsr-x 1 root root 8948 11月 28 12:04 ./rtprio
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.
它也意外失败,功能 CAP_SYS_RESOURCE 以及所有功能:
$ sudo setcap cap_sys_resource=eip ./rtprio
$ getcap ./rtprio
./rtprio = cap_sys_resource+eip
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.
$ sudo setcap all=eip ./rtprio
$ getcap ./rtprio
./rtprio =eip
$ ./rtprio
For policy SCHED_FIFO min priority is 1, max is 99.
RTPRIO soft limit is 0, hard is 0.
Failed to raise hard limit for RTPRIO to 50: Operation not permitted.
我在这里想念什么?
$ uname -srv
Linux 3.13.0-100-generic #147-Ubuntu SMP Tue Oct 18 16:48:51 UTC 2016
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.5 LTS
Release: 14.04
Codename: trusty
$ bash --version | head -1
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)