Платный
хостинг от провайдера HostSpace.com.ua - хостинг, регистрация доменов.
Поддержка PHP, MySQL, почта - в каждом тарифном плане.
Программное управление вводом-выводом в linux
Денис Колисниченко
Всем нам известно как использовать перенаправление ввода/вывода из командной строки Linux. Напомню, что для перенаправления ввода/вывода используются символы >, <, >> и символ |. Символ > используется для перенаправления стандартного вывода в файл. Символ < используется для переназначения стандартного ввода команды. Например, при выполнении команды cat < file.txt в качестве стандартного ввода будет использован файл file.txt, а не клавиатура.
Символ >> используется для присоединения данных в конец файла (append) стандартного вывода команды. Символ | используется для перенаправления стандартного вывода одной программы на стандартный ввод другой. Например, ps -ax | grep httpd.
Более подробно о перенаправлении ввода/вывода вы можете прочитать в моей статье «Управление процессами», которую вы сможете найти на сервере Софтерры или на моем сайте.
Перенаправление ввода/вывода можно осуществить и программным путем, то есть без вмешательства пользователя. Наша программа сама перенаправит свой ввод/вывод в нужный файл или какой-нибудь программе.
Вызов system() порождает дочерний процесс, позволяя ему читать данные со стандартного ввода (stdin) и писать на стандартный вывод (stdout). Иногда нам нужно передать данные дочернему процессу или, наоборот, получить информацию от порожденного процесса. Другими словами мы хотим, чтобы дочерний процесс получал данные не со стандартного ввода, а от родительского процесса или/и выводил информацию не на стандартный вывод, а передавал ее процессу-предку. Ввод/вывод между процессами осуществляется с помощью системного вызова popen(). FILE * popen(const char * команда, const char * режим_доступа);
Первый параметр – это название программы, которую мы хотим запустить (дочерний процесс). Второй параметр определяет режим доступа. Установите значение «r», если вам нужно читать вывод дочернего процесса, если же вам нужно передать информацию на стандартный ввод порожденного процесса, установите значение «w». Вы не можете комбинировать сразу оба режима доступа, то есть нельзя установить режим «wr», позволяющий двусторонний обмен.
Вызов popen() возвращает указатель FILE* или пустой указатель NULL, если вызов не удался. Так же, как и при работе с обыкновенными файлами, вы должны закрыть канал вызовом pclose() после завершения операции ввода/вывода. Во время работы с потоком рекомендую использовать вызов fflush(), чтобы предотвратить задержки из-за буферизации.
Теперь несколько простых примеров. Предположим, что нам нужно вывести на стандартный вывод имена всех текстовых файлов, содержащихся в текущем каталоге. Это можно очень просто сделать с помощью вызова system(): system("ls *.txt");
Это уж совсем тривиальная задача – мы просто выводим данные, но никак не обрабатываем их. Как получить все имена текстовых файлов и обработать их в программе? // открываем поток
FILE *fp = popen("ls *.txt", "r");
// в цикле читаем имена всех текстовых файлов
while ((fname = fgets(...,fp);) != EOF)
{
// обрабатываем полученную информацию - fname
}
// закрываем поток
pclose(fp);
Данный код в особых комментариях не нуждается. Сначала мы создаем поток для чтения (доступ «r») информации от порожденного процесс (ls *.txt). Затем в цикле while читаем имена файлов и обрабатываем. Чтение производим до тех пор, пока не будет достигнут конец файла. После окончания операции ввода/вывода закрываем поток вывозом pclose(fp);
Вот теперь мы готовы к тому, чтобы рассмотреть более серьезный пример. В этом примере мы будем передавать данные дочернему процессу. Задача такова: у нас есть две программы. Первая программа передает второй какую-нибудь информацию, вторая обрабатывает ее и выводит на стандартный вывод результат. #include <STDIO.H>
#include <SYS wait.h>
#include <UNISTD.H>
int main()
{
char buff[1024]={0};
FILE * cp; // cp - child process – дочерний процесс
int status;
// Открываем канал для записи. Дочерний процесс – /usr/bin/child
cp=popen("/usr/bin/child", "w");
if (!cp)
{
printf("не могу открыть канал.\n");
exit(1)
}
printf("Введите информацию для передачи дочернему процессу" );
// читаем ввод пользователя
fgets(buff, sizeof (buff), stdin);
// передаем данные дочернему процессу
fprintf(cp, "%s\n", buff);
// «выталкиваем» содержимое буфера в канал
fflush(cp);
// закрываем канал и проверяем состояние вызова pclose()
status=pclose(cp);
if (!WIFEXITED(status))
printf("ошибка при закрытии канала\n");
printf("Завершение работы родительского процесса\n"); return 0;
}
Теперь несколько комментариев. Мы используем вызов popen(), чтобы установить связь между родительским и дочерним процессами. Если мы не можем этого сделать по какой-либо причине, например, исполнимый файл дочернего процесса /usr/bin/child не существует, мы выводим сообщение об ошибке и завершаем работу программы. Потом мы читаем со стандартного ввода родительского процесса информацию для передачи дочернему процессу. С помощью вызова fprintf() мы передаем информацию по открытому каналу порожденному процессу. При этом вызов fprintf() используется так же, как и при работе с обыкновенными файлами. Во избежание задержек при передаче данных по каналу мы используем вызов fflush() для «выталкивания» данных из буфера в порожденный процесс. После окончания работы с каналом мы его закрываем и проверяем состояние вызова pclose(). При невозможности корректного закрытия канала мы выводим соответствующее предупреждение.
Программа child может выглядеть таким образом: #include <STDIO.H>
int main()
{
char buff[1024]={0};
fgets(buff, sizeof (buff), stdin);
printf("Прочитал со стандартного ввода: %s\n",buff);
printf("Завершение работы дочернего процесса\n");
return 0;
}
Как видите, ничего сверхъестественного в ней нет – программа просто читает данные со стандартного ввода и обрабатывает их: выводит на стандартный вывод.
На экране при запуске родительской программы (позаботьтесь о существовании программы /usr/bin/child) вы увидите примерно следующее: Введите информацию для передачи дочернему процессу hello
Прочитал со стандартного ввода: hello
Завершение работы дочернего процесса
Завершение работы родительского процесса
На этом обзор программного управления вводом/выводом можно считать завершенным. Все свои вопросы и комментарии можете отправлять по адресу: dhsilabs@mail.ru
www.sdteam.com
Операционные системы 03-02-2007
Против Microsoft в Китае подан судебный иск 24-10-2008 Операционные системы Против Microsoft в Китае подан еще один иск. На сей раз китайский юрист Донг Дженвей подал иск против корпорации за ее программное обеспечение Windows Genuine Advantage, которое без ведома пользователей Windows устанавливается на компьютеры. Юрист требует в своем иске от Министерства общественной безопасности КНР возбудить против Microsoft дело о "взломе пользовательских компьютеров".Дженвей утверждает, что действия Microsoft с программ...
Возможности нового Планировщика заданий в Windows Server 2008 28-07-2008 Операционные системы Планировщик заданий (Task scheduler) в Windows Server 2008 подвергся значительной модификации по сравнению с предыдущими версиями Windows Server. Теперь ключевыми элементами запланированных заданий стали триггеры (Triggers), действия (Actions), условия (Conditions) и параметры (Settings).Набор настроек триггеров и действий запланированного задания в Windows Server 2008 значительно расширился. Среди стандартных триггеров – возможность начинать зад...
Как намертво заблокировать процедуру входа в Windows Vista 02-07-2008 Операционные системы Недавно в одной из статей в рамках серии обзоров возможностей Windows Vista я показал, как можно вручную войти в систему Windows Vista на домашнем компьютере: «Как обойти процедуру входа в Windows Vista». Несмотря на то, что данная там инструкция предназначалась для людей, единолично использующих Windows Vista на домашней машине, множество читателей не разделили мнение о том, что можно оставить систему незащищенной.Основываясь на этих отзывах, я ...
Оптимизация и настройка служб Windows Vista 25-06-2008 Операционные системы По умолчанию окно Диспетчера задач (Task Manager) выглядит так, как показано на этом снимке. В нём отображены только процессы, работающие под вашей пользовательской учётной записью. Чтобы увидеть также и процессы, работающие под служебными учётными записями, нужно нажать кнопку Отображать процессы всех пользователей (Show processes from all users), которая находится в нижнем левом углу окна.Используйте Диспетчер задач для того, чтобы увидеть все ...
Персонализация функции быстрого поиска в меню «Пуск» Vista 19-05-2008 Операционные системы К счастью, функцию быстрого поиска в меню «Пуск» (Start) Vista можно сделать еще удобнее, объединив ее с поиском Google. Для этого придется воспользоваться Редактором локальной групповой политики (Local Group Policy Editor). Чтобы его запустить, нажмите клавиши [Windows]+[R], введите в диалоговом окне «Открыть» (Run) фразу gpedit.msc и нажмите «OK». После этого появится диалоговое окно системы Контроля учетных записей пользователей (UAC), в котор...
Использование утилиты проверки диска Check Disk в системе Windows Vista 13-05-2008 Операционные системы Утилита «Проверка диска» (Check disk) операционной системы Windows Vista позволяет проверить целостность диска, выявить повреждённые сектора и восстановить информацию.Щёлкните правой кнопкой на пиктограмме нужного диска и в раскрывшемся контекстном меню выберите пункт «Свойства» (Properties), как показано на изображениях A и B.Изображение A.Изображение B.В диалоговом окне «Свойства» (Properties) перейдите на вкладку «Сервис» (Tools) и нажмите кно... |