Самодел 1 (1114716), страница 30

Файл №1114716 Самодел 1 (Старые версии Машбука или нечто подобное) 30 страницаСамодел 1 (1114716) страница 302019-05-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 30)

- если процесс открывает FIFO-файл на запись, он будет заблокирован до тех пор, пока какой-либо процесс не откроет тот же канал на чтение

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

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

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

Пример. «Клиент-сервер».

. Итак: существует некоторый процесс – сервер, оказывающий какие-либо услуги, все остальные процессы являются клиентами, они обращаются к серверу с запросами, сервер их обслуживает и возвращает результаты этих запросов клиентам – вот такая идеология называется «клиент-сервер». В данном примере один из процессов является сервером, предоставляющим некоторую услугу. Он получает от клиента pid клиента и печатает строку на стандартный вывод о том, что он получил сообщение от клиента такого-то. Создается именованный канал, далее он открывается, и соответственно с отсутствием блокировки, и происходит попытка чтения данных из канала, не блокируясь, и если данных в канале нет – то вызов read() в данном не блокирующем режиме будет сразу возвращать –1. Следующий while крутится до тех пор пока в канале не появятся данные. Затем данные появились, они были прочитаны, те данные которые были прочитаны печатаются на стандартный вывод, затем канал закрывается и уничтожаются. Процесс-клиент не должен создавать канал, а должен только пытаться к нему подключится, уже открыв его по записи, и после чего записать в него свой pid и завершится.

/* процесс-сервер*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/file.h>

int main(int argc, char **argv)

{

int fd;

int pid;

mkfifo("fifo", S_IFIFO | 0666);

/*создали специальный файл FIFO с открытыми для всех правами доступа на чтение и запись*/

fd = open ("fifo", O_RDONLY | O_NONBLOCK);

/* открыли канал на чтение*/

while ( read (fd, &pid, sizeof(int) ) == -1) ;

printf ("Server %d got message from %d !\n", getpid(), pid);

close (fd);

unlink ("fifo");

/*уничтожили именованный канал*/

return 0;

}

/* процесс-клиент*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/file.h>

int main(int argc, char **argv)

{

int fd;

int pid=getpid( );

fd = open ("fifo", O_RDWR);

write (fd, &pid, sizeof(int));

close (fd);

return 0;

}

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

Межпроцессное взаимодействие, проводимое по модели «главный-подчинённый».

Последнее средство, которое будет рассмотрено в рамках этой темы – это модель взаимодействия «главный-подчиненный». До сих пор все модели взаимодействия между процессами были равноправны, возможно, они выполняли разные функции: кто-то читал данные, а кто-то являлся отправителем, но так или иначе процессы были равноправными. Схема «главный-подчиненный» предполагает, что один из процессов является главным, т.е. управляет поведением другого процесса. В системе Unix к такой модели относится трассировка, т.е. отладка процессов. Трассировка осуществляется двумя процессами, которые родственны между собой. В ОС Unix возможна трассировка только непосредственно своего потомка, при этом трассирующий процесс управляет поведением, выполнением трассируемого процесса. При этом процесс-потомок, которого мы собираемся отлаживать, предварительно должен дать разрешение на трассировку. После того, как процесс-потомок разрешил трассировку, как правило, происходит замена тела этот потомка на ту программу, которую необходимо отладить.

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

Системный вызов ptrace()

Основной системный вызов, используемый при трассировке,– это ptrace(), прототип которого выглядит следующим образом:

#include <sys/ptrace.h>

int ptrace(int cmd, pid, addr, data)

cmd – код выполняемой команды,

pid – идентификатор процесса-потомка,

addr – некоторый адрес в адресном пространстве процесса-потомка,

data – слово информации.

рассмотрим основные коды - cmd операций этой функции.

cmd = PTRACE_TRACEME — ptrace() с таким кодом операции сыновний процесс вызывает в самом начале своей работы, позволяя тем самым трассировать себя. Все остальные обращения к вызову ptrace() осуществляет процесс-отладчик.

cmd = PTRACE_PEEKDATA - чтение слова из адресного пространства отлаживаемого процесса по адресу addr , ptrace() возвращает значение этого слова.

cmd = PTRACE_PEEKUSER — чтение слова из контекста процесса. Речь идет о доступе к пользовательской составляющей контекста данного процесса, сгруппированной в некоторую структуру, описанную в заголовочном файле <sys/user.h>. В этом случае параметр addr указывает смещение относительно начала этой структуры. В этой структуре размещена такая информация, как регистры, текущее состояние процесса, счетчик адреса и так далее. ptrace() возвращает значение считанного слова.

cmd = PTRACE_POKEDATA — запись данных, размещенных в параметре data, по адресу addr в адресном пространстве процесса-потомка.

cmd = PTRACE_POKEUSER — запись слова из data в контекст трассируемого процесса со смещением addr. Таким образом можно, например, изменить счетчик адреса трассируемого процесса, и при последующем возобновлении трассируемого процесса его выполнение начнется с инструкции, находящейся по заданному адресу.

cmd = PTRACE_GETREGS, PTRACE_GETFREGS — чтение регистров общего назначения (в т.ч. с плавающей точкой) трассируемого процесса и запись их значения по адресу data.

cmd = PTRACE_SETREGS, PTRACE_SETFREGS — запись в регистры общего назначения (в т.ч. с плавающей точкой) трассируемого процесса данных, расположенных по адресу data в трассирующем процессе.

cmd = PTRACE_CONT — возобновление выполнения трассируемого процесса. Отлаживаемый процесс будет выполняться до тех пор, пока не получит какой-либо сигнал, либо пока не завершится.

cmd = PTRACE_SYSCALL, PTRACE_SINGLESTEP — эта команда, аналогично PTRACE_CONT, возобновляет выполнение трассируемой программы, но при этом произойдет ее остановка после того, как выполнится одна инструкция. Таким образом, используя PTRACE_SINGLESTEP, можно организовать пошаговую отладку. С помощью команды PTRACE_SYSCALL возобновляется выполнение трассируемой программы вплоть до ближайшего входа или выхода из системного вызова. Идея использования PTRACE_SYSCALL в том, чтобы иметь возможность контролировать значения аргументов, переданных в системный вызов трассируемым процессом, и возвращаемое значение, переданное ему из системного вызова.

cmd = PTRACE_KILL — завершение выполнения трассируемого процесса.

Общая схема трассировки процессов

Рассмотрим некоторый модельный пример, демонстрирующий общую схему построения отладочной программы:

...

if ((pid = fork()) == 0)

{

ptrace(PTRACE_TRACEME, 0, 0, 0);

/* сыновний процесс разрешает трассировать себя */

exec(“трассируемый процесс”, 0);

/* замещается телом процесса, который необходимо трассировать */

}

else

{

/* это процесс, управляющий трассировкой */

wait((int ) 0);

/* процесс приостанавливается до тех пор, пока от трассируемого процесса не придет сообщение о том, что он приостановился */

for(;;)

{

ptrace(PTRACE_SINGLESTEP, pid, 0, 0);

/* возобновляем выполнение трассируемой программы */

wait((int ) 0);

/* процесс приостанавливается до тех пор, пока от трассируемого процесса не придет сообщение о том, что он приостановился */

ptrace(cmd, pid, addr, data);

/* теперь выполняются любые действия над трассируемым процессом */

}

}

Предназначение процесса-потомка — разрешить трассировку себя. После вызова ptrace(PTRACE_TRACEME, 0, 0, 0) ядро устанавливает для этого процесса бит трассировки. Сразу же после этого можно заместить код процесса-потомка кодом программы, которую необходимо отладить. Отметим, что при выполнении системного вызова exec(), если для данного процесса ранее был установлен бит трассировки, ядро перед передачей управления в новую программу посылает процессу сигнал SIGTRAP. При получении данного сигнала трассируемый процесс приостанавливается, и ядро передает управление процессу-отладчику, выводя его из ожидания в вызове wait().

