Hlavní navigace

Programování pod Linuxem pro všechny (24)

Jakub Matys

Dnešní článek bude...poslední :(. Čeká nás ještě přesměrovávání vstupu a výstupu a nějaká ta závěrečná řeč (jako na pohřbu ;))

Přesměrování standardního vstupu, výstupu a chybového hlášení

Občas je potřeba použít pro standardní vstup či výstup podřízeného procesu datovou kolonu. Tento problém řeší funkce dup2(), která spojuje dva deskriptory souborů. Příklad přesměrování standardního vstupu do deskriptoru fd:

dup2(fd, STDIN_FILENO);

Deskriptor standardního vstupu je zde zastoupen symbolickou konstantou STDIN_FILENO. Volání funkce uzavře standardní vstup a pak jej znovu otevře. Nově otevřený deskriptor vstupu se odkazuje na stejný ukazatel souboru jako fd.

Následující příklad ukazuje použití funkce dup2. Proces vytvoří rouru a poté pomocí funkce funkce fork() svého potomka. Nadřízený proces vytiskne nějaké řetězce do datové kolony. Podřízený proces si připojí deskriptor souboru pro datovou kolonu jako svůj standardní vstup pomocí funkce dup2 a pak spustí program sort.

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
  int fds[2];
  pid_t pid;

  /* Vytvori rouru. */
  pipe(fds);
  /* Rozvetvi proces */
  pid = fork();
  if (pid == (pid_t) 0){
    /* Toto je detsky proces. Uzavre svoji kopii konce roury pro zapis. */
    close(fds[1]);
    /* Spoji konec roury pro cteni se standardnim vstupem. */
    dup2(fds[0], STDIN_FILENO);
    execlp("sort", "sort", 0);
  }
  else{
    /* Toto je rodicovsky proces. */
    FILE *stream;
    /* Uzavre svoji kopii pro cteni. */
    close(fds[0]);
    /* Konvertuje deskriptor souboru pro zapis na objekt typu FILE a zapisuje do nej. */
    stream = fdopen(fds[1], "w");
    fprintf(stream, "Jedna dva tri ctyri pet\n");
    fprintf(stream, "To je jen pokus\n");
    fprintf(stream, "a b c d e f g h i j k l m n\n o p q r s t u v w x y z\n");
    fflush(stream);
    close(fds[1]);
    /* Cekani na ukonceni detskeho procesu. */
    waitpid(pid, NULL, 0);
  }
  return(0);
} 

Funkce popen() a pclose()

Běžné použití datových kolon(rour) spočívá ve výše uvedeném posílání dat mezi spřízněnými procesy. Funkce popen() a pclose()zjedno­dušují celý postup a odstraňují nutnost použít funkce pipe, fork, dup2 a fdopen.

#include <stdio.h>
#include <unistd.h>

int main()
{
  FILE *stream = popen("sort", "w");
  fprintf(stream, "Jedna dva tri ctyri pet\n");
  fprintf(stream, "To je jen pokus\n");
  fprintf(stream, "a b c d e f g h i j k l m n\n o p q r s t u v w x y z\n");
  return(pclose(stream));
} 

Tento program je o poznání kratší než předchozí příklad. Volání funkcepopen() vytváří podřízený proces, který spustí příkaz sort. Druhý argument funkce(„w“) říká, že nadřízený proces bude do vytvářeného procesu zapisovat. Funkce vrací jeden konec datové kolony, druhý je spojen se standardním vstupem podřízeného procesu. Po dokončení zápisu funkce pclose() uzavře proud dat podřízeného procesu, počká, až se podřízený proces ukončí, a pak se sama vrátí se svým návratovým kódem.

Pokud potřebujete komunikovat s nepřízněným procesem, můžete použít datovou kolonu FIFO (first in, first out), která má své jméno v souborovém systému (chová se jako soubor). Proto může takovouto kolonu používat každý proces (pokud má patřičná práva). Tato roura se někdy také nazývá pojmenovaná datová kolona. Jestliže potřebujete používat rouru FIFO, doporučuji, abyste se podívali do manuálových stránek (man 4 fifo).

Pár slov závěrem

Dámy a pánové, pomalu ale jistě se blížíme k cíli. Podle svého vědomí a svědomí jsem do této série umístil vše, co by začínající programátor v Linuxu mohl potřebovat ke svému životu, a doufám, že jste téhož názoru. Všechny příklady jsou ze skvělé knihy „Pokročilé programování v operačním systému Linux“ od autorů Marka Mitchella, Jeffreye Oldhama a Alexe Samuela. A jelikož nejsem zas tak VELKÝM mistrem slohu, vypujčil jsem si občas od autorů pár slov. Doufám, že se někdy zase sejdeme u nějakého mého článku. A jak říká jeden můj přítel: „Díky-Čau“.

Ke stažení je archiv celého seriálu.

Našli jste v článku chybu?
10. 8. 2004 9:33
pc (neregistrovaný)

To je taky duvod, proc se na spousteni noveho programu pouziva vfork().

10. 8. 2004 7:28
Marek Paška (neregistrovaný)

Vyjádříl jsem se poněkud něpřesně (totiž blbě). Paměť se kopírovat nemusí, ale musí se kopírovat adresáře stránek. A tato režie taky není zanedbatelná.