Ciele
- Zistiť, ako fungujú rúry
- Naučiť sa pracovať s nepomenovanými rúrami
- Naučiť sa pracovať s pomenovanými rúrami
- Po prejdení scenára prosím vyplnte dotazník
Postup
Krok 1: Rúry
Príprava
Pre prácu na cvičení si stiahnite súbor k cvičeniu.
Obsah súboru:
.
└── 06
├──u1_1.c
├──Makefile
└──tests
└──u1_1_test.sh
Úvod
Jedná sa o najstarší komunikačný mechanizmus vo všetkých typoch UNIX-ov.
Existujú: - nepomenované rúry - umožňujú komunikovať len príbuzným procesom. - pomenované rúry - umozňujú komunikáciu aj procesom, ktoré nie sú príbuzné.
Krok 2: Nepomenované rúry
Teória
Umožňujú komunikáciu medzi dvoma procesmi, ktoré musia byť vzájomne príbuzné. To znamená, že medzi nimi musí byť vzťah typu rodič-potomok aj keď sa nemusí jednať o bezprostredného potomka.
Princíp komunikácie pomocou nepomenovaných rúr
Údaje sa zapisujú na zapisovacom konci rúry a následne sú prečítané na čítacom konci. Jedná sa o sériovú komunikáciu - v takom poradí, v akom boli údaje zapísané na jednom konci sú na druhom prečítané.
Nevýhody:
- jednosmerný tok dát
- komunikácia len medzi príbuznými procesmi (vytvorené rúry zdedí každý potomok)
- jedná sa o samosynchronizujúci prostriedok ale len v prípade jedného volania jadra pre čítanie. Ak sa čítanie rozdelí na viac volaní, tak môže dochádzať ku konfliktom medzi procesmi.
Krok 3: Pomenované rúry (FIFO)
Teória
Pomenované rúry majú podobné správanie ako nepomenované ale existujú ako záznam v súborovom systéme. Vďaka tomu vedia k ním prístupovať procesy na základe mena tohto súboru.
Poznámka
Na rozdiel od nepomenovaných rúr, pomenované rúry môžu využívať aj procesy, ktoré sú navzájom nezávislé (nejedná sa o rodičovské procesy a ich potomkov).
FIFO musí byť otvorené na oboch koncoch (zápis aj čítanie) predtým než môže odovzdávať dáta. V prípade, že nie je, tak je blokované.
Služba jadra mkfifo()
Služba jadra mkfifo() slúži na vytvorenie pomenovanej rúry.
#include <sys/type.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
Parametere | |
---|---|
const char *pathname | názov súboru, ktorý bude slúžiť ako referenčný bod, ktorým procesy môžu pristupovať k rúre |
mode_t mode | prístupové práva |
Návratová hodnota |
---|
Pri úspešnom vykonaní vráti 0 |
Pri chybe -1. |
Úloha 3.1
Pre podrobnejšie vysvetlenie služby mkfifo() navštívte manuál man 2 mkfifo
Príklad použitia:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(){
int des_fifo;
des_fifo = mkfifo("/tmp/my_fifo", 0777);
printf("Hodnota premennej des_fifo je %d\n", des_fifo);
if(des_fifo==0){
printf("Uspesne sa podarilo vytvorit FIFO.\n");
}
else{
perror("Chyba:");
}
return 0;
}
Opis kódu:
Najprv sa vytvorí pomenovaná rúra s názvom my_fifo prostredníctvom služby mkfifo(). Následne program vypíše v prípade úspešného vykonania "Uspesne sa podarilo vytvorit FIFO.".
Výstup z programu:
des_fifo je 0
Uspesne sa podarilo vytvorit FIFO
Záznam o vytvorení rúry sa dá nájsť pomocou:
ls -lF /tmp/my_fifo
Výpis vyzerá priblížne takto: (u každého sa bude líšiť)
prwxr-xr-x 1 ab123yz tuke 0 Jan 10 10:10 /tmp/my_fifo|
Na začiatku výpisu sa nachádza písmeno p
. To znamená, že sa jedná o rúru. Symbol |
na konci sa nachádza kvôli voľbe F príkazu ls a tiež označuje rúru.
Poznámka
V prípade, že program spustíte opäť, tak nedôjde k vytvoreniu rúry, pretože už v systéme existuje. Výstup v tom prípade bude:
des_fifo je -1
Chyba:: File exists
Vytvorenú rúru je možné odstrániť pomocou služby jadra unlink(). V prípade, aký bol uvedený v príklade použitia, je potrebné zadať:
unlink /tmp/my_fifo
Prístup k pomenovanej rúre
Pomenované rúry sú súčasťou súborového systému. Vďaka tomu je možné ich používať v príkazoch na mieste, kde sa bežne používa názov súboru.
Rozdiel medzi nepomenovanou a pomenovanou rúrou
Pomenovaná rúra | Nepomenovaná rúra |
---|---|
existuje v podobe pomenovaného súboru | existuje ako otvorený deskriptor súboru |
je potrebné ju otvárať pred tým, ako sa do/z nej zapisujú/čítajú dáta | dá sa s ňou pracovať len v aktuálnom procese, alebo v procese potomka |
Pomenovaná rúra sa otvára/zatvára rovnakými funkciami open()/close(), ktoré boli použité pri otváraní/zatváraní súborov.
Záverečná úloha
Úloha 3.2
Vytvorte program, ktorý príjme ako argument reťazec znakov (ten sa automaticky uloží ako argv[1]).
Následne si vytvorí pomenovanú rúru pomocou funkcie make_fifo()
. K tejto rúre bude pristupovať pomocou deskriptoru (návratová hodnota funkcie make_fifo()
) uloženého pod premennou file_descriptor vo funkciách write_fifo()
a read_fifo()
.
Návratovou hodnotou funkcií write_fifo() a read_fifo() je počet zapísaných/prečítaných bytov.
Vo funkcií main()
po vytvorení pomenovanej rúry zapíšte do tejto rúry reťazec znakov a následne ho aj z tejto rúry prečítajte a vypíšte na štandardný výstup.
Kostra úlohy:
fifo_ex1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PATHNAME "/tmp/my_fifo"
int make_fifo(char* pathname);
int write_fifo(int file_descriptor, char* text, int entry_size);
int read_fifo(int file_descriptor, char* buffer, int entry_size);
int main(int argc, char *argv[]){
return 0;
}
int make_fifo(char* pathname){
return 0;
}
int write_fifo(int file_descriptor, char* text, int entry_size){
return 0;
}
int read_fifo(int file_descriptor, char* buffer, int entry_size){
return 0;
}