Процесс-родитель вызывает wait() и переходит в состояние ожидания до того момента, пока потомок не перейдет в состояние трассировки. Проснувшись, управляющий процесс, выполняя функцию ptrace(cmd, pid, addr, data) с различными кодами операций, может производить любое действие с трассируемой программой, в частности, читать и записывать данные в адресном пространстве трассируемого процесса, производить его пошаговое выполнение – при этом, как показано в примере выше, применяется та же схема: процесс-отладчик вызывает wait() в состояние ожидания, а ядро возобновляет выполнение трассируемого потомка, исполняет трассируемую команду, и вновь передает управление отладчику, выводя его из ожидания .

Пример. Использование трассировки.

Процесс, который мы будем отлаживать, осуществляет деление на 0. Это сделано для того, чтобы показать, как происходит прерывание выполнения отлаживаемого процесса, когда к нему приходит сигнал. Т.е. когда было произведено деление на 0, приходит сигнал, который мы и будем ловить в нашем отлаживаемом процессе, но в отличии от обычной ситуации, когда обработка по умолчанию на этот сигнал означала бы завершение процесса, в данном случае он будет только приостановлен. В процессе-отладчике, во-первых, описывается структура, при помощи которой будет осуществляться чтение из регистра; далее порождается процесс; в процессе-сыне запускается трассировка (вызов ptrace с командой PTRACE_TRACEME) и запускается замена тела процесса на процесс, который состоит из единственного деления на 0. Отец запускает wait(), первый выход из этого wait() будет сразу после execl() в сыне. После этого он добывает содержимое некоторых регистров, печатает их содержимое. Обратите внимание, что имена этих регистров – EIP(индексный регистр) и ESP(stack pointer) являются машинно-зависимыми, т.е. на другой машине структура REG, а именно имена полей в ней могут быть другими, но в целом структура REG описывает регистры общего назначения на данной архитектуре. Соответственно, они были получены с помощью команды PTRACE_GETREGS в вызове ptrace, затем они распечатываются, затем идет проверка на то, был ли процесс приостановлен с помощью сигнала SIGTRAP и, если этот так, то продолжается его выполнение.Если это не так (это будет в том случае, когда уже второй раз был получен сигнал SIGTRAP от отлаживаемого процесса, когда он остановился в результате деления на 0) он проверяет, что действительно в статусе передано, что этот процесс должен завершится, и он (процесс) закрывается.

Эта схема работает следующим образом: процесс – сын запускает трассировку и запускает execl(), после чего сразу приостанавливается, потому что к нему пришел сигнал SIGTRAP. Процесс-отец в цикле ожидает в wait(), выходит из ожидания, потому что процесс-сын приостанавливается, далее проверяет содержимое его регистров, печатает это содержимое и запускает опять его выполнение. Теперь процесс-сын выполняет программу, которая осуществляет деление на 0, так только он осуществил деление на 0 ему приходит сигнал SIGFPE, и так как он находится в ситуации трассировки, то он приостанавливается, и управление вновь передается процессу-отцу. Процесс-отец вновь вышел из wait(), проанализировал ситуацию, увидел из-за какого сигнала прервалось выполнение отлаживаемого процесса. Для этого он использует следующие макросы: WSTOPSIG() – это макрос, который позволяет из статуса процесса (из того что вернулось в функции wait()) получить информацию из-за чего тот был приостановлен: т.е. то, что он был приостановлен в результате сигнала или в результате какого сигнала. Далее из этого же статуса с помощью макроса WIFEXITED(), что процесс-потомок должен был завершиться, и в этом случае он просто убивается с помощью использования команды PTRACE_KILL в вызове ptrace.

/* Процесс-сын: */

int main(int argc, char **argv)

{

Характеристики

Тип файла
Документ
Размер
3,53 Mb
Тип материала
Высшее учебное заведение

Список файлов лекций

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6392
Авторов
на СтудИзбе
307
Средний доход
с одного платного файла
Обучение Подробнее