Разделы презентаций


Архитектура вычислительных систем

Содержание

Отображение файлов в виртуальное адресное пространствоВ OC Unix предусмотрена возможность отображения содержимого некоторого файла в виртуальное адресное пространство процесса. В результате такого отображения появляется возможность работы с данными в файле, как

Слайды и текст этой презентации

Слайд 1Архитектура вычислительных систем.
Лекция 9.
Ловецкий К.П.
Москва, ноябрь 2014
Отображение файлов в

виртуальное адресное пространство
Разделяемая память
Взаимодействие процессов через псевдотерминал
Краткие сведения о трассировке


Архитектура вычислительных систем. Лекция 9.Ловецкий К.П.Москва,  ноябрь 2014Отображение файлов в виртуальное адресное пространствоРазделяемая памятьВзаимодействие процессов через

Слайд 2Отображение файлов в виртуальное адресное пространство
В OC Unix предусмотрена возможность

отображения содержимого некоторого файла в виртуальное адресное пространство процесса. В

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

Отображение осуществляется системным вызовом
void *mmap(void *start, int length, int protection,
int flags, int fd, int offset);
Отображение файлов в виртуальное адресное пространствоВ OC Unix предусмотрена возможность отображения содержимого некоторого файла в виртуальное адресное

Слайд 3Перед вызовом mmap() необходимо открыть файл с помощью open(); вызов

mmap() принимает дескриптор файла, подлежащего отображению, в качестве параметра fd.

Параметры offset и length задают, соответственно, позицию начала отображаемого участка в файле и его длину. Здесь необходимо заметить, что и длина, и позиция должны быть кратны некоторому предопределенному числу, называемому размером страницы.
(Заметим, размер страницы для mmap() не имеет, вообще говоря, прямого отношения к размеру страницы виртуальной памяти.) Его можно узнать с помощью функции
int getpagesize();

Отображение файлов в виртуальное адресное пространство

Перед вызовом mmap() необходимо открыть файл с помощью open(); вызов mmap() принимает дескриптор файла, подлежащего отображению, в

Слайд 4Параметр protection вызова mmap() задает режим доступа к получаемому участку

виртуальной памяти. Для этого служат константы PROT_READ, PROT_WRITE и PROT_EXEC,

которые можно объединять операцией побитового «или».
Как ясно из названия, первые две константы соответствуют доступу на запись и чтение. Третья позволяет передавать управление в область отображения, то есть исполнять там код; это используется, например, при подгруздке динамических библиотек. Существует также константа PROT_NONE, соответствующая запрету доступа любого вида.

Отображение файлов в виртуальное адресное пространство

Параметр protection вызова mmap() задает режим доступа к получаемому участку виртуальной памяти. Для этого служат константы PROT_READ,

Слайд 5Отображение файлов в виртуальное адресное пространство
Задаваемый параметром protection доступ должен

быть совместим с режимом, в котором был открыт файл: так,

если файл открыт в режиме «только чтение», то есть в вызове open() был использован флажок O_RDONLY, то попытка отобразить файл в память с режимом, допускающим запись, вызовет ошибку.
В качестве параметра flags необходимо указать либо MAP_SHARED, либо MAP_PRIVATE (тогда изменения, производимые в виртуальном адресном пространстве, никак на файле не отразятся). Кроме того, к одному из этих двух флагов можно добавить через операцию побитового «или» флажки дополнительных опций. Среди этих опций есть MAP_ANONYMOUS, позволяющая создать просто область разделяемой памяти (без файла); в этом случае параметры fd и offset игнорируются.
Отображение файлов в виртуальное адресное пространство	Задаваемый параметром protection доступ должен быть совместим с режимом, в котором был

Слайд 6Отображение файлов в виртуальное адресное пространство
Память, выделенная с помощью mmap()

с указанием MAP_ANONYMOUS, отличается от обычной тем, что при копировании

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

Слайд 7Отображение файлов в виртуальное адресное пространство
Вызов mmap() возвращает указатель на

