- •Введение
- •1 Тема 7. Подсистема управления вводом-выводом
- •1.1 Язык С как стандарт взаимодействия с ОС
- •1.2 Системные операции для работы с файловой системой
- •1.2.1 Системные вызовы open() и close()
- •1.2.2 Системные вызовы read() и write()
- •1.2.3 Системный вызов lseek()
- •1.3 Создание специальных файлов
- •1.4 Запрос информации о статусе файлов
- •1.5 Каналы
- •1.5.1 Полудуплексные каналы UNIX
- •1.5.2 Именованные каналы FIFO
- •1.6 Дублирование дескрипторов файлов
- •1.7 Монтирование и демонтирование ФС
- •1.8 Ссылки на имена файлов
- •1.9 Лабораторная работа по теме №7
- •1.9.1 Интегрированная среда разработки Eclipse
- •1.9.2 Список заданий выполняемых работ
- •1.9.3 Проблема типов в языке С
- •1.9.4 Анализ структуры MBR блочных устройств
- •1.9.5 Запрос информации о статусе файлов
- •1.9.6 Неименованные каналы ядра ОС
- •1.9.7 Именованные каналы FIFO
- •1.9.8 Монтирование flashUSB
- •1.9.9 Работа с именами файлов
- •2 Тема 8. Подсистема управления памятью
- •2.1 Классификация способов управления ОЗУ
- •2.2 Программный и аппаратный способы адресации памяти
- •2.3 Страничная и сегментная адресации памяти
- •2.4 Комбинированный способ адресации памяти
- •2.5 Лабораторная работа по теме №8
- •2.5.1 Структура поцесса
- •2.5.2 Определяемые сегменты процесса
- •2.5.3 Создание и удаление процессов из памяти
- •2.5.4 Динамическое выделение и освобождение памяти процесса
- •3 Тема 9. Базовое взаимодействие процессов
- •3.1 Подсистема управления процессами
- •3.2 Синхронизация процессов
- •3.3 Стандарты POSIX
- •3.4 Системные вызовы ОС по управлению процессами
- •3.5 Системный вызов fork() и каналы процесса
- •1.5.1 Пример использования каналов процессов
- •1.5.2 Имитация конвейеров языка shell
- •3.6 Нити (Threads)
- •3.7 Сигналы POSIX
- •3.8 Лабораторная работа по теме №9
- •3.8.1 Системные вызовы общей группы
- •3.8.2 Управление потоками процессов
- •3.8.3 Обработка сигналов ОС
- •4 Тема 10. Асинхронное взаиодействие процессов
- •4.1 Проблемы распределения ресурсов ОС
- •4.2 Системный пакет IPC
- •4.3 Утилиты управления средствами пакета IPC
- •Утилита ipcmk
- •Утилита ipcs
- •Утлита ipcrm
- •4.4 Семафоры
- •4.5 Задача об обедающих философах
- •4.5.1 Описание задачи
- •4.5.2 Выбор стратегии решения
- •4.5.3 Модель философа
- •4.5.4 Программа-монитор
- •4.6 Лабораторная работа по теме №10
- •4.6.1 Синхронизация двух процессов
- •4.6.2 Задача «Обедающие философы»
- •5 Тема 11. Эффективное взаиодействие процессов
- •5.1 Прикладные средства пакета IPC
- •5.2 Разделяемые сегменты памяти
- •5.3 Задача о читателях и писателях
- •5.4 Передача сообщений
- •5.5 Лабораторная работа по теме №11
- •5.5.1 Задачи с разделяемыми сегментами памяти
- •5.5.2 Программы передачи сообщений
- •6 Тема 12. Системная шина D-Bus
- •6.1 Графические среды ОС
- •6.2 Рабочий стол пользователя
- •6.3 Различия графических сред ОС
- •6.4 X-сервер UNIX
- •6.5 Архитектура шины D-Bus
- •6.5.2 Бибиотека libdbus
- •6.5.3 Проекции ПО D-Bus на языки программирования
- •6.6 Лабораторная работа по теме №12
- •6.6.1 Утилита qdbus
- •6.6.2 Взаимодействие через шину с приложением evince
- •Заключение
- •Список использованных источников
91
2.5.3 Создание и удаление процессов из памяти
Структура процессов ОС Linux следует современным тенденциям построения операционных систем, в плане использования ими основной памяти ЭВМ:
•они полностью используют виртуальную адресацию памяти;
•ядро ОС фиксирует основные характеристики всех запущенных процессов.
Внастоящее время, ядро ОС использует 32-битную виртуальную адресацию пространства процесса, которая составляет размер в 4 ГБ, как показано на рисунке 2.17:
•первые 3 ГБ соответствуют пространству пользователя (User space);
•последний 1 ГБ находится в распоряжении ядра ОС (Kernel space).
Рисунок 2.17 — Виртуальная адресация процесса ОС Linux
В ядре ОС, для каждого процесса отведена директория страниц, что подразумевает возможность доступа к 1КВ таблицам страниц, которые указывают на 1МВ 4- х килобайтных страниц. Это позволяет адресовать 4 ГБ памяти.
Каждый пользовательский процесс имеет свою локальную таблицу дескриптора, которая адресует различные сегменты кода и сегменты данные-стек.
92
Замечание
В пользовательском пространстве, линейные адреса и логические адреса - идентичны.
Процесс получает свои таблицы страниц от родителя, при выполнении последним системного вызова fork(), со входами, помеченными как READ-ONLY или замещаемые.
Если процесс пытается писать в некоторую область памяти и страница является COPY-ON-WRITE страницей, то она копируется и помечается как READ-WRITE.
В любом случае, «Cистема управления памятью» Linux осуществляет подкачку страниц по обращению, в соответствии со стратегией COPY-ON-WRITE, которая основана на механизме подкачки и поддерживается процессором i386.
Современные ядра ОС Linux псевдоустройство proc, с файловой системой типа proc, которая монтируется к директории /proc корневой ФС.
Эта файловая система содержит много информации о каждом запущенном процес-
се:• директория /proc/<номер процесса> - содержит файлы (псевдофайлы) о разных характеристиках процесса с конкретным номером PID;
•директория /proc/self — является уникальной ссылкой для процесса, который обращается к информации о себе и который, как любой дочерний процесс, не знает свой PID.
Вкачестве демострации указанных возможностей, рассмотрим строку данных файла /proc/self/statm, содержащую семь цифровых слов, семантика которых представлена в таблице 2.1.
Таблица 2.1 — Семантика слов файла /proc/<pid>/statm
Номер слова Семантика слова
1 Общий размер программы
2 Размер резидентной части памяти
3 Число разделяемых страниц
4 Число страниц 'code'
5 Число страниц data/stack
6 Число страниц library
7 Число страниц dirty («грязных»)
Замечание
Все строки псевдофайлов заканчиваются символом перевода строки (0x0A).
Другой пример, файл /proc/self/maps, который содержит адреса и другие параметры всех ресурсов, привязанных к текущему процессу.
93
На листинге 2.3, представлен текст программы, которая читает и выводит на терминал информацию из файлов /proc/self/statm и /proc/self/maps.
Листинг 2.3 - Пример вывода файлов /proc/self/stats и /proc/self/maps
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h>
int main(void) {
puts("Проект lab8.3 ..."); |
|
|
|||||||
char |
|
|
buf[BUFSIZ]; |
|
|
||||
|
|
|
|
||||||
int i, j, fd; |
|
|
|||||||
ssize_t n; |
|
|
|||||||
char *pw[7]; |
|
|
|||||||
fd = open("/proc/self/statm", O_RDONLY); |
|
||||||||
if(fd < 0){ |
|
|
|||||||
|
|
perror("open /proc/self/statm"); |
|
||||||
} |
|
exit(EXIT_FAILURE); |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
puts("Содержимое файла /proc/self/statm:"); |
|
||||||||
n = read(fd, |
buf, BUFSIZ); |
|
|
||||||
if(fd < 0){ |
|
|
|
|
|||||
|
|
perror("read /proc/self/statm:"); |
|
||||||
} |
|
exit(EXIT_FAILURE); |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
close(fd); |
|
|
|||||||
buf[n - 1] = 0; |
|
|
|||||||
puts |
(buf); |
|
|
||||||
i = 0; |
|
|
|||||||
j = 0; |
|
|
|||||||
pw[0] = |
buf; |
|
|
||||||
while |
(buf[i] != 0) { |
|
|
||||||
|
|
if |
(buf[i] == 0x20) { |
// Прочитали слово |
|
||||
|
|
|
|
|
buf[i] = 0; |
|
|
||
} |
|
|
pw[++j]= |
&buf[i + 1]; |
|
||||
|
|
|
|
|
|
|
|||
} |
|
i++; |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
printf("%10s - Общий размер программы (в страницах)\n", |
pw[0]); |
||||||||
printf("%10s - Размер резидентной части памяти\n", |
pw[1]); |
||||||||
printf("%10s - Число разделяемых страниц\n", |
pw[2]); |
||||||||
printf("%10s - Число страниц 'code'\n", |
pw[3]); |
||||||||
printf("%10s - Число страниц data/stack\n", |
pw[4]); |
||||||||
printf("%10s - Число страниц library\n", |
pw[5]); |
||||||||
printf("%10s - Число страниц |
dirty («грязных»)\n", |
pw[6]); |
puts("\nСодержимое файла /proc/self/maps:"); read_maps("/proc/self/maps", buf);
puts("Завершение проекта lab8.3 ..."); return EXIT_SUCCESS;
}
int read_maps(const char *fn, char *buf){ int fd;
ssize_t n;
fd = open(fn, O_RDONLY);
94
if(fd < 0){ perror(fn);
return EXIT_FAILURE;
}
while ((n = read(fd, buf, BUFSIZ - 1)) > 0){ buf[n] = 0;
puts(buf);
}
close(fd);
return EXIT_SUCCESS;
}
Задание 2.3
В среде разработки Eclipse, необходимо создать проект с именем lab8.3, руководствуясь текстом листинга 2.3.
Отладить и провести исследование работы полученной программы. Отразить краткое описание работы данного примера в личном отчете.
На листинге 2.4, представлен второй вариант программы, которая читает и выводит на терминал информацию из файлов /proc/self/statm и /proc/self/maps.
В этом примере, программа, относительно себя, выводит только содержимое файла /proc/self/statm, а затем создает дочерний процесс для вызова программы проекта lab8.3.
Листинг 2.4 — Второй пример вывода файлов /proc/self/stats и /proc/self/maps
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h>
int main(void) {
puts("Проект lab8.4 ...");
char buf[BUFSIZ]; int i, j, fd; ssize_t n;
char *pw[7];
fd = open("/proc/self/statm", O_RDONLY); if(fd < 0){
perror("open /proc/self/statm"); exit(EXIT_FAILURE);
}
puts("Содержимое файла /proc/self/statm:"); n = read(fd, buf, BUFSIZ);
if(fd < 0){
perror("read /proc/self/statm:"); exit(EXIT_FAILURE);
}
close(fd); buf[n - 1] = 0; puts(buf);
i = 0; j = 0;
pw[0] = buf;