Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Poprzednia wersja Nowa wersja | Poprzednia wersja | ||
sk2:sockets_concurrency [2024/11/04 22:09] jkonczak [epoll] |
sk2:sockets_concurrency [2024/11/12 11:52] (aktualna) jkonczak |
||
---|---|---|---|
Linia 6: | Linia 6: | ||
Do obsługi wielu źródeł zdarzeń stworzono dedykowane metody, można też używać typowych metod pisania aplikacji współbieżnych. Zwolennicy SE nazwą to "wzorcami projektowymi". Przegląd typowych metod tworzenia aplikacji sieciowych: | Do obsługi wielu źródeł zdarzeń stworzono dedykowane metody, można też używać typowych metod pisania aplikacji współbieżnych. Zwolennicy SE nazwą to "wzorcami projektowymi". Przegląd typowych metod tworzenia aplikacji sieciowych: | ||
* Iteracyjnie – kiedy współbieżność jest zbędna. | * Iteracyjnie – kiedy współbieżność jest zbędna. | ||
- | * Pętla zdarzeń (event loop, [[https://en.wikipedia.org/wiki/Event_loop|[1]]], [[https://web.archive.org/web/20190730174916/https://pl.wikipedia.org/wiki/Programowanie_sterowane_zdarzeniami|[2]]]) – programista wpierw przygotowuje kod (funkcje) obsługi możliwych zdarzeń, następnie w pętli czeka na zdarzenie i wywołuje kod powiązany ze zdarzeniem. Aplikacja może być jedno- lub wielowątkowa, muszą być dostępne funkcje czekające na zdarzenie – dla I/O pod Linuksem to ''select'', ''poll'' i ''epoll''. Praktycznie wszystkie programy z GUI wykorzystują pętlę zdarzeń przynajmniej do obsługi GUI. | + | * Pętla zdarzeń (event loop, [[https://en.wikipedia.org/wiki/Event_loop|[1]]], [[https://web.archive.org/web/20190730174916/https://pl.wikipedia.org/wiki/Programowanie_sterowane_zdarzeniami|[2]]]) – programista wpierw przygotowuje kod (funkcje) obsługi możliwych zdarzeń, następnie w pętli czeka na zdarzenie i wywołuje kod powiązany ze zdarzeniem. Aplikacja może być jedno- lub wielowątkowa, muszą być dostępne funkcje czekające na zdarzenie – dla I/O pod Linuksem to ''select'', ''poll'' i ''epoll''. \\ Praktycznie wszystkie programy z GUI wykorzystują pętlę zdarzeń przynajmniej do obsługi GUI. |
* Aplikacja wielowątkowa – każde źródło zdarzeń – np. gniazdo – jest obsługiwane w osobnym wątku. | * Aplikacja wielowątkowa – każde źródło zdarzeń – np. gniazdo – jest obsługiwane w osobnym wątku. | ||
+ | |||
====== Wiele wątków ====== | ====== Wiele wątków ====== | ||
[[sk2:cpp11_threads|Wątki w C++]] | [[sk2:cpp11_threads|Wątki w C++]] | ||
- | //Zadanie 1.// Napisz własną wersję programu ''netcat'' wspierającą tylko klienta TCP – program, który nawiąże połączenie TCP pod wskazany adres, następnie dane przychodzące na standardowe wejście będzie wysyłać przez to połączenie, a dane które przyszły z sieci wypisze na standardowe wyjście.\\ (Możesz skorzystać z {{:sk2:tcp_client_template.cpp|przykładowego kodu}}) | + | ~~Zadanie.#~~ Napisz własną wersję programu ''netcat'' wspierającą tylko klienta |
+ | TCP – program, który nawiąże połączenie TCP pod wskazany adres, następnie dane | ||
+ | przychodzące na standardowe wejście będzie wysyłać przez to połączenie, a | ||
+ | równocześnie dane przychodzące z sieci będzie wypisywać na standardowe wyjście. | ||
+ | \\ | ||
+ | (Możesz skorzystać z {{:sk2:tcp_client_template.cpp|przykładowego kodu klienta}}) | ||
- | //Zadanie 2.// Czat – napisz serwer, który każdą otrzymaną wiadomość przekaże wszystkim połączonym klientom. \\ | + | ~~Zadanie.#~~ Czat – napisz serwer, który każdą otrzymaną wiadomość przekaże |
- | (Możesz skorzystać z {{:sk2:tcp_server_template.cpp|przykładowego kodu}}) | + | wszystkim połączonym klientom. |
+ | \\ | ||
+ | (Możesz skorzystać z {{:sk2:tcp_server_template.cpp|przykładowego kodu serwera}}) | ||
====== Zdarzenia ====== | ====== Zdarzenia ====== | ||
Linia 22: | Linia 30: | ||
System Linux zawiera 3 podstawowe funkcje pozwalające na czekanie na przychodzące zdarzenia na deskryptorach plików: | System Linux zawiera 3 podstawowe funkcje pozwalające na czekanie na przychodzące zdarzenia na deskryptorach plików: | ||
* ''select'' – "klasyczna" funkcja, ma kilka dziwnych ograniczeń. Dostaje zbiór deskryptorów, oczekuje na zdarzenie, modyfikuje przekazany zbiór deskryptorów zostawiając tylko te na których można wykonać read/write/lub na których wystąpił wyjątek. (POSIX) | * ''select'' – "klasyczna" funkcja, ma kilka dziwnych ograniczeń. Dostaje zbiór deskryptorów, oczekuje na zdarzenie, modyfikuje przekazany zbiór deskryptorów zostawiając tylko te na których można wykonać read/write/lub na których wystąpił wyjątek. (POSIX) | ||
- | * ''poll'' – zbudowana podobnie jak ''select'', ale m.inn. nie ma ograniczenia na numery monitorowanych deskryptorów((Patrz [[https://man7.org/linux/man-pages/man2/select.2.html|man 2 select]].)), można użyć ponownie struktury opisującej deskryptory etc. (POSIX) | + | * ''poll'' – zbudowana podobnie jak ''select'', ale m. inn. nie ma ograniczenia na numery monitorowanych deskryptorów((Patrz [[https://man7.org/linux/man-pages/man2/select.2.html|man 2 select]].)), można użyć ponownie struktury opisującej deskryptory etc. (POSIX) |
- | * ''epoll'' – specyficzna dla Linuksa funkcja. Inny pomysł: program informuje jądro systemu na które deskryptory chce czekać, potem wywołuje funkcję czekającą na zdarzenie i dostaje deskryptory które są gotowe do pracy. | + | * ''epoll'' – specyficzna dla Linuksa funkcja. Inny pomysł: program informuje jądro systemu na które deskryptory chce czekać, potem wywołuje funkcję czekającą na zdarzenie i dostaje informacje które zarzenia wystąpiły. |
Dłuższe porównanie: http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/ | Dłuższe porównanie: http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/ | ||
Linia 31: | Linia 39: | ||
Aby stworzyć program korzystający z funkcji ''poll'', należy:<html><div style="margin-top:-1.4em"></div></html> | Aby stworzyć program korzystający z funkcji ''poll'', należy:<html><div style="margin-top:-1.4em"></div></html> | ||
- | - dodać plik nagłówkowy ''poll.h'' | ||
- przygotować tablicę struktur ''pollfd'' i wypełnić: | - przygotować tablicę struktur ''pollfd'' i wypełnić: | ||
* ''.fd'' – deskryptor pliku do monitorowania, | * ''.fd'' – deskryptor pliku do monitorowania, | ||
Linia 41: | Linia 48: | ||
- w pętli wywoływać funkcję ''poll(…)''. \\ <small>ostatni argument funkcji ''poll'' to maksymalny czas oczekiwania; aby funkcja czekała bez limitu, należy podać tam dowolną ujemną wartość</small> | - w pętli wywoływać funkcję ''poll(…)''. \\ <small>ostatni argument funkcji ''poll'' to maksymalny czas oczekiwania; aby funkcja czekała bez limitu, należy podać tam dowolną ujemną wartość</small> | ||
- sprawdzać który deskryptor jest gotowy przeglądając pola ''.revents'' | - sprawdzać który deskryptor jest gotowy przeglądając pola ''.revents'' | ||
+ | |||
+ | Funkcja ''poll'', struktura ''pollfd'' i stałe ''POLL…'' są w pliku nagłówkowym ''#include <poll.h>'' | ||
<html> | <html> | ||
Linia 46: | Linia 55: | ||
<span title="Tablica struktur 'pollfd' opisująca na których plikach i na co czekać" style="background-color:#fb02">pollfd pfds<span class="br0">[</span>COUNT<span class="br0">]</span><span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span></span> <span style="color:grey">─┐</span> | <span title="Tablica struktur 'pollfd' opisująca na których plikach i na co czekać" style="background-color:#fb02">pollfd pfds<span class="br0">[</span>COUNT<span class="br0">]</span><span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span></span> <span style="color:grey">─┐</span> | ||
<span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002">pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> STDIN_FILENO<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span title="'fd' wskazuje na którm pliku czekać na zdarzena, a 'events' określa na które zdarzenia na wskazanym pliku" style="background-color:#0f02">.<span class="me1">fd</span> <span class="sy1">=</span></span> cliSock1<span class="sy4">;</span> <span style="color:grey">│</span> | <span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002">pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> STDIN_FILENO<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span title="'fd' wskazuje na którm pliku czekać na zdarzena, a 'events' określa na które zdarzenia na wskazanym pliku" style="background-color:#0f02">.<span class="me1">fd</span> <span class="sy1">=</span></span> cliSock1<span class="sy4">;</span> <span style="color:grey">│</span> | ||
- | <span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002">pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> POLLIN<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span title="'fd' wskazuje na którm pliku czekać na zdarzena, a 'events' określa na które zdarzenia na wskazanym pliku" style="background-color:#0f02">.<span class="me1">events</span> <span class="sy1">=</span></span> POLLIN<span class="sy4">;</span> <span style="color:grey">├─ (2)</span> | + | <span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002">pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> POLLIN<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span title="'fd' wskazuje na którm pliku czekać na zdarzena, a 'events' określa na które zdarzenia na wskazanym pliku" style="background-color:#0f02">.<span class="me1">events</span> <span class="sy1">=</span></span> POLLIN<span class="sy4">;</span> <span style="color:grey">├─ (1)</span> |
<span title="Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania" style="background-color:#00f2">pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> serverSock<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> cliSock2<span class="sy4">;</span> <span style="color:grey">│</span> | <span title="Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania" style="background-color:#00f2">pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> serverSock<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span>.<span class="me1">fd</span> <span class="sy1">=</span> cliSock2<span class="sy4">;</span> <span style="color:grey">│</span> | ||
<span title="Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania" style="background-color:#00f2">pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> POLLIN<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> <span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4">POLLIN</span><span class="sy3">|</span><span title="Jeśli zostanie podane POLLOUT, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'write' (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)" style="background-color:#ff04">POLLOUT</span><span class="sy4">;</span> <span style="color:grey">─┘</span> | <span title="Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania" style="background-color:#00f2">pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> POLLIN<span class="sy4">;</span></span> pfds<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span>.<span class="me1">events</span> <span class="sy1">=</span> <span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4">POLLIN</span><span class="sy3">|</span><span title="Jeśli zostanie podane POLLOUT, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'write' (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)" style="background-color:#ff04">POLLOUT</span><span class="sy4">;</span> <span style="color:grey">─┘</span> | ||
Linia 54: | Linia 63: | ||
<span class="kw4">int</span> ile_gotowych <span class="sy1">=</span> poll<span class="br0">(</span><span title="Tablica struktur 'pollfd' opisująca na których plikach i na co czekać" style="background-color:#fb02">pfds</span>, <span title="Wskazuje ile struktur pod wskaźnikiem 'pfds' ma odczytać funkcja 'poll'" style="background-color:#f082">liczbaStruktur</span>, <span title="Limit czasu oczekiwania na pierwsze zdarzenie: | <span class="kw4">int</span> ile_gotowych <span class="sy1">=</span> poll<span class="br0">(</span><span title="Tablica struktur 'pollfd' opisująca na których plikach i na co czekać" style="background-color:#fb02">pfds</span>, <span title="Wskazuje ile struktur pod wskaźnikiem 'pfds' ma odczytać funkcja 'poll'" style="background-color:#f082">liczbaStruktur</span>, <span title="Limit czasu oczekiwania na pierwsze zdarzenie: | ||
nieujemna wartość: maksymalny czas czekania w milisekundach, | nieujemna wartość: maksymalny czas czekania w milisekundach, | ||
- | ujemna wartość: czekanie bez limitu czasowego" style="background-color:#0002"><span class="sy2">-</span><span class="nu0">1</span></span><span class="br0">)</span><span class="sy4">;</span> <span style="color:grey">═╾─ (3)</span> | + | ujemna wartość: czekanie bez limitu czasowego" style="background-color:#0002"><span class="sy2">-</span><span class="nu0">1</span></span><span class="br0">)</span><span class="sy4">;</span> <span style="color:grey">═╾─ (2)</span> |
<span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLIN<span class="br0">)</span> readingFromStdin<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span></span> <span style="color:grey">─┐</span> | <span title="poll() może monitorować dowolne pliki, np. standardowe wejście" style="background-color:#f002"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLIN<span class="br0">)</span> readingFromStdin<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span></span> <span style="color:grey">─┐</span> | ||
<span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span title="poll() wypełnia pole .revents, wpisując tam identyfikatory wszystkich zdarzeń które wystąpiły na pliku" style="background-color:#0f42">.<span class="me1">revents</span> <span class="sy3">&</span></span> POLLIN<span class="br0">)</span> acceptingNewClient<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span style="color:grey">│</span> | <span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span title="poll() wypełnia pole .revents, wpisując tam identyfikatory wszystkich zdarzeń które wystąpiły na pliku" style="background-color:#0f42">.<span class="me1">revents</span> <span class="sy3">&</span></span> POLLIN<span class="br0">)</span> acceptingNewClient<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span style="color:grey">│</span> | ||
<span class="kw1">for</span><span class="br0">(</span><span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> i <span class="sy1"><</span> liczbaStruktur<span class="sy4">;</span> <span class="sy2">++</span>i<span class="br0">)</span><span class="br0">{</span> <span style="color:grey">│</span> | <span class="kw1">for</span><span class="br0">(</span><span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> i <span class="sy1"><</span> liczbaStruktur<span class="sy4">;</span> <span class="sy2">++</span>i<span class="br0">)</span><span class="br0">{</span> <span style="color:grey">│</span> | ||
- | <span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLIN<span class="br0">)</span></span> <span style="color:grey">├─ (4)</span> | + | <span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLIN<span class="br0">)</span></span> <span style="color:grey">├─ (3)</span> |
<span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4">readFromClient<span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">fd</span><span class="br0">)</span><span class="sy4">;</span></span> <span style="color:grey">│</span> | <span title="Jeśli zostanie podane POLLIN, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'read' (w buforze są dane lub wystąpił błąd na gnieździe)" style="background-color:#0ff4">readFromClient<span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">fd</span><span class="br0">)</span><span class="sy4">;</span></span> <span style="color:grey">│</span> | ||
<span title="Jeśli zostanie podane POLLOUT, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'write' (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)" style="background-color:#ff04"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLOUT<span class="br0">)</span></span> <span style="color:grey">│</span> | <span title="Jeśli zostanie podane POLLOUT, to 'poll()' zakończy się kiedy tylko będzie dało się bez czekania wykonać 'write' (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)" style="background-color:#ff04"><span class="kw1">if</span><span class="br0">(</span>pfds<span class="br0">[</span>i<span class="br0">]</span>.<span class="me1">revents</span> <span class="sy3">&</span> POLLOUT<span class="br0">)</span></span> <span style="color:grey">│</span> | ||
Linia 68: | Linia 77: | ||
</html> | </html> | ||
- | //Zadanie 3.// Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący ''poll''. | + | ~~Zadanie.#~~ Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący ''poll''. |
+ | \\ | ||
+ | (Możesz skorzystać z {{:sk2:tcp_client_template.cpp|przykładowego kodu klienta}}) | ||
===== epoll ===== | ===== epoll ===== | ||
Linia 76: | Linia 88: | ||
- Funkcja czekająca na zdarzenia – ''epoll_wait'' – przyjmuje jako argumenty tylko deskryptor utworzony przez ''epoll_create'', tablicę zdarzeń do wypełnienia i czas oczekiwania (-1 = nieskończoność). \\ | - Funkcja czekająca na zdarzenia – ''epoll_wait'' – przyjmuje jako argumenty tylko deskryptor utworzony przez ''epoll_create'', tablicę zdarzeń do wypełnienia i czas oczekiwania (-1 = nieskończoność). \\ | ||
- ''epoll_wait'' nie przekazuje numerów gotowych deskryptorów – przekazuje tylko rodzaj zdarzenia i powiązane z nim wcześniej dane. | - ''epoll_wait'' nie przekazuje numerów gotowych deskryptorów – przekazuje tylko rodzaj zdarzenia i powiązane z nim wcześniej dane. | ||
- | Plik nagłówkowy: ''#include <sys/epoll.h>'' | + | Funkcje ''epoll_…'', struktura ''epoll_event'' i stałe ''EPOLL…'' są w pliku nagłówkowym ''#include <sys/epoll.h>'' |
<html> | <html> | ||
Linia 99: | Linia 111: | ||
<span title="'epoll_ctl' zarządza listą zdarzeń które monitoruje wskazany plik epoll: | <span title="'epoll_ctl' zarządza listą zdarzeń które monitoruje wskazany plik epoll: | ||
z flagą EPOLL_CTL_ADD dodaje nowy plik, | z flagą EPOLL_CTL_ADD dodaje nowy plik, | ||
- | z flagą EPOLL_CTL_DEL przestaje monitorować wskzany plik, | + | z flagą EPOLL_CTL_DEL przestaje monitorować wskazany plik, |
z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="background-color:#f0f2">epoll_ctl</span><span class="br0">(</span>epollDescr, <span title="'epoll_ctl' zarządza listą zdarzeń które monitoruje wskazany plik epoll: | z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="background-color:#f0f2">epoll_ctl</span><span class="br0">(</span>epollDescr, <span title="'epoll_ctl' zarządza listą zdarzeń które monitoruje wskazany plik epoll: | ||
z flagą EPOLL_CTL_ADD dodaje nowy plik, | z flagą EPOLL_CTL_ADD dodaje nowy plik, | ||
- | z flagą EPOLL_CTL_DEL przestaje monitorować wskzany plik, | + | z flagą EPOLL_CTL_DEL przestaje monitorować wskazany plik, |
z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="background-color:#f0f2">EPOLL_CTL_ADD</span>, STDIN_FILENO, <span class="sy3">&</span>ee<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="sy4">;</span> │ | z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="background-color:#f0f2">EPOLL_CTL_ADD</span>, STDIN_FILENO, <span class="sy3">&</span>ee<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="sy4">;</span> │ | ||
ee<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">data</span>.<span class="me1">u32</span> <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">2</span><span class="sy4">;</span> │ | ee<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>.<span class="me1">data</span>.<span class="me1">u32</span> <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">2</span><span class="sy4">;</span> │ | ||
Linia 108: | Linia 120: | ||
<span class="kw1">while</span> <span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span> | <span class="kw1">while</span> <span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span> | ||
- | <span title="'epoll_wait' zwraca ile pierwszych struktur z podanej listy wypełnił" style="background-color:#f402"><span class="kw4">int</span> ile_gotowych</span> <span class="sy1">=</span> <span title="'epoll_wait' wpisuje do podanej listy struktur epoll_event listę zdarzeń które wystąpiły na wcześniej zgłoszonych do monitorowania plikach (jeśli trzeba, czekając na pierwsze zdarzenie)" style="background-color:#0ff2">epoll_wait</span><span class="br0">(</span><span title="Wybiera na którym z plików epoll będzie pracować ta funkcja" style="background-color:#0fa2">epollDescr</span>, <span title="wskazuje że wyniki mają trafić do tablicy 'ee' w której są 2 elementy" style="background-color:#8f03">ee, <span class="nu0">2</span></span>, <span title="limit czasu oczekiwania (jak w poll)" style="background-color:#0001"><span class="sy2">-</span><span class="nu0">1</span></span><span class="br0">)</span><span class="sy4">;</span> ═╾─ (3) | + | <span title="'epoll_wait' zwraca ile pierwszych struktur z podanej listy wypełnił" style="background-color:#f402"><span class="kw4">int</span> ile_gotowych</span> <span class="sy1">=</span> <span title="'epoll_wait' wpisuje do podanej listy struktur epoll_event listę zdarzeń które wystąpiły na wcześniej zgłoszonych do monitorowania plikach (jeśli trzeba, czekając na pierwsze zdarzenie)" style="background-color:#0ff2">epoll_wait</span><span class="br0">(</span><span title="Wybiera na którym z plików epoll będzie pracować ta funkcja" style="background-color:#0fa2">epollDescr</span>, <span title="wskazuje że wyniki mają trafić do tablicy 'ee' w której jest miejsce na co najwyżej 2 elementy" style="background-color:#8f03">ee, <span class="nu0">2</span></span>, <span title="limit czasu oczekiwania (jak w poll)" style="background-color:#0001"><span class="sy2">-</span><span class="nu0">1</span></span><span class="br0">)</span><span class="sy4">;</span> ═╾─ (3) |
<span class="kw1">for</span> <span class="br0">(</span><span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> i <span class="sy1"><</span> ile_gotowych<span class="sy4">;</span> <span class="sy2">++</span>i<span class="br0">)</span> <span class="br0">{</span> ─┐ | <span class="kw1">for</span> <span class="br0">(</span><span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> i <span class="sy1"><</span> ile_gotowych<span class="sy4">;</span> <span class="sy2">++</span>i<span class="br0">)</span> <span class="br0">{</span> ─┐ | ||
Linia 192: | Linia 204: | ||
++++ | ++++ | ||
- | //Zadanie 4.// Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący mechanizm epoll. | + | ~~Zadanie.#~~ Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący mechanizm epoll. |
+ | \\ | ||
+ | (Możesz skorzystać z {{:sk2:tcp_client_template.cpp|przykładowego kodu klienta}}) | ||
- | //Zadanie 5.// Napisz jednowątkowy serwer czatu używając ''poll'' lub ''epoll_wait''. | + | ~~Zadanie.#~~ Napisz jednowątkowy serwer czatu używając ''poll'' lub ''epoll_wait''. |
+ | \\ | ||
+ | (Możesz skorzystać z {{:sk2:tcp_server_template.cpp|przykładowego kodu serwera}}) |