Изучение возможностей межпроцессных коммуникаций в ОС Linux. Знакомство и получение практических навыков использования средств межпроцесных коммуникаций – неименованных каналов и общей памяти

Страницы работы

Фрагмент текста работы

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

При реализации перенаправления стандартного вывода выполняются следующие действия:

•  родительская оболочка порождает потомок-оболочку и ждет ее окончания; 

•  порожденная оболочка открывает файл «output», создавая его или добавляя в него, в зависимости от указаний пользователя; 

•  порожденная оболочка дублирует дескриптор файла «output» в дескриптор стандартного вы-вода с номером 1, а затем закрывает исходный дескриптор файла «output». Весь стандартный вывод, таким образом, будет перенаправляться в «output»; 

•  порожденная оболочка выполняет утилиту, используя вызов exec. Так как файловые дескрипторы наследуются при вызове функции exeс, то стандартный вывод утилиты будет направлен в «output»; 

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

Для дублирования файловых дескрипторов используются функции dup и dup2.

int dup(int oldfd);

int dup2(int oldfd, int newfd);

dup находит первый свободный файловый дескриптор с наименьшим номером и дублирует его из дескриптора oldfd. dup2 закрывает newfd, если он еще не закрыт, и затем копирует дескриптор oldfd в newfd. В обоих случаях исходный и скопированный дескрипторы разделяют один текущий указатель внутри файла и режим доступа. Обе функции возвращают номер нового файлового дескриптора или –1 в случае ошибки. 

Пример 2. Перенаправление данных в файл

#include<stdio.h>

#include<sys/file.h>

main(int argc, char *argv[]) 

{

int fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0777);

dup2(fd, 1); /*duplicate to the standard output*/ close(fd);

execvp(argv[2], &argv[2]);

printf("End\n"); /*this command will never be executed*/

}

Примерный вывод:

[nus@localhost src]# 6_2.exe file6_2 ls

Содержимое файла file6_2:

6_1.exe 6_2.exe file6_2 lab6_1.c

lab6_2.c

Программная реализация конвейера

Рассмотрим программную реализацию простейшего конвейера «ls | wc». Для выполнения этой команды оболочка должна создать канал и создать два дочерних процесса, в одном из которых должен быть затем загружен образ «ls», а в другом – «wc». Обычно «ls» пишет в стандартный вывод (дескриптор 1), и «wc» читает со стандартного ввода (дескриптор 0).

Пример 3. Программная реализация конвейера

#include<stdio.h>

#include<string.h>

#define READ 0

#define WRITE 1

main(int argc, char *argv[])

{

int pid, fd [2] ;

if(pipe(fd) == -1) {perror("pipe failed");exit(1);} if((pid = fork( )) < 0) {perror("fork failed");exit(2);}  if( pid != 0 ) /* parent, writer */

{ close( fd [READ] ); /* close unused end */

dup2( fd [WRITE], 1); /* duplicate used end to standard out */ close( fd [WRITE] ); /* close used end */

execlp( argv[1], argv[1], NULL); /* execute writer program */

}

else { /* child, reader */ close( fd [WRITE] ); /* close unused end */

dup2( fd [READ], 0); /* duplicate used end to standard input */ close( fd [READ] ); /* close used end */

execlp( argv[2], argv[2], NULL); /* execute reader program */ }

}

Примерный вывод:

[root@localhost src]# 6_3.exe ls wc

8 8 69

• Общая память

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

Сегмент общей памяти имеет уникальный идентификатор, описываемый структурой типа shmid_ds, определенной в <sys/shm.h> (для использования этого файла требуется подключение <sys/types.h> и <sys/ipc.h>). 

Принцип использования общей памяти заключается в следующем. Для сервера и клиента существует определенная последовательность действий.

Сервер первым должен выполнить следующие действия:

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

Похожие материалы

Информация о работе