Таблица 10.2. Ограничения ресурсов
Значение |
Лимит |
RLIMIT_AS |
Максимальный объем памяти, доступный процессу. Включает память для стека, глобальных переменных и динамически выделенную память. |
RLIMIT_CORE |
Максимальный размер дампа памяти, генерируемого ядром (если файл дампа получается слишком большим, он не создается). |
RLIMIT_CPU |
Общее используемое время процессора (в секундах). Более подробно об этом ограничении рассказывается при описании SIGXCPU в главе 12. |
RLIMIT_DATA |
Максимальный объем памяти данных (в байтах). Это не включает динамически выделенную память. |
RLIMIT_FSIZE |
Максимальный размер открытого файла (проверяется при записи). Более подробно об этом ограничении рассказывается при описании SIGXFSZ в главе 12. |
RLIMIT_MEMLOCK |
Максимальный объем памяти, которая может быть блокирована с помощью mlock() . Функция mlock() рассматривается в главе 13. |
RLIMIT_NOFILE |
Максимальное количество открытых файлов. |
RLIMIT_NPROC |
Максимальное количество дочерних процессов, которые может породить данный процесс. Это ограничивает только количество дочерних процессов, которые могут существовать одновременно. Это не ограничивает количества наследников дочерних процессов — каждый из них может иметь до RLIMIT_NPROC потомков. |
RLIMIT_RSS |
Максимальный объем ОЗУ, использованный в любой момент (всякое превышение этого объема используемой памяти вызывает страничную подкачку). Это также известно под названием размера резидентной части (resident set size). |
RLIMIT_STACK |
Максимальный размер памяти стека (в байтах), включая все локальные переменные. |
Различные ограничения, которые могут быть установлены, перечислены в табл. 10.2 и определены в . Системные вызовы getrlimit()
и setrlimit()
устанавливают и получают ограничения для отдельного ресурса.
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
Обе эти функции используют структуру struct rlimit
, определенную следующим образом:
struct rlimit {
long int rlim_cur; /* мягкое ограничение */
long int rlim_max; /* жесткое ограничение */
};
Второй член структуры — rlim_max
, указывает жесткое ограничение лимита, переданного в параметре resource
, a rlim_cur
— мягкое ограничение. Это те же наборы лимитов, которыми манипулируют команды ulimit
и limit
, одна из которых встроена в большинство командных оболочек.
10.4. Примитивы процессов
Несмотря на относительно длинную дискуссию, необходимую для описания процесса, создание и уничтожение процессов в Linux достаточно просто.
10.4.1. Создание дочерних процессов
В Linux предусмотрены два системных вызова, которые создают новые процессы: fork()
и clone()
. Как упоминалось ранее, clone()
используется для создания потоков, и этот вызов будет кратко описан далее. А сейчас мы сосредоточимся на fork()
— наиболее популярном методе создания процессов.
#include
pid_t fork(void);
Этот системный вызов имеет уникальное свойство возвращать управление не один раз, а дважды: один раз в родительском процессе и другой — в дочернем. Обратите внимание, что мы не говорим "первый — в родительском" — написание кода, который делает какие-то предположения относительно предопределенного порядка — очень плохая идея.
Каждый из двух возвратов системного вызова fork()
имеет разные значения. В родительский процесс этот системный вызов возвращает pid вновь созданного дочернего процесса, а в дочернем он возвращает 0.
Разница возвращаемых значений — это единственное отличие, видимое процессам. Оба имеют одинаковые образы памяти, права доступа, открытые файлы и обработчики сигналов [19] Детальную информацию о том, как родительские и дочерние открытые файлы соотносятся друг с другом, можно найти в главе 11.
. Рассмотрим простой пример программы, порождающей дочерний процесс.
#include
#include
#include
int main(void) {
pid_t child;
if (!(child = fork())) {
printf("в дочернем\n");
exit (0);
}
printf("в родительском - дочерний: %d\n", child);
return 0;
}
10.4.2. Наблюдение за уничтожением дочерних процессов
Сбор состояний возврата дочернего процесса называется ожиданиемпроцесса. Это можно делать четырьмя способами, хотя только один из вызовов предоставляется ядром. Остальные три метода реализованы в стандартной библиотеке С. Поскольку системный вызов ядра принимает четыре аргумента, он называется wait4()
.
Читать дальше