Програмне керування введенням-виведенням в linux, Linux, Операційні системи, статті

Денис Колісниченко

Усім нам відомо як використовувати перенаправлення вводу / виводу з командного рядка Linux. Нагадаю, що для перенаправлення вводу / виводу використовуються символи>, <, >> і символ |. Символ> використовується для перенаправлення стандартного виводу у файл. Символ <використовується для перепризначення стандартного вводу команди. Наприклад, при виконанні команди cat Символ >> використовується для приєднання даних в кінець файлу (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

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*