Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)
Transkrypt
Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)
Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi) Ćwiczenie ósme (jeden tydzień) Temat: Niskopoziomowa obsługa terminali Opracowanie: mgr inż. Arkadiusz Chrobot Wprowadzenie 1. Terminale Każdy system komputerowy jest wyposażony w pewną liczbę urządzeń przeznaczonych do komunikacji z użytkownikiem lub innymi komputerami. Mianem „terminal” określa się najczęściej monitor i klawiaturę, choć można tym terminem określić również takie urządzenia jak modem i drukarka. W przypadku systemów uniksowych określa się tak również protokół terminala określający sposób obsługi danego urządzenia przez system operacyjny i część systemu obsługującą urządzenia interakcji z użytkownikiem. Istnieje zbiór funkcji wchodzących w skład API, które umożliwiają programom użytkownika sterowanie zachowaniem terminali. Z każdym terminalem są związane dwie kolejki, wejściowa i wyjściowa, które stanowią rodzaj buforów jądra na znaki, które mają zostać zapisane na ekran, bądź które zostały pobrane z klawiatury. Każdy terminal może pracować w dwóch trybach: kanonicznym i niekanonicznym. W pierwszym trybie znaki przeczytane lub zapisywane na terminal są przetwarzane grupami, które kończą znaki nowej linii, końca linii, lub końca pliku. Ponadto niektóre znaki mają specjalne znaczenia, np.: mogą powodować skasowanie poprzedzającego je znaku. Natomiast w trybie niekanonicznym program może określić samodzielnie jakimi porcjami mają być czytane i pisane dane na terminal, oraz które znaki będą znakami kontrolnymi. 2. Wybrane funkcje i struktury danych Podstawową strukturą danych wykorzystywaną w obsłudze terminali jest struktura termios. Standardy uniksowe gwarantują, że będą się w niej znajdować przynajmniej następujące pola: c_iflag – pole określające flagi trybu wejścia, c_oflag – pole określające flagi trybu wyjścia, c_cflag – pole określające flagi trybu sterowania, c_lflag – pole określające flagi trybu lokalnego, cc_t c_cc[NCCS] – tablica określająca, które znaki są związane z funkcjami kontrolnymi. Uwaga: Niektóre terminale mogą definiować własne pola w tej strukturze, związane np. z obsługą kolorowych wyświetlaczy, dlatego przy manipulacji ustawieniami terminala należy przeczytać jego bieżące ustawienia, zapamiętać je w osobnej zmiennej, a następnie zmodyfikować odpowiednie pole struktury termios, przy pomocy odpowiednich stałych i operatorów bitowych. Potem należy wywołać funkcję zmieniającą zachowania terminala. 2 Przed zakończeniem terminala. program powinien przywrócić domyślną obsługę funkcja isatty() – sprawdza, czy podany deskryptor pliku odnosi się do pliku urządzenia terminala (Szczegóły: man isatty). funkcja ttyname() – zwraca nazwę pliku terminala do której odnosi się deskryptor (Szczegóły: man ttyname). funkcja tcgetattr() – pobiera bieżące atrybuty terminala związanego z podanym deskryptorem pliku i zapisuje je do struktury termios (Szczegóły: man tcgetattr). funkcja tcsetattr() – ustawia żądane atrybuty terminala związanego z podanym deskryptorem pliku. Należy zauważyć, że stan tych atrybutów nie zmieni się po zakończeniu program i jeśli nie przywrócimy domyślnej procedury obsługi terminala możemy zakłócić pracę innych programów współpracujących z tym samym terminalem (Szczegóły man tcsetattr). makro VMIN – ma znaczenie tylko w trybie niekanonicznym, wyznacza położenie miejsca w tablicy cc określającego liczbę bajtów, która musi się znaleźć w kolejce wejściowej zanim zostanie zakończona operacja odczytu. makro VTIME – ma znaczenie tylko w trybie niekanonicznym, określa miejsce w tablicy cc, określające jak długo będzie czekał system zanim zakończy operacje wejścia. Jednostką czasu jest 0,1 sekundy. Szczegółowy opis wszystkich funkcji i struktur danych związanych z obsługą terminali znajduje się w podręczniku systemowym (man termios) i w dokumentacji biblioteki glibc: „The GNU C Library Reference Manual” autorstwa Sandry Loosemore, Richarda Stallmana, Rolanda McGratha, Andrew Orama i Urlicha Dreppera. Zadania 1. Napisz program, który sprawdzi, czy z deskryptorem standardowego wejścia (STDIN_FILENO lub wartość 0) jest związany terminal. Jeśli tak, to program powinien wypisać nazwę pliku urządzenia tego terminala, oraz kilka jego bieżących ustawień. 3 2. Napisz program, który wyłączy echo, czyli wypisywanie znaków wprowadzonych z klawiatury na ekran. Po ponownym uruchomieniu program powinien przywrócić echo. 3. Napisz program demonstrujący obsługę terminala w trybie niekanonicznym (Może to być np. program posiadający menu, które jest uaktywnione naciśnięciem klawisza, bez konieczności potwierdzania klawiszem Enter). 4. Napisz program, po którego uruchomieniu terminal będzie wypisywał wszystkie informacje dużymi literami (niezależnie od ustawienia CapsLock). Efekt ten powinno usuwać ponowne uruchomienie programu. 4