Патч к ядру Linux: использование
Навигация: Главная страница/Система ejudge/Патч к ядру Linux/Использование
В данном разделе описывается использование патча для ядер серии 2.6. Здесь описываются нискоуровневые интерфейсы, которые могут измениться (и изменяются) от версии к версии ядра. Поэтому рекомендуется использовать библиотеку reuse.
Contents
Включение безопасного режима работы процесса
Для включения безопасного режима работы используется системный вызов ptrace:
ptrace(0x4281, 0, 0, 0)
Здесь 0x4281 — «магическое» число - код запроса. Безопасный режим включается у текущего процесса. После включения безопасного режима процесс имеет право выполнить один системный вызов execve, то есть запустить на выполнение другую программу. Запускаемая программа будет работать в безопасном режиме, но уже не будет иметь право выполнять системный вызов exec.
При успешном завершении (то есть когда патч установлен в работающее ядро) системный вызов ptrace возвращает значение 0. Если патч не установлен, ptrace вернет значение -1, а переменная errno будет содержать код ошибки EINVAL.
Установка ограничения времени работы процесса в миллисекундах
Для установки ограничения времени работы процесса в миллисекундах используется системный вызов setrlimit со специальным кодом ресурса.
struct rlimit lim; lim.rlim_cur = mtime; // устанавливаем ограничение mtime миллисекунд lim.rlim_max = mtime; // устанавливаем ограничение mtime миллисекунд setrlimit(RLIMIT_MCPU, &lim);
Константа RLIMIT_MCPU определена в заголовочных файлах исходных кодов ядра Linux после применения патча. Однако, эта константа не определена в пользовательских заголовочных файлах стандартной библиотеки. Поэтому вместо нее необходимо использовать численное значение, которое разное для разных версий ядра. Так, для ядер серии 2.4 RLIMIT_CPU равен 11, для ядер серии 2.6 до версии 2.6.25 RLIMIT_CPU равен 15, а начиная с версии 2.6.25 — 19.
Проверку версии ядра лучше всего проводить на этапе работы программы, проанализировав информацию, возвращаемую системным вызовом uname.
Контроль ошибки Memory Limit Exceeded
По умолчанию даже в безопасном режиме диагностирование ошибки Memory Limit Exceeded отключено. Поведение системы в ситуации превышения лимита памяти процессом не отличается от стандартного, то есть:
- если лимит памяти превышен при запуске программы (например, слишком большая область глобальных переменных), процесс снимается с выполнения посылкой ему сигнала SIGKILL (для непривилегированного участника это отображается как Run-time Error);
- если лимит памяти превышен при работе со стеком (например, вследствии слишком глубокой рекурсии или слишком большой области локальных переменных), процесс снимается с выполнения посылкой ему сигнала SIGSEGV (для непривилегированного участника это отображается как Run-time Error);
- если лимит памяти превыщен при выполнении системного вызова выделения памяти, такого как sbrk или mmap, системный вызов завершается с соответствующим кодом ошибки, и дальнейшая обработка ошибки возлагается на работающую программу.
Для включения диагностики ошибки Memory Limit Exceeded требуется выполнить системный вызов ptrace:
ptrace(0x4280, 0, 0, 0)
Здесь 0x4280 — «магическое» число - код запроса. После включения режима диагностики ошибки Memory Limit Exceeded в ситуации превышения лимита памяти процессом в любой из трех ситуаций ему посылается сигнал SIGKILL, и устанавливается специальный флаг. Это значит, что при включенной диагностике ошибки Memory Limit Exceeded программа не имеет возможность отреагировать на исчерпание памяти в куче.
Значение флага ошибки Memory Limit Exceeded можно получить с помощью системных вызовов семейства wait*. В слове состояния процесса (параметр status) устанавливается бит 0x10000, проверить который можно следующим образом:
wait(&status); if ((status & 0x10000)) { // Memory Limit Exceeded status &= 0xffff; }