SCHED_FIFOLinuxリアルタイム クラスでプログラムを実行したいと考えています。ユーザーのハード リミット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)