созданную область виртуальной памяти. Обычно этот указатель преобразуют к другому

типу, например к char*.
В случае ошибки mmap() возвращает значение MAP_FAILED, равное -1, преобразованной к типу void*. Пример:
int fd; char *ptr;
fd = open("file.dat", O_RDWR);
if (fd == -1) { /* ... обработка ошибки ... */ }
ptr = (char*) mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) { /* ... обработка ошибки ... */ }
После выполнения этих действий выражение ptr[25] будет равно значению 26-го байта в файле "file.dat", причем операция присваивания ptr[25] = ’a’ занесет в этот байт символ ’a’.
Отображение файлов в виртуальное адресное пространствоВызов mmap() возвращает указатель на созданную область виртуальной памяти. Обычно этот указатель

Слайд 8Отображение файлов в виртуальное адресное пространство
Рассмотрим другой пример:
int *ptr;
ptr =

(char*) mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
if (ptr ==

MAP_FAILED) { /* ... обработка ошибки ... */ }
if (fork() == 0)
{ /* ... дочерний процесс ... */ }
else { /* ... родительский процесс ... */ }

В этом примере родительский и дочерний процессы имеют доступ к одному и тому же массиву целых чисел (длиной 1024 элемента, если считать, что int занимает 4 байта). Массив доступен через указатель ptr, так что если один из процессов сделает присваивание ptr[77] = 120, то в обоих процессах выражение ptr[77] будет иметь значение 120.
Отображение файлов в виртуальное адресное пространство	Рассмотрим другой пример:int *ptr;ptr = (char*) mmap (NULL, 4096, PROT_READ|PROT_WRITE, 				MAP_SHARED|MAP_ANONYMOUS, 0,

Слайд 9Отображение файлов в виртуальное адресное пространство
Отменить отображение, созданное вызовом mmap(),

можно с помощью вызова

int munmap(void *start, int lenght);

Физическую запись в

файл изменений, сделанных в области отображения, система может произвести не сразу.

Если необходимо гарантировать, что изменения физически записаны на диск, можно воспользоваться вызовом msync().
Отображение файлов в виртуальное адресное пространство	Отменить отображение, созданное вызовом mmap(), можно с помощью вызоваint munmap(void *start, int

Слайд 10Взаимодействие процессов через псевдотерминал
В ОС Unix важное значение имеет

понятие терминала. Иногда терминал приходится эмулировать программно − если мы

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

Слайд 11Взаимодействие процессов через псевдотерминал
Чтобы понять, в чем заключается функционирование

терминала, рассмотрим простейший пример − нажатие комбинации клавиш Ctrl-C. Известно,

что при этом активная программа получает сигнал SIGINT; вопрос только в том, откуда этот сигнал берется. Ясно, что обычный терминал − устройство, передающее и принимающее данные, − ничего не знает о сигналах ОС Unix (и вообще может работать с разными операционными системами). Поэтому логично предположить, что сигнал генерирует сама система, получив от терминала некий специальный символ. Это действительно так: по нажатию Ctrl-C в действительности генерируется символ с кодом 3 (вообще, Ctrl-A генерирует 1, Ctrl-B − 2, и т.д.). Получив этот символ, драйвер терминала рассылает всем процессам основной группы в текущем сеансе под управлением данного терминала сигнал SIGINT.
Кстати, с помощью функции tcsetattr() драйвер терминала можно перепрограммировать, чтобы он отправлял SIGINT по какой-либо другой комбинации клавиш, тогда символ с кодом 3 будет просто отправлен работающей программе на стандартный ввод.
Взаимодействие процессов через псевдотерминал 	Чтобы понять, в чем заключается функционирование терминала, рассмотрим простейший пример − нажатие комбинации

Слайд 12Взаимодействие процессов через псевдотерминал
Рассмотрим ситуацию с программой xterm. Ясно,

что при нажатии Ctrl-C получить SIGINT должна не сама программа

xterm, а те процессы, которые запущены в ее окошке. Сама по себе программа xterm, будучи оконным приложением, и не получает никакого SIGINT, по крайней мере, когда активно именно ее окно и мы нажали Ctrl-C. Вместо этого она получает клавиатурное событие от системы XWindow, свидетельствующее о нажатии комбинации клавиш. Но генерировать сигнал для запущенных под ее управлением процессов ей не нужно, достаточно передать символ с кодом 3 драйверу псевдотерминала, и драйвер поступит точно так же, как если бы на месте программы был настоящий терминал − то есть перехватит символ и вместо него выдаст сигнал SIGINT.
Взаимодействие процессов через псевдотерминал 	Рассмотрим ситуацию с программой xterm. Ясно, что при нажатии Ctrl-C получить SIGINT должна

Слайд 13Взаимодействие процессов через псевдотерминал
Примерно так же обстоят дела и

при нажатии Ctrl-D. Программе xterm нет необходимости закрывать канал связи

с активной программой, выполняющейся в ее окошке, тем более что это и нельзя делать, ведь сеанс одним EOF’ом не заканчивается, в нем могут быть и другие запущенные программы.
Вместо этого программа xterm просто передает драйверу терминала символ, соответствующий комбинации Ctrl-D (то есть символ с кодом 4). Получив его, драйвер терминала обеспечит, чтобы ближайший вызов read(), выполненный на поддерживаемом им логическом терминале, вернул 0 (то есть сигнализировал о ситуации «конец файла»).
Взаимодействие процессов через псевдотерминал 	Примерно так же обстоят дела и при нажатии Ctrl-D. Программе xterm нет необходимости

Слайд 14Взаимодействие процессов через псевдотерминал
Таким образом, псевдотерминал как объект ядра

имеет два двусторонних канала связи,
один для программы, эмулирующей функционирование

терминала (в нашем примере это xterm),
второй для программ, выполняющихся под управлением нашего терминала.

Программа, эмулирующая терминал, в данном виде взаимодействия называется главной (master), а работающие под управлением терминала − подчиненными (slaves).
Взаимодействие процессов через псевдотерминал 	Таким образом, псевдотерминал как объект ядра имеет два двусторонних канала связи, один для

Слайд 15Взаимодействие процессов через псевдотерминал
Чтобы создать псевдотерминал, главная программа вызывает

функцию
int getpt();
возвращающую дескриптор канала связи с псевдотерминалом (для

главной программы). При этом в файловой системе появляется файл устройства, открытие которого позволит присоединиться к тому же псевдотерминалу уже со стороны подчиненных программ. Это логическое устройство называется подчиненным псевдотерминалом (pseudo terminal slave, сокращенно pts).
Затем необходимо применить к полученному дескриптору последовательно функции
int grantpt(int fd);
int unlockpt(int fd);
Взаимодействие процессов через псевдотерминал 	Чтобы создать псевдотерминал, главная программа вызывает функцию 	int getpt(); возвращающую дескриптор канала связи

Слайд 16Взаимодействие процессов через псевдотерминал
int grantpt(int fd);
int unlockpt(int fd);
Первая из

них изменяет принадлежность файла устройства подчиненного псевдотерминала так, что он

становится доступен владельцу текущего процесса. Перед вызовом grantpt() программа, эмулирующая терминал, может, например, сменить свой uid с суперпользовательского на uid конкретного пользователя.
Вторая функция разрешает открытие файла псевдотерминала с помощью вызова open() (до этого он недоступен к открытию, с тем, чтобы главная программа имела возможность установить права доступа к нему до того, как кто-либо его откроет).
Взаимодействие процессов через псевдотерминал int grantpt(int fd);int unlockpt(int fd);	Первая из них изменяет принадлежность файла устройства подчиненного псевдотерминала

Слайд 17Взаимодействие процессов через псевдотерминал
После этого псевдотерминал готов к работе,

и его можно открыть с помощью open(). Например, можно создать

дочерний процесс, там закрыть потоки стандартного ввода, вывода и ошибок, после чего открыть псевдотерминал и связать его дескриптор со всеми тремя потоками, а потом выполнить exec для вызова подчиненной программы. Узнать имя файла устройства подчиненного псевдотерминала можно с помощью функции
char *ptsname(int master_fd);
где master_fd − дескриптор, полученный от getpt().
Всю работу, связанную с созданием описанной связки главный-подчиненный, можно выполнить и проще, с помощью одной функции:
int openpty(int *master, int *slave, char *name, struct termios *termp, struct winsize *winp);
Параметры master и slave задают адреса переменных, в которые следует записать дескрипторы, связанные, соответственно, с «главным» и «подчиненным» каналами связи с псевдотерминалом. Параметр name указывает на буфер, куда следует записать имя подчиненного псевдотерминала, параметры termp и winp задают режим работы псевдотерминала. В качестве любого из последних трех параметров можно передать нулевой указатель.
Взаимодействие процессов через псевдотерминал 	После этого псевдотерминал готов к работе, и его можно открыть с помощью open().

Слайд 18Краткие сведения о трассировке
Трассировка применяется в основном при отладке

программ. В режиме трассировки один процесс (отладчик) контролирует выполнение другого

процесса (отлаживаемой программы), может остановить его, просмотреть и изменить содержимое его памяти, выполнить в пошаговом режиме, установить точки останова, продолжить выполнение до точки останова или до системного вызова, и т.п.

В ОС Unix для поддержки трассировки введен системный вызов
int ptrace(int request, int pid, void *addr, void *data);
Краткие сведения о трассировке 	Трассировка применяется в основном при отладке программ. В режиме трассировки один процесс (отладчик)

Слайд 19Краткие сведения о трассировке
int ptrace(int request, int pid, void

*addr, void *data);

В качестве параметра request вызов получает одну из

возможных команд (описывающую конкретные действия, связанные с трассировкой). Интерпретация остальных параметров зависит от конкретной команды.
Начать трассировку можно двумя способами:
запустить трассируемую программу с начала или
присоединиться к существующему (работающему) процессу.
В первом случае отладчик вызывает fork(), порожденный процесс сначала устанавливает режим отладки (вызывает ptrace() с командой PTRACE_TRACEME), затем запускает (exec) программу, подлежащую трассировке.
Краткие сведения о трассировке 	int ptrace(int request, int pid, void *addr, void *data);В качестве параметра request вызов

Слайд 20Краткие сведения о трассировке
Сразу после команды exec система останавливает

трассируемый процесс и отправляет родительскому процессу (отладчику) сигнал SIGCHLD. Отладчик

должен дождаться этого момента с помощью вызовов семейства wait, которые в данном случае будут ожидать не окончания дочернего процесса, а его останова для трассировки. Далее отладчик может заставить отлаживаемый процесс выполнить один шаг с помощью команды PTRACE_SINGLESTEP,
продолжить его выполнение с помощью PTRACE_CONT,
узнать содержимое регистров с помощью PTRACE_GETREGS, и т.п.
Краткие сведения о трассировке 	Сразу после команды exec система останавливает трассируемый процесс и отправляет родительскому процессу (отладчику)

Слайд 21Краткие сведения о трассировке
Для присоединения к существующему процессу используется

вызов

ptrace() с командой PTRACE_ATTACH.

Следует отметить, что при этом отладчик

во многих смыслах начинает выполнять роль родительского процесса по отношению к отлаживаемому; в частности, сигналы SIGCHLD посылаются теперь отладчику, а не исходному родительскому процессу, хотя функция getppid() в отлаживаемом процессе продолжает возвращать идентификатор настоящего родительского процесса.
Краткие сведения о трассировке 	Для присоединения к существующему процессу используется вызов		ptrace() с командой PTRACE_ATTACH. Следует отметить, что

Слайд 22Th-th-th-that's all folks!

Th-th-th-that's all folks!

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика