9.3. Поиск заголовочных и библиотечных файлов
Заголовочные файлы в системе Linux хранятся в иерархии каталогов /usr/include
. Именно там по умолчанию компилятор ищет включаемые файлы. (Заголовочные файлы могут храниться за пределами /usr/include
, но тогда на них имеются ссылки внутри /usr/include
. Например, на момент написания книги включаемые файлы системы X были расположены в /usr/X11R6/include/X11
, но благодаря символической ссылке компилятор мог найти их через /usr/include/X11
.)
С библиотеками дело обстоит практически так же, правда, с некоторыми нюансами. Библиотеки, которые считаются важными для загрузки системы (и ее отладки в случае необходимости), расположены в /lib
. Другие системные библиотеки находятся в /usr/lib
, кроме библиотек X11R6, которые хранятся в /usr/X11R6/lib
. Компилятор по умолчанию будет искать стандартные системные библиотеки.
Некоторые библиотеки обеспечивают поддержку разработки в одной системе для нескольких основных своих версий. В большинстве случаев доступны специальные утилиты конфигурации, которые обеспечивают включение корректных версий заголовочных файлов и компоновку с подходящими версиями библиотек. Унифицированный инструмент под названием pkg-config
обеспечивает эту информацию для каждой версии каждой библиотеки, разработанной для его поддержки.
Часть III
Системное программирование
Глава 10
Модель процессов
Модель процессов — один из "фирменных знаков" Unix. Это — ключ к пониманию прав доступа, отношений между открытыми файлами, сигналов, управления заданиями и большинства других низкоуровневых понятий, описанных в этой книге. Linux адаптирует большую часть модели процессов Unix и добавляет собственные новые идеи, касающиеся реализации облегченных потоков.
10.1. Определение процесса
Что такое процесс? В исходной реализации Unix процессом была любая выполняющаяся программа. Для каждой программы ядро системы отслеживает перечисленные ниже аспекты.
• Текущая точка выполнения (такая как ожидание возврата системного вызова из ядра), часто называемая программным контекстом.
• К каким файлам имеет доступ программа.
• Сертификаты (credentials) программы (например, какой пользователь и группа владеют процессом).
• Текущий каталог программы.
• К какому пространству памяти имеет доступ программа и как оно распределено.
Процесс также является базовой единицей планирования для операционной системы. Только процессам разрешено выполняться в центральном процессоре.
10.1.1. Усложнение концепции — потоки
Хотя определение процесса может показаться очевидным, концепция потока (thread) делает все это несколько менее ясным. Поток позволяет единственной программе выполняться во многих местах одновременно. Все потоки, созданные одной программой, разделяют большинство характеристик, которые отличают процессы друг от друга. Например, множество потоков, порожденных от одной программы, разделяют информацию об открытых файлах, правах доступа, текущем каталоге и образе памяти. Как только один из потоков модифицирует глобальную переменную, все потоки увидят новое значение, а не только тот, что это сделал.
Многие реализации Unix (включая каноническую версию AT&T System V) были перепроектированы, чтобы сделать потоки фундаментальным элементом планирования для ядра, и процесс превратился в коллекцию потоков, разделяющих ресурсы. Поскольку множество ресурсов разделяется между потоками, ядро может быстрее переключаться между потоками одного процесса, чем оно это делает при полноконтекстном переключении между процессами. В результате в большинстве ядер Unix существует двухуровневая модель процессов, которая различает потоки и процессы.
В Linux, однако, все идет другим путем. Переключение контекстов в Linux всегда было исключительно быстрым (примерно на том же уровне, как новые "переключатели потоков", представленные в двухуровневом подходе), что стимулировало разработчиков ядра вместо смены подхода к планированию процессов позволить процессам разделять ресурсы более либерально.
Под Linux процесс определен исключительно как планируемая сущность, и единственная вещь, которая уникальна для процесса — это текущий контекст выполнения. Он не предполагает ничего относительно разделенных ресурсов, потому что процесс, создающий новый дочерний процесс, имеет полный контроль над тем, какие из ресурсов процессы могут разделять между собой (см. детали в описании системного вызова clone() в конце этой главы). Эта модель позволяет сохранять традиционную систему управления процессами Unix, в то время как традиционный интерфейс потоков строится вне ядра.
Читать дальше