Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ядро Linux.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
117.25 Кб
Скачать

Принцип генерируемости

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

В наши дни при использовании персональных компьютеров с принципом генерируемости ОС можно столкнуться разве что только при работе с UNIX-like системами, как например linux или freeBSD. В linux имеется возможность не только использовать какое-либо готовое ядро ОС, но и самому сгенерировать (скомпилировать) такое ядро, которое будет оптимальным для данного конкретного персонального компьютера и решаемых на нем задач. Кроме генерации ядра в linux имеется возможность указать и набор подгружаемых драйверов, то есть часть функций может реализовываться модулями, непосредственно входящими в ядро системы, а часть — модулями, имеющими статус подгружаемых, транзитных.

Функциональной избыточности

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

Ipc как пример функциональной избыточности

Средства IPC (Inter-process communication) или межпроцессного взаимодействия представляют механизмы обмена данными между процессами. Количество средств IPC является примером функциональной избыточности различных ОС, в частности ОС linux. Традиционными средствами IPC являются: файлы, сигналы, сокеты, каналы, именованные каналы, семафоры, разделяемая память, посылка сообщений, отображаемая память, очереди сообщений.

Совместно используемая память

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

Совместное использование памяти — самый быстрый способ взаимодействия. Процес обращается к общей памяти с той же скоростью, что и к своей собственной памяти, и никаких системных вызовов или обращений к ядру не требуется. Устраняется также ненужное копирование данных.

Ядро не синхронизирует доступ процессов к общей памяти — об этом следует позаботиться программисту. Например, процесс не должен читать данные из совместно используемой памяти, пока в нее осуществляется запись, и два процесса не должны одновременно записывать данные в одну и ту же область памяти. Стандартная стратегия предотвращения подобной конкуренции заключается в использовании семафоров.

При совместном использовании сегмента памяти один процесс должен сначала выделить память. Затем все остальные процессы, которые хотят получить доступ к ней, должны подключить сегмент. По окончании работы с сегментом каждый процесс отключает его. Последний процесс освобождает память.

Для того чтобы понять принципы выделения и подключения сегментов памяти, необходимо разобраться в модели памяти Linux. В Linux виртуальная память (ВП) каждого процесса разбита на страницы. Все процессы хранят таблицу соответствий между своими адресами памяти и страницами ВП, содержащими реальные данные. Несмотря на то что за каждым процессом закреплены свои адреса, разным процессам разрешается ссылаться на одни и те же страницы. Это и есть совместное использование памяти.

При выделении совместно используемого сегмента памяти создаются страницы ВП. Это действие должно выполняться только один раз, так как все остальные процессы будут обращаться к этому же сегменту. Если запрашивается выделение существующего сегмента, новые страницы не создаются; вместо этого возвращается идентификатор существующих страниц. Чтобы сделать сегмент общедоступным, процесс подключает его, при этом создаются адресные ссылки на страницы сегмента. По окончании работы с сегментом адресные ссылки удаляются. Когда все процессы завершили работу с сегментом, один (и только один) из них должен освободить страницы виртуальной памяти.

Размер совместно используемого сегмента кратен размеру страницы ВП. В Linux последняя величина обычно равна 4 Кбайт, но никогда не помешает это проверить с помощью функции getpagesize ().

Процесс выделяет сегмент памяти с помощью функции shmget (). Первым аргументом пункции является целочисленный ключ, идентифицирующий создаваемый сегмент. Если несвязанные процессы хотят получить доступ к одному и тому же сегменту, они должны казать одинаковый ключ. К сожалению, ничто не мешает посторонним процессам выбрать тот же самый ключ сегмента, а это приведет к системному конфликту. Указание специальной константы IPC_PRIVATE в качестве ключа позволяет гарантировать, что будет создан совершенно новый сегмент.

Во втором аргументе функции задается размер сегмента в байтах. Это значение округляется, чтобы быть кратным размеру страницы ВП.

