Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

5.10.9. Ограничения на размер файла: вызов ulimit

Для каждого процесса существует ограничение на размер файла, который может быть создан при помощи системного вызова fdwrite. Это ограничение распространяется также на ситуацию, когда увеличивается размер существующего файла, имевшего до этого длину, меньшую максимально возможной.

Предельный размер файла можно изменять при помощи системного вызова ulimit.

Описание

uses stdio;

function ulimit(cmd:longint;args:array of const):longint;

Для получения текущего максимального размера файла можно вызвать ulimit, установив значение параметра cmd равным UL_GETFSIZE. Возвращаемое значение равно числу 512-байтных блоков.

Для изменения максимального размера файла можно присвоить переменной cmd значение UL_SETFSIZE и поместить новое значение максимального размера файла, также в 512-байтных блоках, в переменную newlimit, например:

if ulimit(UL_SETFSIZE, newlimit) < 0 then

perror('Ошибка вызова ulimit');

В действительности увеличить максимальный размер файла таким способом может только суперпользователь. Процессы с идентификаторами других пользователей могут только уменьшать этот предел.

5.10.10. Приоритеты процессов

Система приближенно вычисляет долю процессорного времени, отводимую для работы процесса, руководствуясь значением nice (буквально «дружелюбный»). Значения nice находятся в диапазоне от нуля до максимального значения, зависящего от конкретной системы. Чем больше это число, тем ниже приоритет процесса. Процессы, «дружелюбно настроенные», могут понижать свой приоритет, используя системный вызов nice. Этот вызов имеет один аргумент, положительное число, на которое увеличивается текущее значение nice, например:

nice(5);

Процессы суперпользователя (и только суперпользователя) могут увеличивав свой приоритет, используя отрицательное значение параметра вызова nice. Вызов nice может пригодиться, если есть необходимость, например, вычислить число π с точностью до ста миллионов знаков, не изменяя существенно время реакции системы для остальных пользователей. Вызов nice был введен давно. Современные факультативные расширения реального времени стандарта POSIX определяют гораздо более точное управление планированием параллельной работы процессов.

Описание

uses linux;

Function GetPriority(Which,Who:Integer):Integer;

Function SetPriority(Which,Who,Prio:Integer):Integer;

GetPriority возвращает приоритет процесса, определяемых переменными Which и Who. Which может принимать значения Prio_Process, Prio_PGrp и Prio_User для идентификаторов процесса, его группы и владельца соответственно.

SetPriority устанавливает приоритет процесса. Значение Prio может быть в диапазоне от -20 до 20.

Программа, демонстрирующая функции Nice и Get/SetPriority:

Uses linux;

begin

writeln ('Setting priority to 5');

setpriority (prio_process,getpid,5);

writeln ('New priority = ',getpriority (prio_process,getpid));

writeln ('Doing nice 10');

nice (10);

writeln ('New Priority = ',getpriority (prio_process,getpid));

end.

Глава 6. Сигналы и их обработка

6.1. Введение

Часто требуется создавать программные системы, состоящие не из одной монолитной программы, а из нескольких сотрудничающих процессов. Для этого может быть множество причин: одиночная программа может оказаться слишком громоздкой и не поместиться в памяти; часть требуемых функций часто уже реализована в каких-либо существующих программах; задачу может быть удобнее решать при помощи процесса-сервера, взаимодействующего с произвольным числом процессов-клиентов; есть возможность использовать несколько процессоров и т.д.

К счастью, ОС UNIX имеет развитые механизмы межпроцессного взаимодействия. В этой и следующей главах мы обсудим три наиболее популярных средства: сигналы (signals), программные каналы (pipes) и именованные каналы (FIFO). Данные средства, наряду с более сложными средствами, которым будут посвящены главы 8 и 10, предоставляют разработчику программного обеспечения широкий выбор средств построения многопроцессных систем.

Эта глава будет посвящена изучению первого средства – сигналам. Рассмотрим пример запуска команды UNIX, выполнение которой, вероятно, займет много времени:

$ fpc verybigprog.pas

Позже становится ясным, что программа содержит ошибку, и ее компиляция не может завершиться успехом. Тогда, чтобы сэкономить время, следует прекратить выполнение команды нажатием специальной клавиши прерывания задания (interrupt key) терминала; обычно это клавиша Del или клавиатурная комбинация Ctrl+C. Выполнение программы прекратится, и программист вернется к приглашению ввода команды командного интерпретатора.

В действительности при этом происходит следующая последовательность событий: часть ядра, отвечающая за ввод с клавиатуры, распознает символ прерывания задания. Затем ядро посылает сигнал SIGINT всем процессам, для которых текущий терминал является управляющим терминалом. Среди этих процессов будет и экземпляр компилятора cc. Когда процесс компилятора ее получит этот сигнал, он выполнит связанное с сигналом SIGINT действие по умолчанию – завершит работу. Интересно отметить, что сигнал SIGINT посылается и процессу оболочки, тоже связанному с терминалом. Тем не менее процесс оболочки благоразумно игнорирует этот сигнал, поскольку он должен продолжать работу для интерпретации последующих команд. Как будет рассмотрено далее, пользовательские программы также могут выбирать, нужно ли им перехватывать сигнал SIGINT, есть выполнять специальную процедуру реакции на поступление сигнала, и полагаться на действие по умолчанию для данного сигнала.

Сигналы также используются ядром для обработки определенных типов критических ошибок. Например, предположим, что файл программы поврежден и содержит недопустимые машинные инструкции. При выполнении этой программы процессом, ядро определит попытку выполнения недопустимой инструкции и пошлет процессу сигнал SIGILL (здесь ILL является сокращением от illegal, то есть недопустимый) для завершения его работы. Получившийся диалог может выглядеть примерно так:

$ badprog

illegal instruction - core dumped

Смысл термина core dumped (сброс образа памяти) будет объяснен ниже.

Сигналы могут посылаться не только от ядра к процессу, но и между процессами. Проще всего показать это на примере команды kill. Предположим, например, что программист запускает в фоновом режиме длительную команду

$ fpc verybigprog.pas &

[1] 1098

а затем решает завершить ее работу. Тогда, чтобы послать процессу сигнал SIGTERM, можно использовать команду kill. Так же, как и сигнал SIGINT, сигнал SIGTERM завершит процесс, если в процессе не переопределена стандартная реакция на этот сигнал. В качестве аргумента команды kill должен быть задан идентификатор процесса:

$ kill 1098

Terminated

Сигналы обеспечивают простой метод программного прерывания работы процессов UNIX. Образно можно сравнить его с похлопыванием по плечу, отвлекающим от работы. Из-за своей природы сигналы обычно используются для обработки исключительных ситуаций, а не для обмена данными между процессами.

Процесс может выполнять три действия с сигналами, а именно:

  • изменять свою реакцию на поступление определенного сигнала (изменять обработку сигналов);

  • блокировать сигналы (то есть откладывать их обработку) на время выполнения определенных критических участков кода;

  • посылать сигналы другим процессам.

Каждое из этих действий будет рассмотрено далее в этой главе.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal