Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Переспрямування потоків введення-виведення у POSIX
Реалізація переспрямування потоків введення-виведення у POSIX ґрунтується на тому, що наперед визначені дескриптори не закріплені за конкретними файлами. Перед створенням процесу або під час його виконання можна змінити відповідний елемент таблиці дескрипторів так, щоб він посилався на інший відкритий файл. У результаті всі системні виклики, що використовують як параметр цей файловий дескриптор, працюватимуть із цим файлом, а не з керуючим терміналом. Для переспрямування потоків введення-виведення необхідно, щоб наперед визначений файловий дескриптор посилався на той самий файл, що і наявний дескриптор oldfd, відкритий за допомогою орепО. Щоб змусити наявний дескриптор посилатися на той самий файл, що й інший відкритий дескриптор, можна використати системний виклик dup2(). int dup2 (int fd1. int newfd); де: fd1 — вихідний відкритий дескриптор; newfd — наявний дескриптор, що посилатиметься на той самий файл, що і fdl. Ось приклад переспрямування потоку виведення: int fd1: wri te( STD0UT_FILENO. "на консоль\п", 11); fdl = open(’’output-log.txt". 0_CREAT|0_RDWR. 0644); // переспрямування виведення, аналог myprog > output -1og .txt dup2 (fd1, STDOUTJILENO): // тут STD0UT_FILEN0 посилається на той самий файл, що й fdl wri te( STD0UT_FIL ENO. "у файл\п", 7); close(fd1): Зазначимо, що виклик close () у цьому разі закриє тільки один із двох дескрипторів, STDOU T _FILEN0 залишиться відкритим, і через нього можна продовжувати роботу із файлом. Подібний код можна використати і для переспрямування потоків введення-виведення процесу-нащадка (як це робить командний інтерпретатор), тут виклики ореп() і dup2() виконують у нащадку після виклику fork(), але перед викликом ехес(). Переспрямування потоків введення-виведення у Win32 Для реалізації переспрямування потоків введення-виведення в рамках одного процесу у Win32 використовують функцію SetStdHandl е()
BOOL SetStdHandlе( DWORD std_const. HANDLE fh):
Тут std_const набуває тих самих значень, що і для GetStdHandle(), a fh відображає відкритий файл.
DWORD bytes_written; HANDLE fd. stdout: // одержати стандартний дескриптор stdout = GetStdHandle(STD_OUTPUT_HANDLE); // вивести дані у файл стандартного виводу WriteFile(stdout. "на консоль\n", 11. &bytes_written. 0); fh ч CreateFile(‘’output-log.txt". GENERIC_WRITE....): // переспрямування виведення, аналог myprog.exe > output-log.txt SetStdHandle(STD_OUTPUT_HANDLE. fh); Wn'teFile(stdout. "у файл\п". 7. &bytes_written. 0):
Використання каналів Кілька фільтрів можна об'єднувати для обробки даних за допомогою каналів, при цьому стандартний вивід одного процесу переспрямовують на стандартний ввід іншого:
$ grep linux * I sort
У цьому разі результати виконання утиліти дгер передаватимуться на стандартний ввід утиліті sort. Канали можуть об'єднувати будь-яку кількість процесів. Ще один спосіб використання каналів зводиться до обміну даними між процесом і командним інтерпретатором, під час якого результати виконання процесу будуть підставлені в командний рядок інтерпретатора. Таку технологію називають командною підстановкою (command substitution), для цього командний рядок виклику застосування, результати виконання якого потрібно використати, беруть у зворотні лапки: ~виконуваний_файл параметри1.
$ grep linux 'cat filelist.txt'
У даному випадку файл filelist.txt містить список імен файлів, у яких потрібно зробити пошук. Внаслідок виконання утиліти cat список має видаватись на стандартний вивід, але замість цього його підставляють у командний рядок виклику утиліти grep.
Реалізація каналів у POSIX Для реалізації описаного обміну даними між процесами використовують технологію безіменних каналів (див. розділ 6). Такий канал забезпечує однобічне передавання даних від одного процесу до іншого (тобто коли один процес у канал пише, другий може із нього читати і навпаки). Безіменний канал відкривають за допомогою системного виклику ріре():
#include<unistd.h> int pipe (int fifo[2]):
Тут f і f о — масив із двох файлових дескрипторів, що складають канал: один із них використовують для записування, інший — для читання. Один процес може записувати дані у fifo[0], тоді інший зчитуватиме ці дані із fifo[l]; якщо ж перший процес запише у fifo[l], то другий зчитає з fifo[0]. Спроби читання забло-кують, якщо в канал не надійшли дані, спроби записування - якщо не було спроби читання. Одним із способів використання безіменних каналів є переспрямування стандартного потоку введення або виведення нащадка на один із дескрипторів каналу у тому випадку, коли нащадок запускає зовнішнє застосування [24]. При цьому результати виведення застосування можуть бути зчитані у предку із каналу, а дані, які предок записує в канал, стають, у свою чергу, доступні у застосуванні. Розглянемо приклад отримання доступу до результатів виконання іншого застосування (він може бути основою реалізації командної підстановки).
int pipefd[2], bytes_read, status: pipe (pipefd); if ((pid – fork())== -1) exit(); if ((pid==0) { // нащадок close (pipefd[0]): // закриття дескриптора для читання // переспрямування виведення на дескриптор для записування dup2 (pipefd[l], STD0UTFILEN0): // запуск застосування (execveC...)) або виконання коду нащадка } else { // предок close (pipefd[l]); // закриття дескриптора для записування II... читання даних у циклі з pipefd[0] close (pipefd[0]); // закриття дескриптора для читання waitpid (pid, &status. 0): }
Безіменні канали Win32 Для створення безіменного каналу у Win32 використовують функцію CreatePipeC):
BOOL CreatePipeC PHANDLE rpipe. PHANDLE wpipe, LPSECURITY_ATTRIBUTES psa, DWORD size):
де: грі rpiре, wpi ре — покажчики на дескриптори для читання і записування каналу; size - розмір буфера для каналу (0 - розмір за замовчуванням).
Розглянемо, як задати переспрямування потоків введення-виведення проце-сів-нащадків [50]. ♦ Під час створення каналу для нього має бути дозволене успадкування дескрипторів (передаванням у CreatePipeC) структури SECURITY_ATTRIBUTES із полем blnheritHandle, рівним TRUE). ♦ Потрібно задати певні поля структури STARTUPINF0 перед її передачею у функцію CreateProcessO. Зокрема, встановлення полів hStdlnput, hStdOutput і hStdEr-ror спричиняє задания стандартних дескрипторів нащадка. Якщо стандартний дескриптор треба переспрямовувати, йому присвоюють один із дескрипторів каналу, якщо ні — дескриптор, отриманий за допомогою GetStdHandleC):
// стандартне введення нащадка переспрямовують si.hStdOutput - wpipe; // wpipe отриманий з CreatePipe() // стандартне виведення нащадка не переспрямовують si.hStdlnput - GetStdHandlе (STD_INPUT_HANDLE);
Крім того, полю dwFlags надається значення STARTF_USESTDHANDLES.
♦ Під час виклику CreateProcess() параметру blnheritHandles задається значення TRUE. Після виклику необхідно закрити дескриптор для записування (щоб процес-нащадок завершив своє виведення), зчитати дані з дескриптора для читання, після чого його закрити.
HANDLE грі ре. wpipe; STARTUP INFO Si = {0}; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES). NULL. TRUE}; CreatePipe(&rpipe. &wpipe, &sa. 0); // переспрямування виведення нащадка на дескриптор для записування si.hStdOutput = wpipe; si.hStdlnput = GetStdHandle(STD_INPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.dwFlags - STARTFJJSESTDHANDLES: CreateProcess(NULL. "cmd /с dir". NULL. NULL. TRUE, 0, NULL. NULL. &si. &pi); CloseHandle(pi.hThread); CloseHandle(wpipe); // закриття дескриптора для записування //... читання даних у циклі з гріре > CloseHandle(rpipe); // закриття дескриптора для читання WaitForSingleObject(pi.hProcess. INFINITE): CloseHandle(pi.hProcess);
|
||||||
Последнее изменение этой страницы: 2017-02-06; просмотров: 172; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.220.66.151 (0.01 с.) |