Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 11 лет назад пользователемВладлена Чернавская
1 Реализация взаимодействия процессов
2 Взаимодействие процессов взаимодействие в рамках локальной ЭВМ (одной ОС) взаимодействие в рамках сети родственные процессы произвольные процессы неименованные каналы трассировка именованные каналы сигналы IPC сокеты MPI
3 Сигнал – средство уведомления процесса о наступлении некоторого события в системе. Инициаторы посылки сигнала - другой процесс или ОС. Сигналы – механизм асинхронного взаимодействия, момент прихода сигнала процессу заранее неизвестен. Сигналы
4 Обработка сигнала работа процесса приход сигнала Обработка сигнала по умолчанию Вызов функции- обработчика Игнорирование сигнала Примеры сигналов SIGINT (2) SIGQUIT (3) SIGKILL (9) SIGALRM (14) SIGCHLD (18)
5 #include int kill (pit_t pid, int sig); Работа с сигналами pid –идентификатор процесса, которому посылается сигнал sig – номер посылаемого сигнала При удачном выполнении возвращает 0, в противном случае возвращает -1
6 Работа с сигналами #include void (*signal ( int sig, void (*disp) (int))) (int) sig –номер сигнала, для которого устанавливается реакция disp – либо определенная пользователем функция – обработчик сигнала, либо одна из констант: SIG_DFL – обработка по умолчанию SIG_IGN - игнорирование При успешном завершении функция возвращает указатель на предыдущий обработчик данного сигнала.
7 #include int count=1; Пример. Обработка сигнала. void SigHndlr (int s) {printf("\n I got SIGINT %d time(s) \n", count ++); if (count==5) signal (SIGINT, SIG_DFL); else signal (SIGINT, SigHndlr); } int main(int argc, char **argv) {signal (SIGINT, SigHndlr); while (1);/*тело программы*/ return 0; }
8 #include const char * tempfile = abc; Пример. Удаление временных файлов при завершении программы. void SigHndlr (int s) { unlink(tempfile); } int main(int argc, char **argv) { signal(SIGINT, SigHndlr); … creat(tempfile, 0666); … unlink(tempfile); return 0; }
9 Пример. Программа будильник. int main(int argc, char **argv) { char s[80]; signal(SIGALRM, alrm); alarm(5); printf(Введите имя \n); for (;;) { printf(имя:); if (gets(s) != NULL) break; }; printf(OK! \n); return 0; } void alrm (int s) { printf(\n жду имя \n); alarm(5); signal (SIGALRM,alrm); } #include
10 Пример. Двухпроцессный вариант программыбудильник. #include void alr(int s) { printf(\n Быстрее!!! \n); signal (SIGALRM, alr); } int main(int argc, char **argv) { char s[80]; int pid; signal(SIGALRM, alr); if (pid=fork()) {/*отец*/} else {/*сын*/} return 0; }
11 Пример. Двухпроцессный вариант программыбудильник. /*отец*/ for (;;) { sleep(5); kill(pid, SIGALRM); } /*сын*/ printf(Введите имя \n); for (;;) { printf(имя:); if (gets(s) != NULL) break; } printf(OK!\n); kill(getppid(), SIGKILL);
12 Неименованные каналы.
13 Неименованные каналы. Отличительные свойства. Невозможен доступ по имени (доступ только по файловым дескрипторам) Канал не существует вне процесса Реализуется модель последовательного дотупа к данным (FIFO)
14 #include int pipe (int *fd); Неименованные каналы. Системный вызов pipe( ) fd – возвращаемый вызовом массив файловых дескрипторов fd[1] – для записи в канал fd[0] – для чтения из канала
15 Особенности организации чтения из канала. Если прочитано меньше байтов, чем находится в канале, оставшиеся сохраняются в канале Если - попытка чтения из канала - данных недостаточно - существуют открытые дескрипторы записи то имеющиеся данные изымаются, канал блокируется, пока не появятся остальные Можно избежать блокировки, используя вызов fcntl() При закрытии записывающей стороны канала в него помещается EOF (при считывании не будет блокирования)
16 Особенности организации записи в канал. Если процесс пытается записать больше байтов, чем помещается в канал, то возможное количество данных записывается, процесс блокируется, пока не будет достаточно места Можно избежать блокировки, используя вызов fcntl() Если процесс пытается записать в канал, с которым не ассоциирован ни один дескриптор чтения, то он получает сигнал SIGPIPE
17 Пример. Использование канала. int main(int argc, char **argv) { char s*=chanel; char buf[80]; int pipes[2]; pipe(pipes); write(pipes[1],s,strlen(s)+1); read(pipes[0],buf,strlen(s)+1); close(pipes[0]); close(pipes[1]); printf(%s\n,buf); }
18 Пример. Схема взаимодействия процессов с использованием канала. int main(int argc, char **argv) { int fd[2]; pipe(fd); if(fork()) {close(fd[0]); write (fd[1], …); … close(fd[1]); … } else {close(fd[1]); while(read(fd[0],…)){…} … }
19 Пример. Реализация конвейера. #include int main(int argc, char **argv) { int fd[2]; pipe(fd); if(fork()) { dup2(fd[1],1); close(fd[1]); close(fd[0]); exelp(print,print,0); } dup2(fd[0],0); close(fd[0]); close(fd[1]); execl(/usr/bin/wc,wc,0); }
20 #include #define MAX_CNT 100 int target_pid, cnt; int fd[2]; int status; Пример. Совместное использование сигналов и каналов – «пинг-понг».
21 void SigHndlr (int s) { signal(SIGUSR1, SigHndlr); if (cnt < MAX_CNT) { read(fd[0], &cnt, sizeof(int)); printf("%d \n", cnt); cnt++; write(fd[1], cnt, sizeof(int)); kill(target_pid, SIGUSR1); } …
22 Пример. Совместное использование сигналов и каналов – «пинг-понг». … else if (target_pid == getppid()) { printf("Child is going tobe terminated\n"); close(fd[1]); close(fd[0]); exit(0); } else kill(target_pid, SIGUSR1); }
23 Пример. Совместное использование сигналов и каналов – «пинг-понг». int main(int argc, char **argv) { pipe(fd); signal(SIGUSR1, SigHndlr); cnt = 0; if (target_pid = fork()) { wait(&status); printf("Parent is going to be terminated\n"); close(fd[1]); close(fd[0]); return 0; …
24 Пример. Совместное использование сигналов и каналов – «пинг-понг». … } else { target_pid = getppid(); write(fd[1], &cnt, sizeof(int)); kill(target_pid, SIGUSR1); for(;;); }
25 Именованные каналы.
26 int mkfifo (char *pathname, mode_t mode); Именованные каналы. Создание. pathname– имя создаваемого канала mode – права доступа владельца/ группы/прочих
27 Блокировка при подключении; Использование флага O_NONBLOCK или O_NDELAY; Правила работы с именованными каналами полностью аналогичны неименованным каналам. Именованные каналы. Использование системного вызова open().
28 Пример. «Клиент-сервер». Процесс-сервер: #include
29 Пример. «Клиент-сервер». Процесс-сервер: int main(int argc, char **argv) { int fd; int pid; mkfifo("fifo", S_IFIFO | 0666); 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"); }
30 Пример. «Клиент-сервер». Процесс-сервер: int main(int argc, char **argv) { int fd; int pid = getpid( ); fd = open ("fifo", O_RDWR); write (fd, &pid, sizeof(int)); close (fd); } #include
31 Межпроцессное взаимодействие, проводимое по модели «главный-подчинённый».
32 Модель подчиненный-главный Трассировка – возможна между родственными процессами: Процесс-родитель может вести трассировку только непосредственно порожденных им потомков, при этом процесс-потомок должен дать разрешение на это.
33 Системный вызов ptrace() #include int ptrace(int cmd, int pid, int addr, int data); cmd – код выполняемой команды pid – идентификатор процесса-потомка addr – некоторый адрес в адресном пространстве процесса-потомка data – слово информации.
34 Системный вызов ptrace() #include int ptrace(int cmd, int pid, int addr, int data); cmd=PTRACE_TRACEME вызывает сыновний процесс, позволяя трассировать себя cmd=PTRACE_PEEKDATA чтение слова из адресного пространства отлаживаемого процесса cmd=PTRACE_PEEKUSER чтение слова из контекста процесса (из пользовательской составляющей, содержащейся в ) cmd=PTRACE_POKEDATA запись данных в адресное пространство процесса-потомка cmd=PTRACE_POKEUSER запись данных в контекст трассируесого процесса.
35 Системный вызов ptrace() #include int ptrace(int cmd, int pid, int addr, int data); cmd=PTRACE_GETREGS,PTRACE_GETFREGS чтение регистров общего назначения cmd=PTRACE_SETREGS,PTRACE_SETFREGS запись в регистры общего назначения cmd=PTRACE_CONT возобновление выполнения трассируемого процесса cmd=PTRACE_SYSCALL, PTRACE_SINGLESTEP возобновляется выполнение трассируемой программы, но снова останавливается после выполнения одной инструкции cmd=PTRACE_KILL завершение выполнения трассируемого процесса
36 Общая схема трассировки процессов Процесс-потомок ptrace(PTRACE_TRACEME, 0, 0, 0); exec(…);... Процесс-предок wait(…); for(;;) { … ptrace(PTRACE_SINGLESTEP, …); … wait(…); … } cигнал SIGTRAP cигнал SIGTRAP
37 Пример. int main(int argc, char **argv) { return argc/0; } #include
38 Пример. int main(int argc, char *argv[]) { pid_t pid; int status; struct user_regs_struct REG; if ((pid = fork()) == 0) { ptrace(PTRACE_TRACEME, 0, 0, 0); execl(son, son, 0); } …
39 while (1) { wait( &status ); ptrace(PTRACE_GETREGS, pid, ®, ®); printf("signal = %d, status = %#x, EIP=%#x, ESP=%#x\n, WSTOPSIG(status), status, REG.eip, REG.esp); if (WSTOPSIG(status) != SIGTRAP) { if (!WIFEXITED(status)) ptrace (PTRACE_KILL, pid, 0, 0); break; } ptrace (PTRACE_CONT, pid, 0, 0); } Пример.
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.