Третий параметр содержит набор битовых флагов. Перечислим наиболее важные из них.

  • IPC_CREAT. Указывает на то, что создается новый сегмент, которому присваивается заданный ключ.

  • IPC_EXCL. Всегда используется совместно с флагом IPC_CREAT и заставляет функцию shmget () выдать ошибку в случае, когда сегмент с указанным ключом уже существует. Если флаг не указан и возникает описанная ситуация, функция shmget () возвращает идентификатор существующего сегмента, не создавая новый сегмент.

  • Флаги режима. В эту группу входят 9 флагов, задающих права доступа к сегменту для владельца, группы и остальных пользователей. Биты выполнения игнорируются. Проще всего задавать права доступа с помощью констант, определенных в файле <sys/stat.h> (они описаны на man-странице функции stat О ).' Например, флаги S IRUSR и S_IWUSR предоставляют право чтения и записи владельцу сегмента, а флаги SIROTH и SIWOTH предоставляют аналогичные права остальным пользователям.

В случае успешного завершения функция shmget() возвращает идентификатор сегмента. Если сегмент уже существует, проверяются права доступа к нему.

Чтобы сделать сегмент памяти общедоступным, процесс должен подключить его с помощью функции shmat (). В первом ее аргументе передается идентификатор сегмента, возвращенный функцией shmget (). Второй аргумент — это указатель, определяющий, где в адресном пространстве процесса необходимо создать привязку на совместно используемую область памяти. Если задать значение NULL, ОС Linux выберет первый доступный адрес. Третий аргумент может содержать следующие флаги.

SHM_RND. Указывает на то, что адрес, заданный во втором параметре, должен быть округлен, чтобы стать кратным размеру страницы. Если этот флаг не указан, необходимо самостоятельно позаботиться о выравнивании сегмента по границе страницы.

SHM_RDONLY. Указывает на то, что сегмент доступен только для чтения, но не для записи.

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

По завершении работы с сегментом его необходимо отключить с помощью функции shmdt (). Ей следует передать адрес, возвращаемый функцией shmat (). Если текущий процесс был последним, кто ссылался на сегмент, сегмент удаляется из памяти. Функции exit () и exec () автоматически отключают сегменты

Функция shmctl() возвращает информацию о совместно используемом сегменте и способна модифицировать его. Первым параметром является идентификатор сегмента.

Чтобы получить информацию о сегменте, укажите в качестве второго параметра константу IPC_STAT, а в третьем параметре передайте указатель на структуру shmid_ds.

Чтобы удалить сегмент, передайте во втором параметре константу IPC_RMID, а в третьем параметре — NULL. Сегмент удаляется, когда последний подключивший его процесс отключает сегмент.

Каждый совместно используемый сегмент должен явно освобождаться с помощью функции shmctl (), чтобы случайно не был превышен системный лимит на общее число таких сегментов. Функции exit () и exec () отключают сегменты, но не освобождают их.

Рассмотрим пример взаимодействия двух процессов с помощью разделяемой памяти.

Первый файл (программа):

#include <iostream> #include <sys/shm.h> #include <sys/stat.h> int main(){ int segment_id; char * shared_memory; const int segment_size = 0x6400; segment_id = shmget (IPC_PRIVATE, segment_size, IPC_CREAT | S_IRUSR | S_IWUSR); shared_memory = (char *) shmat(segment_id,0,0); sprintf (shared_memory, "Hello World" ); std::cout << "shared memory descriptor is:" << segment_id << std::endl; shmdt (shared_memory); return 0; }

Второй файл(программа):

#include <iostream> #include <sys/shm.h> int main(){ int id; char * shared_memory; std::cin >> id; shared_memory = (char*) shmat(id,0,0); std::cout << "Message: " << shared_memory << std::endl; shmdt(shared_memory); shmctl(id,IPC_RMID,0); return 0;}

Теперь, если скомпилировать обе программы и последовательно запустить их, то при правильном вводе целочисленного ключа, вторая программа выводит сообщение "Message: Hello World"