В Linux системным вызовом для установки привязки ЦП для процесса является sched_setaffinity
. Еще есть инструмент набора задач
, который делает это в командной строке.
Чтобы эта единственная программа работала только на одном ЦП, я думаю, вам понадобится что-то вроде
taskset -c 1 ./myprogram
(установите любой номер ЦП в качестве аргумента переключателя -c
).
Это должен быть достаточно близок к однопроцессорной системе, если другие ваши процессы не выполняются слишком много по сравнению с тем, который вы хотите измерить, или они не планируются для других процессоров. Если вы хотите выделить один ЦП только для этого единственного процесса и предотвратить запуск других процессов на этом ЦП, вам также потребуется установить их сродство.
Что, я не знаю, как делать правильно. Вам нужно будет установить привязку к процессору init
на очень раннем этапе процесса загрузки, чтобы гарантировать, что она будет унаследована всеми процессами в системе. В качестве обходного пути вы можете использовать taskset -c -p 0 $ PID
для всех других процессов, чтобы заставить их работать только на CPU №0.
systemd также имеет CPUAffinity =
для управления привязкой в файлах модулей, и есть пара из вопросов по установке привязки по умолчанию здесь, в unix.SE , но я не нашел подходящего решения.
Хотя, как прокомментировал @Kamil Maciorowski , ответил на другой вопрос о суперпользователе.com , установка isolcpus = 1
в командной строке ядра должна «изолировать этот ЦП от общих алгоритмов планирования», что может вам понадобиться.
#!/bin/sh
if [ "$(id -u)" -ne 0 ]; then
echo 'This script must be run by root' >&2
exit 1
fi
cat <<HEADER
Host: $(hostname)
Time at start: $(date)
Running cache maintenance...
HEADER
swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches
cat <<FOOTER
Cache maintenance done.
Time at end: $(date)
FOOTER
Пользователь root имеет UID 0 (независимо от имени учетной записи «root» ). Если эффективный UID, возвращаемый id -u
, не равен нулю, пользователь не выполняет сценарий с привилегиями root. Используйте id -ru
для проверки реального ID (UID пользователя , вызывающего скрипт ).
Не используйте $EUID
в скрипте, так как он может быть изменен непривилегированным пользователем:
$ bash -c 'echo $EUID'
1000
$ EUID=0 bash -c 'echo $EUID'
0
Если это сделает пользователь, это, очевидно, не приведет к повышению привилегий, но может привести к тому, что команды в сценарии не смогут выполнять то, что они должны делать, и файлы будут созданы с неверным владельцем и т. д.
Вы можете использовать $USER
или whoami
для проверки текущего пользователя.
if [[ "$USER" != "root" ]]; then
echo "Error: script not running as root or with sudo! Exiting..."
exit 1
fi
if [[ $(whoami) != "root" ]]; then
echo "Warning: script must be run as root or with elevated privileges!"
exit 1
fi
if [[ $(id -u) != "0" ]]; then
echo "Error: script not running as root or with sudo! Exiting..."
exit 1
fi
Я думаю, вам нужно скорее проверить, что у вас есть -привилегии суперпользователя, то есть что ваш эффективный идентификатор пользователя равен 0.
zsh
и bash
делают это доступным в переменной $EUID
, так что вы можете сделать:
if ((EUID != 0)); then
echo >&2 "Error: script not running as root or with sudo! Exiting..."
exit 1
fi
С любыми POSIX -подобными оболочками вы можете использовать id
стандартную команду:
if [ "$(id -u)" -ne 0 ]; then
echo >&2 "Error: script not running as root or with sudo! Exiting..."
exit 1
fi
Обратите внимание, что все id -un
или whoami
или переменная $USERNAME
в zsh
дадут вам первое имя пользователя для uid. В системах, в которых есть другие пользователи с идентификатором 0, это может быть не root
, даже если процесс является потомком процесса, который был аутентифицирован как root
.
$USER
обычно дает вам пользователя, прошедшего аутентификацию, но полагаться на него довольно ненадежно. Он не устанавливается оболочкой, но обычно устанавливается командой аутентификации (, например login
,su
(в системах GNU/Linux, не обязательно другими ), sudo
,sshd
(командой из openssh по крайней мере )... ). Хотя (изменение uid не всегда автоматически устанавливает эту переменную, это должно быть сделано явным образом приложением, изменяющим uid ), и оно также могло быть изменено каким-либо другим процессом в предках оболочки. $LOGNAME
, с той же оговоркой более надежен, так как указан в POSIX (первоначально из FIPS 151 -2)
На самом деле вам нужно определить, есть ли у вас доступ для выполнения этих операций. Вместо этого считается плохой практикой проверять, являетесь ли вы пользователем root.
Если система настроена таким образом, чтобы пользователь, не являющийся -пользователем root, мог изменять кэш подкачки и удалять кэш страниц, почему этот пользователь не должен запускать ваш скрипт?
Вместо этого вы можете просто попробовать операцию и выйти с полезным сообщением, если она не удалась:
if ! ( swapoff -a && swapon -a )
then
echo "Failed to clear swap (rerun as root?)" >&2
exit 1
fi
if ! echo 1 > /proc/sys/vm/drop_caches
then
echo "Failed to free page cache (rerun as root?)" >&2
exit 1
fi