Do tematu: Struktury danych
typ | nazwa pola | opis |
int | magic | Liczba magiczna |
struct tty_driver | driver | Sterownik urządzenia terminalowego |
struct tty_ldisc | ldisc | Dyscyplina linii |
struct termios* | termios | Stałe parametry pracy urządzenia terminalowego |
struct termios* | termios_locked | Jeśli proces, wywołując funkcję ioctl, chce zmienić parametry pracy urządzenia terminalowego, tj. zawartość struktury termios, do której wskaźnik pamiętany jest w polu o tej samej nazwie, to przeprowadzenie zmian zależy od zawartości innej struktury termios, a mianowicie tej, do której wskaźnik jest pamiętany w polu termios_locked. Zmiana wartości bitu (ustawienie lub wyzerowanie flagi) w strukturze wskazywanej przez termios jest dokonywana tylko wtedy, gdy odpowiadający bit w strukturze wskazywanej przez termios_locked jest wyzerowany, tzn. dopóki jakiś bit w strukturze *termios_locked jest ustawiony, zmiana wartości odpowiadającego mu bitu w strukturze *termios nie jest możliwa. Aby zmienić zawartość struktury *termios, trzeba najpierw wyzerować odpowiednie bity w strukturze *termios_locked. Zasada ta dotyczy nie tylko flag, ale wszystkich pól struktury termios, a więc również znaków sterujących i dyscypliny linii. |
int | pgrp | Identyfikator grupy terminalowej.
Grupa terminalowa, to grupa procesów, której identyfikator jest równy polu pgrp. Zazwyczaj, chociaż nie zawsze, proces należy do grupy terminalowej swojego terminala sterującego. Terminalem sterującym procesu jest urządzenie terminalowe opisywane przez pole tty w strukturze task_struct. Terminalem sterującym grupy procesów jest pierwsze urządzenie terminalowe otwarte przez przywódcę tej grupy. Zwykle przywódcą grupy procesów jest proces shell, a terminalem sterującym terminal, z którego użytkownik rozpoczął pracę. |
int | session | Identyfikator sesji.
Jest on równy identyfikatorowi sesji przywódcy grupy terminalowej danego terminala. |
kdev_t | device | Numer urządzenia |
unsigned long | flags | Flagi |
int | count | Liczba otwartych plików specjalnych, umożliwiających
dostęp do danego urządzenia terminalowego.
Licznik ten jest zwiększany podczas otwierania urządzenia terminalowego (w funkcji init_dev() zdefiniowanej w pliku tty_io.c), zmniejszany podczas zamykania (w funkcji release_dev()). W przypadku pseudoterminali otwieranie polega na otwarciu części nadrzędnej i podrzędnej. Odbywa się to podczas pojedynczego wykonania funkcji init_dev(). Wówczas zwiększana jest o jeden wartość licznika count w części podrzędnej. Ponieważ część nadrzędna nie może być otwarta przez więcej niż jeden proces na raz, wartość licznika count w części podrzędnej jest zawsze o jeden większa od liczby odpowiadających jej otwartych plików specjalnych. Takie postępowanie zapewnia, że część podrzędna zamykana jest tylko wówczas, gdy zamykana jest jej część nadrzędna. |
struct winsize | winsize | Wymiary okna dla terminali |
unsigned char | stopped: 1, hw_stopped: 1, packet: 1 | Pole stopped ma wartość 1, jeśli urządzenie terminalowe jest zatrzymane,
wartość 0, jeśli nie jest zatrzymane. Mówimy, że urządzenie jest zatrzymane,
jeśli w wyniku wprowadzenia przez użytkownika znaku
zatrzymania, sterownik przestał wysyłac dane do terminala. Po nadejściu
znaku rozpoczęcia, dane ponownie będą
wysyłane.
Pole hw_stopped (ang. hardware stopped) ma wartość 1, jeśli urządzenie terminalowe jest zatrzymane, wartość 0, jeśli nie jest zatrzymane. Pole to jest używane, jeśli dostępne jest sprzętowe sterowanie przepływem danych. Pole packet używane jest, gdy urządzenie terminalowe jest częścią nadrzędną pseudoterminala. Proces może przełączyć tryb pracy pseudoterminala na pakietowy wywołując funkcje ioctl z poleceniem TIOCPKT. Wówczas pole packet otrzymuje wartość 1. Praca w trybie pakietowym polega na przekazywaniu procesom pewnych informacji dotyczących części podrzędnej pseudoterminala. Jeśli proces wykonuje funkcję read w odniesieniu do części nadrzędnej pseudoterminala, to w pierwszym bajcie bufora umieszczana zostaje informacja. Jeśli bajt ten ma wartość zero, to wczytane zostały dane. Jeśli ma wartość różną od zera, to wczytany został tylko ten jeden bajt. Wartości, które może przyjmować są zdefiniowane w postaci flag. Znaczenie flag podane zostało przy opisie pola ctrl_status. |
unsigned char | ctrl_status | Pole to służy do pamiętania stanu części podrzędnej pseudoterminala, o ile odpowiadająca jej część nadrzędna pracuje w trybie pakietowym. Jeśli użytkownik wykonuje operację czytania z części nadrzędnej pseudoterminala, to pierwszemu bajtowi bufora w przestrzeni użytkownika jest nadawana wartość pola ctrl_status. Wartości poszczególnych bitów tego pola odpowiadają ustawieniu, bądź wyzerowaniu odpowiednich flag. |
struct tty_struct * | link | Jeśli struktura tty_struct opisuje urządzenie, które jest jedną z części pseudoterminala, to zmienna link jest wskaźnikiem na drugi element pary. |
struct fasync_struct* | fasync | Lista plików |
tty_flip_buffer | flip | Bufor sterownika urządzenia terminalowego |
int | max_flip_cnt | Obecnie nieużywany |
struct wait_queue* | write_wait | Kolejka procesów czekających na pisanie do urządzenia terminalowego |
struct wait_queue* | read_wait | Kolejka procesów czekających na czytanie z urządzenia terminalowego |
void * | disc_data | W polu tym zapamiętują prywatne dane niektóre sterowniki sieciowe |
void * | driver_data | Służy do zapamiętywania prywatnych danych sterowników urządzeń terminalowych. Zazwyczaj sterownik opisywany jest przez pewną strukturę, której definicja zależy ściśle od rodzaju urządzenia. Np. dla konsoli zdefiniowana jest struktura vt_struct, dla pseudoterminali pty_struct. Wówczas wskaźnik do takiej struktury pamiętany jest w polu driver_data. |
Pola używane przez dyscyplinę linii N_TTY
(Ze względów historycznych stanowią część struktury tty_struct) |
||
unsigned int | column | liczba mówiąca, w której kolumnie będziemy wypisywać bieżący znak na terminal |
unsigned char | lnext:1 | mówi, czy poprzednio otrzymanym przez dysc. linii znakiem był znak VLNEXT (literal next) |
unsigned char | erasing:1 | mówi, czy aktualnie jesteśmy w trybie obsługi znaków ścierania |
unsigned char | raw:1, real_raw:1 | raw - wartość 1 oznacza, że terminal jest w trybie surowym (nie przetwarzane
są znaki końca linii, ścierające), ale że znaki powodujące wysyłanie sygnałów
są obsługiwane. raw jest ustawiany na 1 lub 0 w zależności od tego, jakie
flagi są związane z terminalem.
real_raw - wartość 1 oznacza, że dyscyplina linii nie będzie obsługiwać żadnych znaków specjalnych (nie będzie też możliwe wysyłanie sygnałów za pomocą znaków z klawiatury). Parametr ten jest ustawiany na 1, jeśli m.in. włączone są następujące flagi: IGNBRK, IGNPAR, oraz driver terminala ma ustawioną flagę TTY_DRIVER_REAL_RAW |
unsigned char | icanon:1 | ustawione na 1, jeśli terminal pracuje w trybie kanonicznym, czyli znaki wejściowe są przetwarzane, jest obsługa końca linii, znaków ścierających. icanon jest ustawiane na 1, m.in jeśli jest ustawiona flaga ICANON |
unsigned char | closing:1 | mówi, czy jesteśmy w trakcie zamykania dyscypliny linii |
unsigned short | minimum_to_wake | ilość znaków w buforze wystarczająca, aby obudzić procesy czekające na czytanie z terminala (patrz pole read_wait) |
unsigned | overrun_time | czas, w którym przybył pierwszy z serii znak z flagą TTY_OVERRUN |
int | num_overrun | ile znaków w ciągu HZ tyknięć zegara przybyło z flagą TTY_OVERRUN |
unsigned long | process_char_map [256/(8*sizeof(unsigned long)) ] | tej tablicy używa się tylko wtedy, gdy terminal nie jest w trybie surowym (raw = 0, real_raw = 0). Tablica ta traktowana jest jak ciąg bitów. Te bity sprawdza się i ustawia. Bit o numerze odpowiadającym znakowi sterującemu jest ustawiony, jeśli ten znak jest obsługiwany przez terminal (o czym mówią flagi). Wypełnianie tej tablicy jest dokonywane w funkcji n_tty_set_termios, która jest też wywoływana przy otwieraniu dyscypliny linii N_TTY |
char * | read_buf | bufor dyscypliny linii, jest alokowany dynamicznie podczas wywołania funkcji open dla dysc.linii. Bufor jest traktowany jak cykliczna kolejka znaków |
int | read_head | pozycja w buforze char_buf, gdzie znajduje się początek danych |
int | read_tail | pozycja w char_buf oznaczająca, że tam jest koniec danych |
int | read_cnt | ilość znaków znajdująca się w buforze |
unsigned long | read_flags [N_TTY_BUF_SIZE/(8* sizeof(unsigned long)) ] | traktuje się tę tablicę jak ciąg bitów. Bity ustawia się na 1, jeśli na pozycji równej numerowi tego bitu w tablicy read_buf znajduje się koniec linii (ostatni znak w linii). Przy otwieraniu dyscypliny linii tablica jest zerowana |
Następujące pola używane są tylko wtedy, kiedy icanon = 1 | ||
int | canon_data | liczba znaków buforowanych w read_buf |
unsigned long | canon_head | mówi gdzie jest początek znaków obsługiwanych w trybie kanonicznym (bufor read_buf) |
unsigned int | canon_column | numer kolumny (tryb kanoniczny) |
Liczba magiczna (ang. magic number) jest unikatową liczbą, przypisywaną do typu struct, pozwalającą zidentyfikować dany typ. Przykładowe definicje dla tty_struct, tty_driver oraz tty_ldisc są następujące:
TTY_MAGIC 0x5401
TTY_DRIVER_MAGIC 0x5402
TTY_LDISC_MAGIC 0x5403
Liczby magiczne są przede wszystkim definiowane po to, aby ułatwić wykrywanie błędów w kodzie jądra. Szczególnie przydatne okazują się tam, gdzie mamy do czynienia z wielokrotnym przekazywaniem i rzutowaniem wskaźników do struktur. Dzięki liczbom magicznym możemy w prosty sposób sprawdzać poprawność przekazywanych do funkcji wskaźników.
Jeśli rozbudowujemy kod jądra, dodając m. in. nową strukturę i chcemy skorzystać z pomysłu magicznych liczb, to definiujemy swoją liczbę magiczną, a pierwszemu polu naszej struktury nadajemy nazwę magic i typ int. Wartością tego pola, nadawaną przy inicjalizacji, zawsze powinna być zdefiniowana przez nas liczba magiczna.
Dobry obyczaj wymaga, abyśmy swoją liczbę magiczną umieścili w pliku magic-number.txt, gdzie znajdują się wszystkie definicje liczb magicznych. Takie postępowanie pozwala zachować unikalność tych liczb.
Numer urządzenia jest liczbą dodatnią. Liczba ta, zdefiniowana dla każdego urządzenia, jednoznacznie identyfikuje urządzenie w systemie operacyjnym Linux. Typ kdev_t jest zdefiniowany następująco:
typedef unsigned short kdev_t;
Numer urządzenia może zostać utworzony tylko w wyniku wykonania makra MKDEV.
#define MINORBITS 8
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
Makro to koduje numer główny i drugorzędny urządzenia w jednej liczbie (nazwy argumentów makra, ma oraz mi, są skrótami angielskich słów major - główny oraz minor - drugorzędny). Często używanymi makrami operującymi na numerze urządzenia są MAJOR i MINOR
#define MINORMASK ((1 << MINORBITS) - 1)
#define MAJOR(dev) ((dev) >> MINORBITS)
#define MINOR(dev) ((dev) & MINORMASK)
Obliczają one odpowiednio numer główny i drugorzędny urządzenia o numerze dev (ang. device - urządzenie). Definicje te znajdują się w pliku kdev_t.h.
flaga | kod | komentarz |
TTY_THROTTLED | 0 | (ang. throttle - dusić) Jeśli jest ustawiona oraz w wejściowym buforze znaków dyscypliny linii znajduje się mniej niż TTY_THRESHOLD_UNTHROTTLE znaków, to dyscyplina linii wywołuje, zdefiniowaną w sterowniku urządzenia terminalowego, funkcję unthrottle. W ten sposób powiadamia urządzenie, że jest już miejsce w buforze wejściowym na przyjęcie kolejnych znaków. Jeśli nie jest ustawiona i w wejściowym buforze znaków znajduje się więcej niż TTY_THRESHOLD_THROTTLE znaków, to wywoływana jest funkcja throttle. Jest to wiadomość dla sterownika, że bufor wejściowy dyscypliny linii jest bliski przepełnienia. Np. w przypadku pseudoterminali ostatnią instrukcją funkcji unthrottle jest ustawienie flagi TTY_THROTTLED. Powoduje to, że dyscyplina linii wywołuje funkcję unthrottle za każdym razem, gdy w kolejce wejściowej jest mniej niż TTY_THRESHOLD_UNTHROTTLE znaków. Można wówczas obudzić procesy, które czekają, aby wysłać dane do pseudoterminala lub żeby dane zostały z pseudoterminala wysłane. |
TTY_IO_ERROR | 1 | Ustawiona informuje o wystąpieniu błedu wejścia-wyjścia. |
TTY_OTHER_CLOSED | 2 | Dotyczy pseudoterminali. Ustawiona informuje, że drugi element pary wchodzący w skład pseudoterminala (wskaźnik do opisującej go struktury tty_struct jest pamiętany w polu link) jest zamknięty (zawieszony). |
TTY_EXCLUSIVE | 3 | Procesy mogą zmieniać ustawienia flagi TTY_EXCLUSIVE za pomocą funkcji ioctl. Jeśli flaga ta zostanie dla jakiegoś urządzenia terminalowego ustawiona, to z wyjątkiem procesów nadzorcy, żaden proces nie będzie już mógł otworzyć tego urządzenia. Nie oznacza to wyłączności korzystania przez proces z urządzenia, ponieważ np., zanim flaga została ustawiona, inne procesy mogły już otworzyć to urządzenie. |
TTY_DEBUG | 4 | Obecnie nieużywana |
TTY_DO_WRITE_WAKEUP | 5 | Flaga ta testowana jest, przede wszystkim, w tych funkcjach sterowników, które wysyłają dane do urządzenia terminalowego (np. write, flush_buffer). Jeśli jest ustawiona, to wywoływana jest funkcja dyscypliny linii write_wakeup, o ile funkcja ta jest zdefiniowana. W dyscyplinie linii N_TTY funkcja write_wakeup nie jest zdefiniowana. |
TTY_PUSH | 6 | Używana przez dyscyplinę linii. |
TTY_CLOSING | 7 | Ustawiona oznacza, że urządzenie terminalowe jest w trakcie zamykania. Informacja ta jest przechowywana ze względu na konieczność zapobiegania tzw. wyścigom procesów (ang. races). |
TTY_THRESHOLD_THROTTLE (N_TTY_BUFSIZE - 128)
TTY_THRESHOLD_UNTHROTTLE 128
flaga | kod | komentarz |
TIOCPKT_DATA | 0x00 | Informuje o tym, że do bufora w przestrzeni użytkownika zostały wczytane dane. |
TIOCPKT_FLUSHREAD | 0x01 | Ustawiona oznacza, że wejściowy bufor znaków terminala został opróżniony. |
TIOCPKT_FLUSHWRITE | 0x02 | Ustawiona oznacza, że wyjściowy bufor znaków terminala został opróżniony. |
TIOCPKT_STOP | 0x04 | Ustawiona oznacza, że część podrzędna pseudoterminala jest zatrzymana. Zatrzymanie zostalo spowodowane nadejściem znaku specjalnego VSTOP. |
TIOCPKT_START | 0x08 | Ustawiona oznacza, że część podrzędna pseudoterminala nie jest zatrzymana. Wznowienie pracy nastąpiło po nadejściu znaku specjalnego VSTART. |
TIOCPKT_NOSTOP | 0x10 | Ustawiona, jeśli dla części podrzędnej pseudoterminala znakiem zatrzymania nie jest VSTART lub znakiem rozpoczęcia nie jest VSTOP lub część ta pracuje w trybie surowym |
TIOCPTK_DOSTOP | 0x20 | Ustawiona, jeśli dla części podrzędnej pseudoterminala znakiem zatrzymania jest VSTOP, znakiem rozpoczęcia jest VSTART oraz część ta nie pracuje w trybie surowym. |