Wstęp do informatyki
(Podręcznik. Wersja RC1)
1
Piotr Fulmański
2
Ścibór Sobieski
3
4 stycznia 2004
1
RC1 — Release Condidate 1, oznacza, że nie będzie żadnych istotnych mody-
fikacji, raczej będą usuwane wyłącznie błędy.
2
E-mail: fulmanp@math.uni.lodz.pl
3
E-mail: scibor@math.uni.lodz.pl
2
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Spis treści
Spis treści
3
Spis rysunków
9
1 Wstęp
15
1.1 Czym jest informatyka? . . . . . . . . . . . . . . . . . . . . . 15
1.2 Historia informatyki . . . . . . . . . . . . . . . . . . . . . . . 17
1.2.1
Bardzo dawno temu ... . . . . . . . . . . . . . . . . . . 17
1.2.2
Ostatnie tysiąclecie . . . . . . . . . . . . . . . . . . . . 19
1.2.3
Wiek XX . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.3 Zastosowanie i przyszłość . . . . . . . . . . . . . . . . . . . . 27
1.4 Kierunki współczesnej informatyki . . . . . . . . . . . . . . . 29
1.4.1
Algorytmika . . . . . . . . . . . . . . . . . . . . . . . . 29
1.4.2
Bazy danych . . . . . . . . . . . . . . . . . . . . . . . 30
1.4.3
Grafika komputerowa . . . . . . . . . . . . . . . . . . 30
1.4.4
Kryptografia . . . . . . . . . . . . . . . . . . . . . . . 31
1.4.5
Programowanie . . . . . . . . . . . . . . . . . . . . . . 31
1.4.6
Sieci komputerowe . . . . . . . . . . . . . . . . . . . . 32
1.4.7
Systemy operacyjne . . . . . . . . . . . . . . . . . . . 33
1.4.8
Sztuczna inteligencja . . . . . . . . . . . . . . . . . . . 35
1.4.9
Teoria informacji . . . . . . . . . . . . . . . . . . . . . 36
1.5 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2 Podstawowe pojęcia i definicje
39
2.1 Algebra Boole’a . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.1.1
Definicja ogólna . . . . . . . . . . . . . . . . . . . . . 39
2.1.2
Dwuelementowa algebra Boole’a . . . . . . . . . . . . 44
2.2 Pozycyjne systemy liczbowe . . . . . . . . . . . . . . . . . . . 45
2.2.1
System dwójkowy . . . . . . . . . . . . . . . . . . . . 47
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4
SPIS TREŚCI
2.2.2
Zapis liczby rzeczywistej w systemie dwójkowym . . . 52
2.2.3
Kod szesnastkowy . . . . . . . . . . . . . . . . . . . . 56
2.2.4
Inne pozycyjne systemy liczbowe . . . . . . . . . . . . 57
2.3 BCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.4 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3 Architektura i działanie komputera
69
3.1 Maszyna Turinga . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.1.1
Definicja Maszyny Turinga . . . . . . . . . . . . . . . 70
3.2 Bramki logiczne . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.3 Architektura współczesnego komputera . . . . . . . . . . . . . 78
3.4 Procesor — serce komputera . . . . . . . . . . . . . . . . . . 83
3.4.1
Cykl pracy procesora . . . . . . . . . . . . . . . . . . . 84
3.4.2
Rejestry procesora Intel 8086 . . . . . . . . . . . . . . 86
3.4.3
Budowa rozkazu . . . . . . . . . . . . . . . . . . . . . 89
3.4.4
Adresowanie . . . . . . . . . . . . . . . . . . . . . . . 90
3.4.5
Asembler . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.5 Reprezentacja informacji . . . . . . . . . . . . . . . . . . . . . 100
3.5.1
Znaki alfanumeryczne . . . . . . . . . . . . . . . . . . 100
3.5.2
Liczby naturalne . . . . . . . . . . . . . . . . . . . . . 103
3.5.3
Liczby całkowite . . . . . . . . . . . . . . . . . . . . . 103
3.5.4
Reprezentacja uzupełnień do dwu . . . . . . . . . . . . 105
3.5.5
Liczby rzeczywiste . . . . . . . . . . . . . . . . . . . . 109
3.6 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
4 Teoria informacji
117
4.1 Informacja vs. wiadomość . . . . . . . . . . . . . . . . . . . . 117
4.2 Geneza i zakres teorii informacji . . . . . . . . . . . . . . . . 118
4.3 Metody kontroli poprawności danych . . . . . . . . . . . . . . 120
4.3.1
Bit parzystości . . . . . . . . . . . . . . . . . . . . . . 121
4.3.2
Suma kontrolna . . . . . . . . . . . . . . . . . . . . . . 122
4.3.3
Kod CRC . . . . . . . . . . . . . . . . . . . . . . . . . 125
4.4 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
5 Algorytmy i struktury danych
129
5.1 Pojęcie algorytmu . . . . . . . . . . . . . . . . . . . . . . . . 129
5.2 Struktury danych . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.2.1
Typ danych . . . . . . . . . . . . . . . . . . . . . . . . 132
5.2.2
Tablica . . . . . . . . . . . . . . . . . . . . . . . . . . 133
5.2.3
Rekord . . . . . . . . . . . . . . . . . . . . . . . . . . 134
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
SPIS TREŚCI
5
5.2.4
Zbiór . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.2.5
Plik . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.3 Metody opisu algorytmów . . . . . . . . . . . . . . . . . . . . 137
5.3.1
Schemat blokowy . . . . . . . . . . . . . . . . . . . . . 137
5.3.2
Schemat zapisu algorytmu za pomocą pseudo-języka . 139
5.4 Podstawowe algorytmy . . . . . . . . . . . . . . . . . . . . . . 143
5.4.1
Algorytmy obliczeniowe . . . . . . . . . . . . . . . . . 143
5.4.2
Algorytmy sortowania . . . . . . . . . . . . . . . . . . 144
5.4.3
Algorytmy wyszukujące . . . . . . . . . . . . . . . . . 146
5.5 Rekurencja vs. iteracja . . . . . . . . . . . . . . . . . . . . . . 148
5.6 Analiza złożoności . . . . . . . . . . . . . . . . . . . . . . . . 153
5.7 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
6 Języki programowania
157
6.1 Czym jest język programowania? . . . . . . . . . . . . . . . . 157
6.1.1
Składnia i semantyka . . . . . . . . . . . . . . . . . . . 159
6.2 Ewolucja języków programowania . . . . . . . . . . . . . . . . 159
6.3 Klasyfikacja języków programowania . . . . . . . . . . . . . . 173
6.3.1
Podział według metodologii programowania . . . . . . 173
6.3.2
Generacje języków programowania . . . . . . . . . . . 176
6.4 Kompilacja vs. interpretacja . . . . . . . . . . . . . . . . . . . 177
6.5 Elementy teorii języków formalnych . . . . . . . . . . . . . . . 183
6.5.1
Gramatyka . . . . . . . . . . . . . . . . . . . . . . . . 183
6.5.2
Notacja BNF . . . . . . . . . . . . . . . . . . . . . . . 184
6.5.3
Notacja przy użyciu diagramów składni . . . . . . . . 185
7 System operacyjny
187
7.1 Zadania realizowane przez system operacyjny . . . . . . . . . 188
7.2 System operacyjny a architektura komputera . . . . . . . . . 189
7.3 Klasyfikacja systemów operacyjnych . . . . . . . . . . . . . . 190
7.4 Realizacja zadań . . . . . . . . . . . . . . . . . . . . . . . . . 193
7.5 W kierunku systemów wielozadaniowych . . . . . . . . . . . . 196
7.6 Procesy, wątki, . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
7.7 Zarządzanie pamięcią . . . . . . . . . . . . . . . . . . . . . . . 198
7.8 System plików . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
7.9 Czy każdy komputer musi posiadać system operacyjny? . . . 199
7.10 Przykładowe systemy operacyjne . . . . . . . . . . . . . . . . 201
7.10.1 Amoeba . . . . . . . . . . . . . . . . . . . . . . . . . . 201
7.10.2 Mac OS . . . . . . . . . . . . . . . . . . . . . . . . . . 202
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6
SPIS TREŚCI
7.10.3 MS-DOS i Windows . . . . . . . . . . . . . . . . . . . 204
7.10.4 NetWare . . . . . . . . . . . . . . . . . . . . . . . . . . 207
7.10.5 OS/390 . . . . . . . . . . . . . . . . . . . . . . . . . . 208
7.10.6 OS/400 . . . . . . . . . . . . . . . . . . . . . . . . . . 210
7.10.7 Unix i rodzina . . . . . . . . . . . . . . . . . . . . . . 211
7.11 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
8 Sieci komputerowe
215
8.1 Po co mi ona? . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
8.2 Struktura fizyczna sieci . . . . . . . . . . . . . . . . . . . . . 216
8.2.1
Zasięg sieci . . . . . . . . . . . . . . . . . . . . . . . . 216
8.2.2
Topologia sieci . . . . . . . . . . . . . . . . . . . . . . 217
8.3 Architektura sieci . . . . . . . . . . . . . . . . . . . . . . . . . 218
8.3.1
Architektura równorzędna . . . . . . . . . . . . . . . . 222
8.3.2
Architektura klient-serwer . . . . . . . . . . . . . . . . 223
8.4 Kilka przydatnych pojęć . . . . . . . . . . . . . . . . . . . . . 224
8.4.1
Pakiety i ramki . . . . . . . . . . . . . . . . . . . . . . 224
8.4.2
Protokół . . . . . . . . . . . . . . . . . . . . . . . . . . 225
8.4.3
TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . 227
8.4.4
Usługa DNS . . . . . . . . . . . . . . . . . . . . . . . . 228
8.5 Urządzenia sieci komputerowych . . . . . . . . . . . . . . . . 229
8.5.1
Urządzenia transmisji . . . . . . . . . . . . . . . . . . 229
8.5.2
Urządzenia dostępowe . . . . . . . . . . . . . . . . . . 230
8.6 Zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
A Podstawowe jednostki i pojęcia w informatyce
235
B Kody ASCII
237
C Kodowanie polskich znaków
241
D Organizacje standaryzujące
243
E Rozwiązania zadań
245
E.1 Rozwiązania do rozdziału 2 . . . . . . . . . . . . . . . . . . . 245
E.2 Rozwiązania do rozdziału 3 . . . . . . . . . . . . . . . . . . . 248
E.3 Rozwiązania do rozdziału 4 . . . . . . . . . . . . . . . . . . . 251
E.4 Rozwiązania do rozdziału 5 . . . . . . . . . . . . . . . . . . . 252
Bibliografia
257
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
SPIS TREŚCI
7
Indeks
260
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8
SPIS TREŚCI
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Spis rysunków
1.1 Ilustracja idei metody różnicowej . . . . . . . . . . . . . . . . 20
1.2 Schemat maszyny analitycznej . . . . . . . . . . . . . . . . . 21
3.1 Ilustracja procesu czytania przez człowieka. . . . . . . . . . . 69
3.2 Kartka przekształcona w taśmę . . . . . . . . . . . . . . . . . 70
3.3 Symbole reprezentujące bramki AND, OR, NOT, NAND,
NOR i XOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.4 Realizacja bramek AND, OR , NOT za pomocą bramek NAND
lub NOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.5 Ilustracja architektury współczesnego komputera. . . . . . . . 79
3.6 Ilustracja zależności kosztów pamięci, ich pojemności i czasu
dostępu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.7 Architektura procesora Intel 8086. . . . . . . . . . . . . . . . 84
3.8 Rozmieszczenie flag w rejestrze flagowym. . . . . . . . . . . . 87
3.9 Uproszczony schemat rozkazu procesora Intel 8086. . . . . . . 89
3.10 Adresowanie natychmiastowe. . . . . . . . . . . . . . . . . . . 93
3.11 Adresowanie bezpośrednie z rejestru. . . . . . . . . . . . . . . 93
3.12 Adresowanie bezpośrednie z pamięci. . . . . . . . . . . . . . . 93
3.13 Adresowanie pośrednie przez rejestr bazowy. . . . . . . . . . . 94
3.14 Adresowanie pośrednie przez rejestr bazowy i offset. . . . . . 94
3.15 Adresowanie przez rejestr bazowy i indeksowy. . . . . . . . . 95
3.16 Adresowanie przez rejestr bazowy, indeksowy i offset. . . . . . 95
5.1 Przykładowe symbole stosowane na schematach blokowych. . 138
5.2 Schemat blokowy — fragment algorytmu znajdowania pier-
wiastków trójmianu. . . . . . . . . . . . . . . . . . . . . . . . 139
5.3 Instrukcja warunkowa if zapisana w postaci schematu blo-
kowego. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
10
SPIS RYSUNKÓW
5.4 Pętla while i do--while zapisana w postaci schematu blo-
kowego. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
5.5 Pętla for zapisana w postaci schematu blokowego. . . . . . . 142
5.6 Ilustracja procesu sortowania przez wstawianie. . . . . . . . . 145
5.7 Ilustracja procesu przeszukiwania połówkowego. . . . . . . . . 147
5.8 Drzewo wywołań dla rekurencyjnego obliczania 5-ego wyrazu
ciągu Fibonacciego. . . . . . . . . . . . . . . . . . . . . . . . . 152
5.9 Schemat blokowy pewnego algorytmu. . . . . . . . . . . . . . 155
6.1 Ilustracja procesu kompilacji. . . . . . . . . . . . . . . . . . . 179
6.2 Ilustracja procesu interpretacji. . . . . . . . . . . . . . . . . . 181
6.3 Ilustracja procesu prekompilacji i wykonania na maszynie
wirtualnej. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
6.4 Fragment składni Pascala zapisany przy pomocy diagramów
składni. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
7.1 Umiejscowienie Systemu Operacyjnego w systemie kompute-
rowym. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
7.2 Stany procesu i przejścia pomiędzy nimi. . . . . . . . . . . . . 194
7.3 Wykorzystanie procesora przez dwa procesy. . . . . . . . . . . 195
8.1 Topologia magistrali. . . . . . . . . . . . . . . . . . . . . . . . 218
8.2 Topologia pierścienia. . . . . . . . . . . . . . . . . . . . . . . 219
8.3 Topologia gwiazdy. . . . . . . . . . . . . . . . . . . . . . . . . 219
8.4 Topologia oczek pełnych. . . . . . . . . . . . . . . . . . . . . 220
8.5 Porównanie transmisji pakietowej. . . . . . . . . . . . . . . . 225
8.6 Ogólny schemat ramki. . . . . . . . . . . . . . . . . . . . . . . 225
8.7 Kabel koncentryczny. . . . . . . . . . . . . . . . . . . . . . . . 230
8.8 Skrętka. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
8.9 Światłowód. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
8.10 Ogólny schemat komputerów w sieci. . . . . . . . . . . . . . . 233
E.1 Schamat blokowy algorytmu obliczającego potęgę. . . . . . . 253
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Przedmowa
Pisanie jest jedyną sztuką, którą musimy się nauczyć pisząc.
Anonim
Autorzy niniejszego podręcznika od roku 2000 prowadzą wykłady i ćwi-
czenia z przedmiotu „Wstęp do informatyki”. Przedmiot ten występuje na
pierwszym roku studiów informatycznych na Wydziale Matematyki Uniwer-
sytetu Łódzkiego. Jego celem jest zapoznanie studentów z historią informa-
tyki, jej podstawowymi pojęciami i definicjami, oraz przybliżenie tego co
dzieje się w obecnej informatyce i jakie dziedziny wchodzą jej skład. W
czasie prowadzenia zajęć z przedmiotu Autorzy zauważyli lukę w literaturze
informatycznej. Owszem istnieje wiele książek, czy publikacji skryptowych,
które omawiają wszystkie poruszane problemy, jednak informacje i wiedza
są zwyczajnie rozproszone w bardzo wielu pozycjach, wśród których trudno
jednoznacznie wskazać najbardziej pomocną czy użyteczną
1
. Kiedy studenci
często pytali skąd można uzyskać informację, Autorzy byli zmuszeni wskazy-
wać dość pokaźną bibliografię. Działało to w pewien sposób odstraszająco,
nawet nie z przyczyny ilości pozycji, co często niemożności ich otrzymania,
a często również stopnia trudności w jaki sposób były one napisane
2
. Więk-
szość specjalistycznych pozycji, omawiających jakiś dział jest zbyt trudna
dla osób dopiero poznających informatykę, lub wprowadza za dużo szcze-
gółów, niepotrzebnie zaciemniających idee danego zagadnienia. Stąd też
w 2001 roku zrodziła się potrzeba stworzenia podręcznika, który bardziej
pasowałby do charakteru przedmiotu wprowadzającego w informatykę.
Niniejsze opracowanie jest próbą przybliżenia obecnego zakresu dzie-
dziny naukowej nazywanej Informatyka. Autorzy starają się wskazać czy-
telnikowi na charakter tej dyscypliny wiedzy, jej podstawowe pojęcia oraz
główne gałęzie. I tak w kolejnych rozdziałach czytelnik zapozna się z róż-
nymi fragmentami wiedzy informatycznej. Niektóre działy są potraktowane
1
Dowodem mnogości źródeł może być spis cytowanej bibliografii.
2
Są to najczęsciej specjalistyczne ksiązki z danego działu.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
12
SPIS RYSUNKÓW
bardzo dokładnie (dla przykładu 2), gdyż omawiają podstawowe pojęcia,
które stanowią niejako alfabet informatyka. Inne zaś, dla przykładu sieci
czy systemy operacyjne, są potraktowane bardziej powierzchownie, głów-
nie w celu wprowadzenie pojęć i zasygnalizowania problematyki, kierunki
te stanowią tematykę specjalizowanych wykładów na późniejszych latach
studiów.
Na samym wstępie umieszczono rozdział omawiający istotę i historię
informatyki, oraz pokazano, iż rozwój informatyki jest w chwili obecnej
ściśle związany z rozwojem komputerów. Opisano też główne dziedziny
obecnej informatyki i wskazano, gdzie według autorów odbywa się obecnie
najbardziej dynamiczny rozwój.
W rozdziale 2 Czytelnik zapozna się z niezbędnymi definicjami i infor-
macjami dotyczącymi systemów liczbowych, kodów i pojęć stosowanych w
komputerach. Rozdział ten jest w części związanej z algebrą Boole’a teore-
tyczny i zawiera definicje oraz podstawowe twierdzenia tych algebr. Starano
się jednak opisać to wszystko w sposób maksymalnie uproszczony i przej-
rzysty, zdając sobie sprawę, że nie każdy czytelnik ma odpowiednie przygo-
towanie matematyczne. Należy jednak podkreślić, że algebra Boole’a jest
bardzo ważnym elementem, bynajmniej nie tylko teoretyczny, szczególnie
przydaje się w późniejszej praktyce upraszczanie wyrażań algebraicznych.
W rozdziale 3 została omówiona budowa dzisiejszego komputera i zasada
jego działania. Przy czym szczególny nacisk położono na ideę konstrukcji od
strony koncepcji nie zaś technologii. Stąd w pierwszej kolejności omówiono
Maszynę Turinga, która stanowiła jeden z elementów, który posłużył von
Neumannowi do stworzenia idei maszyny von neumannowskiej. Poza tym
sama Maszyna Turinga stanowi ważną konstrukcję myślową, która służy
później do badań w teorii języków formalnych i automatów skończonych.
W dalszym ciągu w rozdziale tym omówiono elementarną budowę mikro-
procesora na przykładzie procesora INTEL 8086, wraz z sygnalizacją takich
pojęć jak rejestry, kod maszynowy czy asembler. Wyjaśniono również w
jaki sposób jest reprezentowana informacja w komputerze, zatem została
omówiona reprezentacja w kodzie uzupełnień do dwu, reprezentacja zmien-
noprzecinkowa, kod ASCII czy też UNICODE.
Rozdział 4 stanowi wprowadzenie w zagadnienia teorii informacji. Po-
nieważ sama ta teoria jest trudna i wymagająca świetnej znajomości ra-
chunku prawdopodobieństwa, stąd starano się przedstawić tylko najważ-
niejsze fakty, wyrabiając w czytelniku pewną intuicję, pomijając zaś niepo-
trzebne szczegóły techniczne, czy twierdzenia. W dalszej części pokazano
jak pewne elementy związane z teorią informacji wykorzystuje się na codzień
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
SPIS RYSUNKÓW
13
w praktyce informatyka.
Rozdział 5 zawiera wprowadzenie do algorytmów i struktur danych.
Dział ten jest przedmiotem osobnego wykładu na studiach informatycznych.
Autorzy omówili podstawowe pojęcie tego przedmiotu i opisali te elementy,
co do których później zakłada się, że student je zna. Są to sposoby zapisu
algorytmów, za pomocą schematu blokowego, czy też pseudo-języka.
W rozdziale 6 czytelnik znajdzie informacje o historii i rozwoju języ-
ków programowania, oraz ich własnościach i próbach klasyfikacji. Języki
programowania jak i samo programowanie stanowią jeden z głównych dzia-
łów informatyki, bez którego nie istniały by programy, a z pewnością nie
pisano by ich tak szybko i efektywnie jak to się dzieje w chwili obecnej.
Stąd Autorzy starają się wprowadzić pewną wiedzą związaną z tym, czym
są języki programowania, co spowodowało powstanie tak wielkiej ich ilo-
ści, oraz w jaki sposób można je pogrupować i które z nich wykorzystać w
określonych sytuacjach.
Rozdział 7 zawiera omówienie podstawowych własności systemu opera-
cyjnego. Podział współczesnych systemów operacyjnych na kategorie, a na
końcu krótkie omówienie współczesnych systemów operacyjnych, głownie w
ujęciu historycznym. System operacyjny to zaraz po sprzęcie najważniejszy
element komputera, niejednokrotnie decydujący o jego sprawności i uży-
teczności. Stąd Autorzy starali się omówić różnice pomiędzy systemami
operacyjnymi na poziomie ich budowy, unikając odniesień, tam gdzie tylko
to możliwe, do rzeczywiście istniejących systemów. Główny powód takiego
postępowania, to niechęć do narzucania własnych poglądów, czy też upodo-
bań, oraz próba uniknięcia jakiejkolwiek formy reklamy. Stąd starano się
skoncentrować na wskazaniu gdzie i jakie cechy danego systemu mogą być
użyteczne, a gdzie można się bez nich obejść.
Ostatni rozdział 8 omawia zagadnienia związane z sieciami komputero-
wymi. Opisany jest podział ze względu fizyczną i logiczną strukturę sieci,
wprowadzone są podstawowe pojęci i jednostki. We współczesnym świe-
cie większość ludzi nie wyobraża sobie funkcjonowania bez komputera i to
komputera podłączonego do Internetu. A Internet to nic innego jak jeden
z aspektów wykorzystania sieci rozległych, wszelkie jego usługi, jak poczta
czy WWW działają wyłącznie w oparciu o transmisję danych poprzez sieć.
W rozdziale tym starano się przybliżyć problematykę sieci, zwrócić uwagę
na wady i zalety pewnych technologii czy sposobów konfiguracji sieci.
Na końcu podręcznika znajduje się zbiór dodatków, które mają być ro-
dzajem encyklopedycznego poradnika, po który zawsze łatwo sięgnąć. Do-
łączono również obszerny indeks, który ma ułatwić poruszanie się po całości
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
14
SPIS RYSUNKÓW
pracy.
Udostępniamy to opracowanie w nadziei, że ułatwi ono uporządkowanie
wiadomości z zakresu wykładu „Wstęp do informatyki” dla tych osób, które
takiego wykładu mogły wysłuchać. Pozostałe osoby, mamy nadzieję, rów-
nież mogą skorzystać z tego podręcznika, szczególnie jeśli są zainteresowane
omawianą problematyką i nie boją się uczyć indywidualnie.
Zainteresowanych czytelników zachęcamy do poszukiwania dalszych in-
formacji wymienionych w pozycjach bibliografii. Nawet jeśli któraś z nich
nie jest ściśle związana z omawianymi zagadnieniami, to umożliwi poszerze-
nie własnych horyzontów myślowych, pozwalając na samodzielny rozwój.
Ponieważ zdajemy sobie sprawę z własnej omylności, stąd informujemy,
że wszelkie poprawki do niniejszego wydania, jak i ewentualne uaktualnie-
nia, znajdą się na stronie internetowej:
http://???/
Jeśli ktokolwiek z grona znajdzie jakikolwiek błąd, niejasności czy też
będzie miał sugestie prosimy o kontakt za pomocą poczty elektronicznej na
adresy: fulmanp@math.uni.lodz.pl
scibor@math.uni.lodz.pl
Na koniec chcielibyśmy podziękować tym wszystkim, którzy pomogli
nadać podręcznikowi obecną jego formę, bądź to poprzez motywację, bądź
ciepliwie czytając pierwsze wersje i nanosząc poprawki. I tak Profesorowi
Andrzejowi Nowakowskimu za to, że powiedział: „Piszcie ten skrypt”, na-
szym koleżankom i kolegom: Oli Orpel, Jadwidze Nowak, Jankowi Pustel-
nikowi, Grześkowi Oleksikowi za czytanie i nanoszenie poprawek. Kilkuna-
stu studentom, którzy zgłosili błędy zauważone we wcześniejszych wersjach.
Oraz na końcu, lecz nie oznacza to, że z mniejszą wdzięcznością, Michałowi
Kędzierskiemu, za cierpliwe czytanie i poprawianie błędów językowych, sty-
listycznych i logicznych, dzięki czemu prawdopodobnie ten podręcznik w
ogóle daje się czytać.
Piotr Fulmański, Ścibór Sobieski
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 1
Wstęp
Wykład to przenoszenie wiadomości z notatek wykładowcy do notatek
ucznia — z pominięciem mózgów ich obu.
Pokolenia uczniów
1.1
Czym jest informatyka?
Podobnie można zapytać o matematykę, filozofię, czy biologię, a pytanie o
to, czym jest dana dyscyplina zdaje się być podstawowym w każdej dzie-
dzinie nauki, jaką człowiek uprawia. Wydaje się jednak, że w przypadku
informatyki odpowiedź nie jest tak oczywista. Z pozoru można sądzić, że
informatyka to nauka o komputerach. Jednak odpowiedź ta zawiera w sobie
tylko część prawdy. Owszem trudno sobie wyobrazić dzisiejszą informatykę
bez komputera, ale czy to znaczy, że bez niego informatyka nie mogła by
istnieć jako dyscyplina wiedzy? Nic bardziej błędnego, komputer jest tylko
narzędziem, dzięki któremu informatyka nabrała tak ogromnego znaczenia i
stała się tak bardzo użyteczna. Informatyka to dziedzina, która zajmuje się
przetwarzaniem informacji za pomocą pewnych schematów postępowania
(zwanych algorytmami). Wynikiem takiego procesu jest znów informacja.
Można te rozważania w łatwy sposób zilustrować na przykładzie pro-
stego programu słownika polsko–angielskiego. Użytkownik wpisuje słowo po
polsku (informacja wejściowa), prosi o wykonanie tłumaczenia (algorytm),
w efekcie otrzymuje odpowiednik lub odpowiedniki w języku angielskim (in-
formacja wyjściowa). Jeśli w powyższym przykładzie nie wspomnimy, że
chodzi o program tylko o zwykły drukowany słownik, to czy to jest infor-
matyka? W pewien sposób tak, gdyż człowiek wykonujący czynność wy-
szukiwania odpowiednika słowa w języku obcym, świadomie i nieświadomie
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
16
Wstęp
wykonuje pewien proces (algorytm) poszukiwania tego słowa (świadomie —
gdyż bez udziału świadomości niczego nie znajdzie, nieświadomie — gdyż
nie zdaje sobie sprawy, że wykonuje algorytm). A informatyka zajmuje się
między innymi tworzeniem i badaniem takich algorytmów. Czy to oznacza,
że jesteśmy komputerem? Oczywiście nie. Jednak ten przykład pokazuje,
że komputer jest tylko narzędziem wspomagającym informatykę i informa-
tyków. Ale nie oznacza to, że jest on niezbędny (chodź są procesy, które
bez komputera byłyby nie wykonalne), czy też jedyny. Z pewnością trudno
by było mówić o informatyce w dzisiejszej formie bez komputerów. Wynika
to przede wszystkim z faktu, że informatycy do przetwarzania informacji
używają coraz to bardziej skomplikowanych algorytmów, które by były wy-
konane w rozsądnym czasie potrzebują coraz szybszych komputerów.
Kolejnym ważnym aspektem informatyki jest przechowywanie ogrom-
nych ilości informacji, zwykle w celu późniejszego jej wyszukania, czy też
przeanalizowania
1
. I tu znów z pomocą przychodzą komputery i elektronika,
która w obecnej chwili pozwala nam na magazynowanie coraz to większej
ilości danych w coraz to mniejszych nośnikach informacji (CD, DVD, etc.).
Obecnie tak bardzo utożsamia się informatykę i komputer, że nawet an-
gielskie określenie informatyki „Computer science”, informuje, że jest to
„nauka o komputerach”, jednak właściwszym terminem byłaby „nauka o
przetwarzaniu informacji”.
Niewątpliwie najbardziej intensywny rozwój informatyki przypadł na
ostatnie kilkadziesiąt powojennych lat. Spowodowane to było przede wszyst-
kim powstaniem i bardzo szybkim rozwojem elektroniki, w szczególności
elektroniki cyfrowej. Rozwój technologii i w konsekwencji miniaturyzacja
układów cyfrowych umożliwił powstanie komputerów osobistych posiadają-
cych dużą moc obliczeniową.
Jednak czynności związane z pobieraniem, przechowywaniem i przetwa-
rzaniem informacji, człowiek wykonywał od bardzo dawna. Możliwości me-
chanizacji tych prac, a później ich automatyzacji pojawiały się stopniowo w
miarę konstruowania i wytwarzania odpowiednich urządzeń, co było zwią-
zane właśnie z rozwojem techniki i technologii. W tej sytuacji przestaje
dziwić fakt, że informatyka jest w dużej mierze „nauką o komputerach”,
gdyż bez nich nie była by ona tym, czym jest w chwili obecnej. Potwierdza
to nawet datowanie początków informatyki jako dziedziny naukowej, które
umieszcza się na początek lat pięćdziesiątych, kiedy to powstawały pierwsze
komputery elektronowe.
1
Wygenerowanie raportu sprzedaży za ostatni miesiąc w programie magazynowo-sprze-
dażowym jest przykładem informacji, która została przetworzona (przeanalizowana).
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.2 Historia informatyki
17
Spróbujmy zatem przybliżyć dokładniej zakres dawnej i dzisiejszej in-
formatyki.
1.2
Historia informatyki
Historia to koszmar, z którego próbuję się obudzić.
James Joyce
Gdybyśmy lepiej znali historię, u źródła każdej innowacji
odkrylibyśmy jakiś wielki umysł.
Emile Mal´e
Pytanie o początki informatyki jest, podobnie jak pytanie o jej istotę,
pytaniem trudnym, głównie ze względu na wcześniej wspomniane trudności
ze zdefiniowaniem zakresu informatyki. W tym rysie historycznym przy-
jęto, że początek informatyki to początek rozwoju myśli ludzkiej związanej
z obliczaniem jak i próbami automatyzacji procesów obliczeniowych. Ta-
kie założenie wynika z faktu ścisłego związania informatyki z maszynami
liczącymi, dzisiejszymi komputerami. Zatem początkowy rozwój informa-
tyki będzie pokrywał się, w głównej mierze, z jednej strony z początkami
pierwszych algorytmów (czyli procedur przetwarzania informacji), z drugiej
zaś z rozwojem przyrządów i urządzeń wspomagających obliczenia.
Rys historyczny zastał ułożony chronologicznie, konsekwencją takiego
założenie jest przeplatanie się faktów z rozwoju urządzeń obliczeniowych
oraz pewnych koncepcji myśli informatycznej.
1.2.1
Bardzo dawno temu ...
Około 3000 lat p.n.e.
2
ludy sumeryjskie wykorzystywały do obliczeń gliniane
tabliczki z wyżłobionymi rowkami do których wkładano kamyki. Około 2600
p.n.e. Chińczycy skonstruowali Abakus: drewnianą tabliczkę podzieloną na
kolumny. Każda kolumna reprezentowała pozycję jednej cyfry: pierwsza
— jednostki, druga — dziesiątki, itd. W każdej kolumnie do wydrążonych
2
Nie należy tej daty utożsamiać z narodzinami liczenia, czy inaczej nazywając zlicza-
nia. Okazuje się bowiem, że w 1937 roku w miejscowości Dolni Vestonice na Morawach
znaleziono kość wilka, która zawiera 57 nacięć pogrupowanych po pięć. Można przypusz-
czać, że należała ona do osoby, która w ten sposób coś zliczała, nie było by w tym nic
dziwnego, gdyby nie fakt, że datuje się to znalezisko na około 30 tysięcy lat p.n.e.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
18
Wstęp
rowków wkładano kamyki (maksymalnie 9) lub kościane gałki oznaczone cy-
frami od 1 do 9
3
. Udoskonaleniem tego przyrządu były późniejsze liczydła.
Wykonywanie działań przy pomocy Abakusa polegało na odpowiednim
przesuwaniu kamyków. Chcąc na przykład do 31 dodać 23 należało:
1. w kolumnie jedności położyć 1 kamyczek,
2. w kolumnie dziesiątek położyć 3 kamyczki,
3. do kolumny jedności dołożyć 3 kamyczki,
4. do kolumny dziesiątek dołożyć 2 kamyczki,
5. policzyć ilość kamyczków w kolumnie jedności i kolumnie dziesiątek.
Procedura ta wydaje się poprawna, ale zauważmy, że jeśli chcielibyśmy do 18
dodać 5 to napotkamy na problem. W kolumnie jedności mamy bowiem już
8 kamyków i należałoby dodać jeszcze 5. Tego zrobić jednak nie można, gdyż
każda kolumna może zawierać maksymalnie 9 kamyków. Aby rozwiązać
ten problem należało w pamięci dodać 8 do 5, w wyniku otrzymamy 13,
zatem w kolumnie jedności pozostawiamy 3 kamyki a do następnej kolumny
dodajemy 1. Ten sposób rozwiązania problemu nosił nazwę dziesiątkowania.
Pomiędzy 400 a 300 rokiem p.n.e. wielki grecki matematyk i filozof
Euklides, wymyślił pierwszy znany nam nietrywialny algorytm, czyli przepis
na realizację zadania. Był to algorytm znajdowania największego wspólnego
dzielnika dwóch dodatnich liczb całkowitych.
W tym miejscu należy zauważyć, iż Euklides wymyślając ten sposób
obliczania największego wspólnego dzielnika nie miał pojęcia, że wymyśla
„algorytm”. A to dlatego, że słowo algorytm pochodzi od nazwiska ma-
tematyka arabskiego, który żył na przełomie VIII i IX wieku naszej ery.
Matematyk ten nazywał się Muhammad ibn Musa al-Chorezmi (spotykana
też pisownia al-Khawarizmy), zasłużył się zaś stworzeniem kilku dzieł z dzie-
dziny matematyki, w których opisał dużą ilość reguł matematycznych (w
tym dodawania, odejmowania, mnożenia i dzielenia zwykłych liczb dziesięt-
nych). Opis tych procedur był na tyle precyzyjny i formalny, jak na tamte
czasy, że właśnie od jego nazwiska pochodzi słowo algorytm.
3
Należy pamiętać, że Chińczycy nie znali cyfr arabskich, którymi dzisiaj się posługu-
jemy, gdyż zostały one wprowadzone znacznie później.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.2 Historia informatyki
19
1.2.2
Ostatnie tysiąclecie
Na początku XVII wieku naszej ery John Neper (1550-1617) opublikował
swoje dzieło o logarytmach oraz opisał przyrząd wspomagający mnożenie
za pomocą logarytmów. Przyrząd ten zwany był pałeczkami Nepera. Idea
działania była bardzo prosta, lecz w tamtych czasach rewolucyjna. Pole-
gała na tym, że mnożenie sprowadzano do serii dodawań. Pomysł ten jest
wykorzystywany do dzisiejszych czasów.
W tym samym czasie żył Wilhelm Schickard (1592-1635), który jest
uznawany za twórcę pierwszej mechanicznej maszyny liczącej. Opisał on
model maszyny czterodziałaniowej wykorzystującej pałeczki Nepera wyko-
nane w postaci walców.
W tych czasach twórcy maszyn liczących ponownie natrafili na problem
dziesiątkowania, który, przypomnijmy, pojawił się 38 wieków wcześniej!
Tym razem problem ten został rozwiązany w sposób mechaniczny, a po-
radził sobie z nim francuski matematyk Blaise Pascal (1623-1662), budując
w 1642 sumator arytmetyczny. Była to maszyna o kilku kołach zębatych
(10 zębów z numerami od 0 do 9). Chcąc wykonać operacje ustawiało się
koła na odpowiednią wartość początkową (na przykład koło dziesiątek na
1, jedności na 8), a następnie przestawiało się odpowiednie koła wymaganą
ilość razy (na przykład jedności o 5). W momencie, gdy jedno z kół obra-
cało się z pozycji 9 na następną, jaką jest 0, powodowało ono również obrót
kolejnego koła o jedną pozycje. Tym oto sposobem uporano się z zagad-
nieniem automatycznego uwzględniania przeniesienia na następną pozycję
dziesiętną. Pascal budował swoje maszyny, zwane Pascalinami, z myślą o
swoim ojcu, który był poborcą podatkowym. Maszyny te, wyprodukowano
ich około 50 egzemplarzy, były głównie przeznaczone do obliczeń w różnych
systemach monetarnych, kilka z nich przystosowanych było do obliczeń od-
ległości i powierzchni i były przeznaczone dla geodetów.
Zarówno Schickard jak i Pascal, skonstruowali tak swoje maszyny liczące,
by potrafiły automatycznie przenosić cyfry przy dodawaniu czy odejmowa-
niu.
Niedługo po skonstruowaniu sumatora arytmetycznego urodził się ko-
lejny wielki matematyk Gottfried Wilhelm Leibniz (1646-1716), który to
ponownie odkrył system dwójkowy, ponownie, gdyż pierwsi byli Chińczycy.
System dwójkowy jest obecnie podstawowym systemem do reprezentacji
wszelkiej informacji (liczb, liter i innych znaków) w dzisiejszych kompute-
rach.
W początkach wieku XIX angielski matematyk Charles Babbage (1791-
1871) skonstruował maszynę różnicową, która miała obliczać określone
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
20
Wstęp
Rysunek 1.1: Ilustracja idei metody różnicowej
równania matematyczne. Zadaniem tej maszyny miało być wyręczenie czło-
wieka od żmudnych i powtarzających się czynności. Podstawą działania tej
maszyny była metoda różnicowa. Wytłumaczymy tę metodę na przykła-
dzie.
Spójrzmy na rysunek 1.1, ilustruje on pewną własność matematyczną.
Własność ta mówi o tym, że potęga kwadratowa dowolnej liczby całkowitej
wyraża się jako suma potęgi kwadratowej liczby całkowitej ją poprzedza-
jącej oraz kolejnej liczby nieparzystej. Spójrzmy na rysunek i rozważmy
potęgę kwadratową liczby 3, wiemy że wynosi ona 9, ale z zacytowanej wła-
sności wynika, że jest ona sumą kwadratu liczby ją poprzedzającej, a zatem
2
2
= 4 oraz liczby 5. Jeśli teraz weźmiemy liczbę dowolną to wykorzystując
tę własność oraz fakt, że możemy tę metodę zastosować w sposób zstępujący
(rekurencyjny zob. 5.5), to zamiast wykonywać żmudne mnożenie możemy
wykonywać sumowanie, które nawet w dzisiejszych komputerach jest tań-
sze od dodawania
4
(zob. 3.4). Babbage wykorzystując podobne własności
pomijał pewne niedogodności, a co za tym idzie przyśpieszał obliczenia.
Istotną różnicą maszyny różnicowej w porównaniu do maszyn Pascala,
było to, że po nastawieniu danych początkowych wszelkie dalsze obliczenia
odbywały się automatycznie bez udziału człowieka, za wyjątkiem samego
faktu napędzania maszyny.
Babbage jest obecnie uważamy za najwybitniejszego twórcę maszyn li-
czących, żyjącego przed nadejściem maszyn elektronicznych. Sławę tę za-
wdzięcza głównie dzięki swojemu kolejnemu pomysłowi, jakim było stworze-
nie modelu i próba realizacji maszyny analitycznej. Maszyna ta miała
składać się z magazynu (dzisiejszy odpowiednik pamięci), młyna (jednostka
4
Mówiąc „tańsze” w tym miejscu, mamy na myśli wymagające mniejszego zaangażo-
wania komputera.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.2 Historia informatyki
21
Młyn
Dane do
Sterowanie
"Programowanie"
Rysunek 1.2: Schemat maszyny analitycznej
licząca) i mechanizmu sterującego (jednostka sterująca).
Pamięć miała służyć do przechowywania danych oraz wyników z prze-
prowadzanych na nich operacji. Młyn, odpowiednik dzisiejszej jednostki
arytmetyczno–logicznej (zob. 3.4), wykonywać miał proste działania aryt-
metyczne. Działaniem całego urządzenia miał kierować mechanizm steru-
jący, który miał być w idei programowany. Bardzo ciekawym pomysłem była
koncepcja wykorzystania do programowania mechanizmu sterującego kart
perforowanych (kartoniki papieru z dziurkami). Pomysł ten został zapoży-
czony od Jacquarda, który kilka lat wcześniej skonstruował krosna sterowane
za pomocą takich kart
5
. Zwróćmy uwagę, że aby maszyna analityczna mo-
gła być programowana musiała posiadać nie tylko jednostkę sterującą, ale
również pamięć, której rolę pełnił magazyn. To właśnie w pamięci przecho-
wywano wyniki obliczeń pośrednich, dzięki czemu można był wykonywać na
tej maszynie więcej niż proste działania, można było wykonywać sekwencje
działań.
Niestety twórcy idei nie udało się skonstruować kompletnej i działają-
cej maszyny analitycznej. Ale opisy były na tyle dokładne i kompletne, że
gdy dostały się w ręce Ady Augusty hrabiny Lovelace, córki Byrona, zain-
spirowały ją do obmyślenia pierwszych programów dla tej, nie istniejącej,
maszyny. Prawdą jest, że były to raczej opisy procedur obliczeniowych niż
5
Dokładniej wzór tkany przez te krosna zależał od „programu” zawartego na tych
kartach.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
22
Wstęp
programy w dzisiejszym tego słowa znaczeniu, ale w niczym nie umniejsza
to zasług Pani hrabiny, która stała się dzięki temu pierwszą programistką
na świecie, a mówiąc ogólnie o zawodzie pierwszym programistą w ogóle.
Jej zasługi zostały uhonorowane nadaniem jej imienia jednemu z najbardziej
uniwersalnych i zaawansowanych obecnie języków programowania jakim jest
ADA.
Kolejnego kroku w dziedzinie przetwarzania informacji dokonał Herman
Hollerith, który był pracownikiem amerykańskiego biura statystycznego.
Impulsem do działania stały się dla niego doświadczenia z opracowywania
wyników spisu powszechnego przeprowadzonego w USA w roku 1880 – ope-
racja ta trwała 7 lat. Najbardziej czasochłonną czynnością okazało się wtedy
grupowanie i liczenie jednostek charakteryzujących się określonymi cechami.
Skonstruowano zatem maszynę, która automatycznie odczytywała, porząd-
kowała i grupowała dane według określonych kryteriów. Do wprowadzania
danych do maszyny użyto specjalnych kart perforowanych. Występowanie
danej cechy zaznaczano otworkiem w odpowiednim miejscu karty. Wydziur-
kowane karty umieszczano w matrycy, pod którą znajdowały się pojemniki
z rtęcią. Do każdego pojemnika doprowadzano prąd elektryczny, następnie
opuszczano na kratę płytę z kołeczkami. W miejscach, gdzie były otwory,
następowało zamknięcie obwodu (kołeczki dotykały rtęci) i uruchomienie
licznika, których zastosowano w sumie 40.
Urządzenie to pozwoliło 8-krotnie przyspieszyć prace obliczeniowe zwią-
zane ze spisem powszechnym w roku 1890. Zadowolony z odniesionego suk-
cesu Hollerith założył w 1896 przedsiębiorstwo Tabulating Machine Com-
pany, które w 1917 przekształciło się w International Business Machine,
czyli dzisiejszą firmę IBM.
Po sukcesach Hollerith’a powstało jeszcze kilka firm, które wykorzysty-
wały do sterowania maszyn obliczeniowych karty perforowane, istniejące do
dziś to Bull, NCR, Bell.
Popularność kart perforowanych doprowadziła do ich znormalizowania,
co z kolei spowodowało, że stały się one przez wiele dziesięcioleci uniwersal-
nym nośnikiem informacji i to zarówno w sensie danych do obliczeń, zapisy-
wania programów, jak i ostatecznie pamiętania wyników tych programów.
1.2.3
Wiek XX
Jedną z najbardziej znanych i zasłużonych postaci historii informatyki jest
Alan Turing (1912-1954). Swoją sławę zawdzięcza opublikowaniu w 1936
roku pracy opisującej tok myślenia prowadzący od obliczeń ręcznych do
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.2 Historia informatyki
23
obliczeń zautomatyzowanych, wykonywanych przez bardzo prostą maszynę,
zwaną maszyną Turinga. Z uwagi na wielkie znaczenie tej maszyny dla
informatyki teoretycznej poświęcimy jej więcej miejsca w punkcie 3.1.
Od czasu drugiej wojny światowej, włączając w to kilka lat wcześniej-
szych, możemy mówić już o rozwoju technologii elektronicznej i co za tym
idzie rozwoju oraz miniaturyzacji komputerów.
W 1936 roku w Niemczech, Konrad Zuse tworzy maszynę Z1, następnie
Z2, a w końcu w 1941 roku maszynę Z3. Zadaniem tych wszystkich maszyn
były obliczenia dla potrzeb militarnych. Obliczenia te były wykonywane
na liczbach zapisanych w systemie dwójkowym (zob. 2.2.1) w reprezenta-
cji dziś zwanej zmiennoprzecinkową (zob. 3.5.5). Sterowanie odbywało się
za pomocą programu zapisanego na perforowanej taśmie filmowej. Budowę
tych maszyn charakteryzował brak części mechanicznych, występowały na-
tomiast przekaźniki elektromagnetyczne. Ostatni model maszyny Zusego
Z4 przetrwał i pracował, aż do końca lat pięćdziesiątych.
W 1937 rozpoczyna pracę zespół konstruktorów złożony z pracowników
firmy IBM, kierowany przez Howarda Aikena. Wynikiem ich prac było
zbudowanie w 1944 pierwszej automatycznej maszyny liczącej. Programo-
wanie tej maszyny polegało na odpowiednim łączeniu kabelkami gniazd w
specjalnej tablicy sterującej. Dane wprowadzano za pomocą kart dziur-
kowanych, wyniki wyprowadzano na taśmę perforowaną lub drukowano za
pomocą elektrycznych maszyn do pisania.
MARK I miał długość 17 metrów, wysokość 3 metry. Składał się z 760
tysięcy części w tym z 17480 lamp elektronowych. Obsługę stanowiło 10
osób. Wykonywał 3.5 dodawania na sekundę oraz 1 dzielenie na 11 sekund.
Częstotliwość pracy wynosiła 100 kHz. Szacowano, iż zastępuje on pracę
100 rachmistrzów wyposażonych w arytmometr mechaniczny.
W 1942 zespół specjalistów pod kierunkiem J.W. Mauchley’ego i J.P.
Eckert’a projektuje i buduje maszynę ENIAC (ang. Electronic Numeri-
cal Integrator And Computer). Jest to pierwsza maszyna w której użyto
wyłącznie elementy elektroniczne (lampy elektronowych), i uznawana jest
powszechnie za pierwszy kalkulator elektroniczny. Dopiero w 1976 roku oka-
zało się, że przed nią zostały uruchomione w Anglii maszyny Colos I i Colos
II. Programowanie ENIAC’a polegało na ręcznym ustawianiu przełączników
oraz wymianie specjalnych tablic programowych. Długość komputera wy-
nosiła 15 metrów, jego szerokość to 9 metrów, waga 30 ton, składał się z
około 18000 lamp elektronowych. Liczby były pamiętane w systemie dzie-
siętnym, był on w stanie wykonać 5000 dodawań na sekundę, oraz od 50 do
360 dzieleń na sekundę.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
24
Wstęp
W 1946 roku do projektu EDVAC (ang. Electronic Discrete Variable
Automatic Computer) przyłącza się John von Neumann (1903-1957), który
inspiruje uczestników projektu do budowy komputera w którym wyelimino-
wane byłyby wady poprzednika. Do najważniejszych z nich należy zaliczyć
wysoką awaryjność, oraz dużą uciążliwość procesu programowania. Neu-
mann zaproponował architekturę, według której są budowane komputery do
dnia dzisiejszego, została ona nazwana von neumannowską. Architektura
ta była wynikiem pracy Johna von Neumann’a nad problemem przechowy-
wania w pamięci komputera zarówno danych podlegających przetwarzaniu,
jak i programu, który na tych danych miał działać. Prace te umożliwiły
odejście od sztywnych metod programowania sprzętowego (przełączanie ka-
belków, czy zworek) i zastąpienie ich programowaniem wewnętrznym, po-
przez umieszczenie w pamięci maszyny programu sterującego przetwarza-
niem danych.
Architektura von neumannowska wyróżniała następujące elementy skła-
dowe: pamięć złożona z elementów przyjmujących stany 0 i 1, arytmometr
wykonujący działania arytmetyczno–logiczne, jednostki sterującej. Sterowa-
nie odbywało się za pomocą programu, który był umieszczany w pamięci.
Stanowiło to duży skok ideowy w stosunku do wcześniejszych koncepcji, w
których program był zapisywany na kartach perforowanych i bezpośrednio
z nich odczytywany oraz uruchamiany. W maszynie von neumannowskiej
program jak i dane znajdował się w pamięci fizycznej, sam program mógł
modyfikować zawartość pamięci fizycznej, a co za tym idzie mógł sam się
modyfikować. Program składał się z ciągu instrukcji, które były pobierane
i rozpoznawane przez jednostkę sterującą w takt zegara taktującego pracą
całego komputera. Instrukcje te musiały odpowiadać poleceniom zakodowa-
nym przez twórców układu elektronicznego. Taka idea powodowała, że nie
było już różnicy pomiędzy danymi a rozkazami, wszystkie one były kodo-
wane za pomocą systemu binarnego. Widać bardzo duże podobieństwo do
budowy maszyny Turinga (zob. 3.1), co nie powinno dziwić, gdyż Neumann
znał doskonale wyniki Turinga.
Maszyną skonstruowaną w oparciu o tę teorię był również EDSAC (1949,
Anglia). Pierwszą maszyną zastosowaną do przetwarzania danych cywilnych
był komputer UNIVAC, za pomocą którego podobno przewidziano zwycię-
stwo D. Eisenhowera w wyborach prezydenckich w 1952 roku.
Mówiąc o rozwoju komputerów trudno nie wspomnieć o początkach kom-
puterów osobistych. Pierwszym komputerem tej klasy był Altair wyprodu-
kowany w 1975 roku przez firmę MITS. Wyposażony w 8-bitowy procesor
Intel 8080 oraz 256 bajtów pamięci, pozbawiony klawiatury, monitora, na-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.2 Historia informatyki
25
pędu taśmowego, stał się niezwykle popularny wśród osób zajmujących się
do tej pory elektroniką. Młody Bill Gates napisał dla niego język BA-
SIC (ang. Beginner’s All Purpose Symbolic Instruction Code). Mimo wielu
ograniczeń Altair zyskał ogromną popularność czego konsekwencją było po-
wstawanie coraz większej ilości firm produkujących tego rodzaju „zabawki”
— tak wówczas nazywano te urządzenia i tak o nich myślano. Praktycz-
nie wszystkie one działały pod kontrolą systemu operacyjnego nazywanego
CP/M (ang. Control Program/Monitor lub Control Program for Microcom-
puter) i wyprodukowanego przez małą kalifornijską firmę Digital Research.
Na skutek dużego zainteresowania rynku urządzeniami takiego typu, po-
wstają produkowane przez IBM komputery PC (ang. Personal Computer),
od których wzięła się nazwa jakby klasy — mówimy dziś „komputer PC” lub
„komputer klasy PC”. Należy tu jednak oddać sprawiedliwość i powiedzieć,
że przed komputerem firmy IBM, powstał inny o nazwie komputer Apple
II, który był pierwszy z całej gamy „jabłuszek” do dziś znanych i bardzo
popularnych choć głównie na rynku amerykańskim. Co ciekawe komputery
Apple a później Macintosh dużo wcześniej od komputerów PC posiadały
interfejs graficzny, bo od roku 1985. Inna też była architektura: IBM PC
były i do dziś są oparte o rodzinę procesorów firmy INTEL
6
, zaś Apple
przez długie lata był związany z rodziną procesorów Motoroli, a obecnie
także PowerPC.
Na koniec tego krótkiego przeglądu wydarzeń z historii informatyki przed-
stawiamy zestawienie wybranych dat z historii rozwoju komputerów obecnej
generacji opartych na krzemie.
1947 wynalezienie tranzystora — pierwszego i podstawowego składnika
elektroniki cyfrowej i analogowej;
1958 wynalezienie układu scalonego — jest to układ, który zawiera w so-
bie tranzystory zamknięte w jednej obudowie i realizujące pewne kon-
kretne funkcje;
1964 komputer IBM S/360 — pierwszy superkomputer zwany do dziś Ma-
inframe;
1964 graficzny interfejs użytkowy i mysz;
1971 INTEL 4004 — zawierał 2.3 tys. tranzystorów, był taktowany zega-
rem 740 kHz, mógł zaadresować 1 kB pamięci dla danych oraz 4kB
pamięci programu;
6
Lub procesorów innych firm, ale kompatybilnych z procesorami INTEL, np. AMD.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
26
Wstęp
1972 INTEL 8008 — zawierał 3.5 tys. tranzystorów, mógł zaadresować do
16 kB RAM;
1974 INTEL 8080 — zawierał 4.8 tys. tranzystorów, mógł zaadresować do
64 kB RAM, lista poleceń składała się z 75 rozkazów;
1975 Altair 8800 – pierwszy komputer domowy oparty na procesorze IN-
TEL 8080, posiadał 256 bajtów RAM;
1976 procesor Zilog Z80 – modyfikacja INTEL 8080, lista poleceń zawierała
176 rozkazów, prędkość zegara wynosiła 4 MHz;
1976 procesor INTEL 8086 i 8088;
1977 komputer Apple II;
1979 procesor Motorola 68000;
1981 komputer IBM PC — pierwszy komputer rozpoczynający całą ro-
dzinę istniejących do dziś komputerów osobistych (ang. Personal
Computer), był oparty na procesorze 8088, posiadał 64 kB RAM;
1982 procesor INTEL 80286 — zawierał 134 tys. tranzystorów, mógł za-
adresować do 16 MB RAM, był taktowany zegarem 6 MHz;
1983 komputer PC XT — oparty na procesorze INTEL 8086;
1984 komputer PC AT — oparty na procesorze INTEL 80286;
1985 procesor INTEL 80386 — zawierał 275 tys. tranzystorów, był takto-
wany zegarem 16 MHz;
1989 procesor INTEL 80486 — zawierał 1.18 mln tranzystorów, był tak-
towany zegarem 25 MHz;
1992 procesor Power PC — zawierał 2,8 mln tranzystorów, początkowo był
taktowany zegarem 66 MHz;
1993 procesor INTEL Pentium — zawierał 3.1 mln tranzystorów, począt-
kowo był taktowany zegarem 60 MHz;
1993 procesor DEC Alpha — zawierał 1.7 mln tranzystorów, 300 MHz;
1995 procesor INTEL Pentium Pro — 5.5 mln tranzystorów, był taktowany
zegarem 200 MHz;
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.3 Zastosowanie i przyszłość
27
1996 procesor INTEL Pentium MMX;
1997 procesor INTEL Pentium II — zawierał 7.5 mln tranzystorów, po-
czątkowo był taktowany zegarem 300 MHz;
1999 procesor INTEL Pentium III — zawierał 9.9 mln tranzystorów, po-
czątkowo był taktowany zegarem 600 MHz;
Tym oto sposobem proste urządzenie wspomagające obliczenia, na prze-
strzeni wieków przekształciło się w urządzenie wspomagające przetwarzanie
danych, a często też służące rozrywce.
Z pewnością dzisiejszy komputer jest bardziej złożony technologicznie od
liczydła, lecz jego rola pozostała w dużej części niezmienna: jego zadaniem
jest przetwarzanie danych, nawet jeśli tymi danymi będą kolejne plansze
gry.
1.3
Zastosowanie i przyszłość
A choć początki twoje były liche, ostatki świetne będą.
Księga Hioba (przekład Cz. Miłosza)
Obecnie coraz trudniej wyobrazić sobie jakąkolwiek dziedzinę życia bez
choćby najmniejszej obecności komputera, a w przyszłości sytuacja ta się
jeszcze bardziej nasili. Wystarczy wymienić niektóre tylko dziedziny oraz
zastosowanie tam informatyki:
• Nauka
– Nauki ścisłe - narzędzie do wspomagania obliczeń, edytor prac
naukowych, umożliwienie szybszego kontaktu ze światem.
– Nauki humanistyczne - inteligentne bazy danych, bazy wiedzy,
edytory prac naukowych, kontakt ze światem.
• Przemysł
– Elektronika - projektowanie układów, wspomaganie obliczeń, ana-
liza poprawności zaprojektowanych obwodów.
– Chemia i farmacja - modelowanie procesów laboratoryjnych, wspo-
maganie obliczeń.
– Biologia, biochemia - bazy wiedzy, modelowanie cząsteczek, ana-
liza DNA lub RNA.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
28
Wstęp
– Aplikacje CAD/CAM - komputerowe wspomaganie projektowa-
nia i modelowania, wykorzystywane głownie przez inżynierów
konstruktorów czy architektów, np. AutoCAD.
• Zastosowania cywilne
– Modelowanie i przewidywanie zmian pogody czy prądów oce-
anicznych.
– Wspomaganie kierowania ruchem lotniczym, kolejowym czy mor-
skim.
– Projektowanie dróg, mostów, tuneli, kolei żelaznych.
• Zastosowania militarne
– Sterowanie systemem obrony.
– Zdalne naprowadzanie pocisków.
• Biznes
– Aplikacje finansowe i ekonomiczne.
– Aplikacje biurowe.
– Systemy eksperckie i systemy wspomagania podejmowania decy-
zji.
Z pewnością przyszłość informatyki będzie związana z rozwojem tech-
nologii kolejnych generacji komputerów. Co więcej same komputery, jak i
technologia ich wykonania mogą się zmienić. Dość nadmienić, że już dziś
prowadzone są próby konstruowania komputerów biologicznych, czyli
takich, w których rolę tranzystora będzie pełniło białko.
Możemy stwierdzić jedynie, że charakter procesów przetwarzanych przez
te komputery nie zmieni się, lecz sposób ich wykonania może ulec modyfi-
kacji. Od wielu lat prowadzi się badania i wdraża przetwarzanie potokowe,
rozproszone oraz równoległe. Wszystkie te pojęcia, za którymi stają techno-
logie, są związane z wysiłkami człowieka, mającymi na celu przyśpieszenie
przetwarzania informacji, a w efekcie uzyskanie wyniku w krótszym czasie.
Cała historia informatyki, a w szczególności jej niesłychanie dynamiczny
rozwój przez ostatnie 40 lat, pozwala snuć wręcz bajeczne wizje dotyczące
przyszłych zastosowań komputerów. Niemniej jednak, należy pamiętać, że
za tym wszystkim stoi człowiek i to od jego mądrości i dalekowzroczności
będzie zależało, czy przyszłe rozwiązania będą służyły nam efektywnie, czy
też staną się dla nas balastem i niechcianą koniecznością.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.4 Kierunki współczesnej informatyki
29
1.4
Kierunki współczesnej informatyki
Adde parvum parvo magnus acervus erit.
(Jeśli będziesz dodawał małe do małego, to zbierze się wielka sterta.)
Owidiusz
Obecnie informatyka jest na tyle szeroką dyscypliną naukową, że po-
dobnie, jak w matematyce, fizyce czy chemii, nie ma już „specjalistów od
wszystkiego”. Zatem pojawiają się specjalności, które skupiają się wokół
jednego bądź kilku zagadnień. Z faktu ogromnej dynamiki rozwoju infor-
matyki wynika często, że osoby uprawiające dany dział muszą poświęcać
mu tyle czasu, że nie mają już możliwości śledzić tego co dzieje się poza ich
poletkiem. Poniżej zamieszczamy jedną z możliwych klasyfikacji dziedzin
informatyki wymienionych w kolejności alfabetycznej.
1.4.1
Algorytmika
Algorytmika jest jedną z najstarszych dziedzin informatyki, wynika to bez-
pośrednio z zakresu jaki obejmuje, a jest nim tworzenie i badanie algoryt-
mów. Poprzez badanie algorytmów rozumie się głównie zagadnienia zwią-
zane z teorią obliczalności, dzięki której można stwierdzić czy dany algorytm
da się w ogóle zrealizować w praktyce, a jeśli tak, to w jakim czasie
7
. Na-
leży podkreślić, że jest to jeden z działów, który swoim zakresem przenika
prawie wszystkie inne, oraz niejednokrotnie wykracza poza samą informa-
tykę, wnikając mocno w matematykę, technikę czy ekonomię. Patrząc na
historię algorytmiki okazuje się, że najbardziej fundamentalne prace z teorii
algorytmów pojawiły się w w latach trzydziestych. Można się temu dziwić,
gdyż jak to wynikało z rysu historii informatyki, wtedy nie istniał jeszcze
żaden komputer elektronowy a już na pewno elektroniczny. Jednak nie ma
w tym nic niezwykłego, algorytmika w swoim aspekcie teoretycznym nie po-
trzebuje w ogóle, lub tylko w minimalnym stopniu komputerów. To właśnie
w latach trzydziestych Alan Turing formułuje założenia Maszyny Turinga
(zob. 3.1) oraz wykorzystuje ją do formułowania teorii obliczalności [Tur36].
Stephen Kleene opisuje formalnie spójną klasę rekurencyjnie definiowalnych
funkcji teorioliczbowych [Kle36]. Z kolei Alonzo Church wymyśla inny spo-
sób opisu algorytmów, tzw. rachunek λ [Chu41]. Nieco później, bo w roku
1961, Andriej Markow proponuje jeszcze inny sposób opisu algorytmów —
opis oparty na łańcuchach [Mar54].
7
Istnieje cała klasa algorytmów, które są poprawne i wiemy, że dają dobre rezultaty
ale na przykład po 3000 lat.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
30
Wstęp
Zarys algorytmiki znajduje się w rozdziale 5.
1.4.2
Bazy danych
W obecnym świecie żyjemy w zalewie informacji, którą należy przetworzyć i
tym zajmują się wspomniane wcześniej algorytmy, ale również należy gdzieś
tę informację magazynować. A jeśli magazynować to w taki sposób by łatwo
i szybko można było do niej sięgnąć i odnaleźć potrzebne dane. Rolę ta-
kiego inteligentnego magazynu spełniają bazy danych. Historycznie bazy
towarzyszyły informatykom od początku powstania komputerów, lecz róż-
niła się ich forma i sposób przechowywania informacji. Można by nawet
zaryzykować stwierdzenie, że już Hollerith opracowując nową metodę prze-
prowadzania spisu ludności posługiwał się bazą danych głosów w postaci
kart perforowanych i na ich podstawie opracowywał raporty. Pojawienie się
komputery jakie znamy obecnie dało też początek bazom danych z praw-
dziwego zdarzenia. Z początku były to bardzo prymitywne technologie, do
których można zaliczyć bazy hierarchiczne i bazy sieciowe. Posiadały one
wiele wad, jak np. nadmiarowość danych, czy brak integralności. Pod ko-
niec lat sześćdziesiątych matematyk E. F. Codd, pracujący w firmie IBM
stworzył model relacyjnej bazy danych. Idee tego modelu opisał w pracy
[Coo70]. Obecnie przede wszystkim wykorzystuje się relacyjne bazy danych,
lecz od ponad 15 lat bardzo dynamicznie rozwijają się obiektowe bazy da-
nych, w których daje się, lepiej niż w relacyjnych, zamodelować pewne dane.
Do najnowszych trendów można również zaliczyć bazy oparte o technologię
XML.
W tym opracowaniu nie ma specjalnego miejsca przeznaczonego na bazy
danych, pewne informacje można znaleźć w ???.
1.4.3
Grafika komputerowa
Za datę powstania tego działu informatyki uznaje się lata pięćdziesiąte,
kiedy to w Massachusetts Institute of Technology zbudowano komputer
Whirlwind wyposażony w grafoskop. Przez ponad dwadzieścia lat dzie-
dzina ta była dostępna wyłącznie nielicznym, głównie ze względu na bardzo
wysokie koszty urządzeń, dość przypomnieć, że wszystkie terminale kom-
puterowe w tamtych czasach były alfanumeryczne, zatem mogły wyświetlać
wyłącznie znaki. W latach sześćdziesiątych widać już pewne zainteresowa-
nie przemysłu grafiką komputerową. General Motors wykorzystuje system
DEC-1 produkcji IBM do projektowania samochodów. W ich ślady idą pro-
ducenci samolotów oraz okrętów, a następnie praktycznie cały przemysł.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.4 Kierunki współczesnej informatyki
31
W dzisiejszych czasach trudno sobie wyobrazić nowoczesnego projek-
tanta bez elektronicznej deski kreślarskiej, i co ciekawe nie ma znaczenia
czy będzie to architekt, czy też projektant ubrań. Grafika komputerowa od-
daje ogromne usługi prawie w każdej dziedzinie współczesnego życia. Idąc
do architekta, można obejrzeć swój przyszły dom wręcz po nim „spaceru-
jąc”, idąc do fryzjera można zweryfikować czy fryzura nam proponowana
jest dla nas odpowiednia. Oczywiście trudno zapomnieć o całym przemyśle
rozrywkowym, czyli grach i wszelkiego rodzaju multimediach, które coraz
chętniej sięgają po tzw. produkty interaktywne.
Wszystko to wymaga wsparcia od strony komputera zarówno od strony
sprzętowej jak i programowej. Widać to wyraźnie w cenach elementów wcho-
dzących w skład komputera, bardzo dobra karta graficzna potrafi kosztować
tyle co reszta komputera. Aby wszystkie te programy działały bardzo wy-
dajnie wymagają udoskonalania algorytmów do generowania obrazu.
1.4.4
Kryptografia
Odkąd sięga pamięć ludzka, to co cenne próbowano ukryć przed wzrokiem
czy dotykiem osób niepowołanych. Ponad 2000 lat temu dostrzeżono ko-
nieczność ukrywania informacji, na ten okres datuje się pierwszy znanym
szyfrem — szyfr Cezara. W chwili obecnej trudno sobie wyobrazić trans-
misję jakichkolwiek ważniejszych danych w komputerach bez stosowania
transmisji szyfrowanej przez protokół SSL. Większość programów pocz-
towych zawiera już wsparcie do szyfrowanego połączenia, a łącząc się z
bankiem w celu sprawdzenia stanu konta, serwer banku wymusza na prze-
glądarce połączanie za pomocą protokołu https, który jest niczym innym
jak zwykłym protokołem http „przepuszczanym” przez SSL.
Dziedzina wiedzy zajmująca się badaniem, tworzeniem i łamaniem szy-
frów to właśnie kryptografia. Jej gwałtowny rozwój zaczął się od roku
1975 i do dzisiejszego momentu pozostaje jedną z najdynamiczniej rozwija-
jących się dziedzin. Należy zaznaczyć, że jest ona przede wszystkim dzie-
dziną matematyki. Ponieważ jednak tak powszechnie jest wykorzystywana
w ochronie informacji stąd też badaniem jej zajmują się również informa-
tycy.
1.4.5
Programowanie
Programowanie jest jednym z działów informatyki, który jest właśnie z nią
kojarzony, nawet przez osoby niedoświadczone. Do niedawna samo stwier-
dzenie „Jestem programistą”, brzmiało prawie jak „Jestem wszechmocny”.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
32
Wstęp
Faktem jest, że języki programowania, będące jednym z elementów całości
zagadnienia związanego z programowaniem, powstały zaraz na początku
współczesnej historii informatyki. Chodź jak wiemy, możemy dopatrywać
się ich korzeni jeszcze wcześniej przy okazji maszyna analitycznej Babbage’a
oraz Pani hrabiny Ady. Niemniej jednak, języki programowania w formie
w jakiej je znamy obecnie, a raczej dziadkowie dzisiejszych języków pro-
gramowania, pojawiły się w momencie powstania idei maszyny von neu-
mannowskiej, która pozwalała zapamiętywać dane i program jednocześnie
w pamięci. Można zatem przyjąć za początek powstania współczesnych ję-
zyków programowania lata pięćdziesiąte ubiegłego wieku. Bezspornym jest,
że języki bardzo się zmieniły od tamtego czasu, choć ich cel pozostał taki
sam. Jest nim dostarczenie wygodnej formy przekazu naszych myśli do kom-
putera w celu uzyskania pewnego konkretnego efektu. Oczywiście sposób
zapisu, czyli wyrażania naszych myśli musi być odpowiednio precyzyjny, ale
ta tematyka jest szerzej omawiana w rozdziale 6.
Programowanie to jednak nie tylko języki programowania, to również
wszelkiego rodzaju narzędzia wspomagające proces wytwarzania oprogra-
mowania, tworzenia dokumentacji technicznej czy dokumentacji użytkow-
nika. Co więcej cały proces tworzenia oprogramowania doczekał się wielu
modeli i sposobów analizowania oraz porównywania, które z nich są lepsze i
w jakich sytuacjach. Powstała oddzielna gałąź informatyki pod nazwą inży-
nieria oprogramowania, której zadaniem jest właśnie systematyzowanie
i badanie procesów związanych z tworzeniem oprogramowania.
1.4.6
Sieci komputerowe
W chwili obecnej sieci komputerowe są jednym z najlepiej ugruntowanych
działów informatyki. Ich korzenie sięgają 1957 roku kiedy to Departa-
ment Stanu USA powołał do życia Agencję Zaawansowanych Projektów
Badawczych Departamentu Obrony USA (ang. Advanced Research Projects
Agency, (ARPA)). Jednym z jej celów było opracowanie takiej formy komu-
nikacji komputerów, która byłaby wygodna a jednocześnie odporna na ataki
militarne. Pod koniec 1969 roku stworzono eksperymentalną sieć opartą na
wymianie pakietów danych, projekt ten pod nazwą ARPANET wykorzy-
stywał protokół NCP (ang. Network Control Protocol). Umożliwiał on
logowanie na zdalnym komputerze, drukowanie na zdalnej drukarce oraz
przesyłanie plików. Na początku rozwój sieci nie był zbyt dynamiczny, dla
przykładu w 1973 roku ARPANET składała się z 23 komputerów. Dzisiejszą
siłę sieć zawdzięcza globalizacji, która była możliwa dzięki zastosowaniu jej
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.4 Kierunki współczesnej informatyki
33
do celów cywilnych. Zaczęto dostrzegać, że można ją wykorzystywać do uła-
twienia komunikacji na prawie wszystkich płaszczyznach. I tak w 1972 roku
zostaje wysłana pierwsza wiadomość elektroniczna (E-mail), której autorem
i pomysłodawcą idei był Roy Tomilnson. W 1974 roku zostaje opracowany
stos protokołów TCP/IP, który został w tym samym roku uznany oficjal-
nym protokołem w sieci i pozostaje nim do dnia dzisiejszego. Autorami
tej idei byli Vinton Cerf oraz Robert Kahn. Mimo tych sukcesów wciąż są
to technologie drogie i niedostępne dla przeciętnego użytkownika. W 1980
roku ARPANET liczy 400 serwerów. Jednak wydarzenia nabierają tempa,
już dziewięć lat później sieć przekroczyła 100 000 komputerów. Stało się to
głównie za sprawą przyłączenia się do poparcia tej idei Narodowej Fundacji
Nauki USA (ang. National Science Foundation), która stworzyła własną
sieć NFSNET i dołączyła się do istniejących. Sieć ta stała się na tyle wy-
dajna, że w roku 1990 zastąpiła całkowicie ARPANET i stała się oficjalnym
szkieletem Internetu
8
. Z pewnością większość użytkowników kojarzy Inter-
net z dwoma usługami: pocztą elektroniczną i stronami WWW. Jednak o
ile poczta jest usługą wiekową (jak na historię sieci) to WWW powstało
dopiero w 1992 roku, a technologię tę opracował Tim Berners-Lee.
Należy pamiętać, że sieci komputerowe to nie tylko Internet, w ich skład
wchodzą również sieci lokalne, czy osiedlowe. Ponadto dziedzina ta zajmuje
się również badaniem wydajności sieci i opracowywaniem nowych algoryt-
mów do przekazywania w niej informacji. W połączeniu z kryptografią dba
o bezpieczeństwo przesyłanej informacji niezależnie od jej nośnika, a obecnie
poza tzw. przewodem, transmisja danych odbywa się za pomocą: podczer-
wieni, promieni laserowych, czy fal radiowych.
Zarys zagadnień sieci komputerowych znajduje się w rozdziale 8.
1.4.7
Systemy operacyjne
System operacyjny jest wyspecjalizowanym programem, który zapewnia
sprawne funkcjonowanie systemu komputerowego. Jest to program ściśle
związany z architekturą konkretnego komputera w tym przede wszystkim
z procesorem. Głównym zadaniem systemu operacyjnego jest dostarczanie
podstawowych operacji dostępu do urządzeń i zasobów systemu komputero-
wego. Od jego jakości i wydajności w dużej mierze zależy wydajność całości
systemu komputerowego. W dniu dzisiejszym istnieje cała gama systemów
8
Polska została przyłączona do tego szkieletu w 1991 roku.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
34
Wstęp
operacyjnych na komputery klasy PC
9
oparte o procesory rodziny INTEL
10
.
Przykładowymi systemami dla takich komputerów są MS-DOS, rodzina sys-
temów Windows, Linux, rodzina BSD, kilka komercyjnych systemów klasy
UNIX. Co więcej systemy rodziny UNIX, w tym Linux i BSD, są syste-
mami posiadającymi swoje wersje na inne wersje procesorów np. PowerPC.
Istnieje również cała gama systemów operacyjnych specjalizowanych na kon-
kretną maszynę i przeznaczonych do specjalnych celów, przykładami mogą
tu być AS/400 czy OS/390.
Trudno dzisiaj powiedzieć, który system był tym pierwszym. Wiemy
na pewno, że w roku 1964 w firmie IBM zaczęto tworzenie systemu ope-
racyjnego z przeznaczeniem na komputery MainFrame, bardzo złożonego i
wydajnego systemu operacyjnego dla maszyn S/360 i ich późniejszych na-
stępców. Były to ogromne komputery przeznaczone do ciągłej pracy i naj-
wyższego obciążenia, projektowane z myślą o profesjonalnych systemach.
Nie mniej jednak IBM wcześniej również pisał prostsze systemy operacyjne
(patrz 7.10.5). Z kolei historia rodziny UNIX sięga roku 1965, kiedy to trzy
organizacje Bell Telephone Laboratories, General Electric Company i Mas-
sachusetts Institute of Technology w ramach projektu MAC podjęły próbę
stworzenia systemu operacyjnego nazwanego Multics. Zadaniem tego sys-
temu było dostarczenie mechanizmów pozwalających na dostęp jednoczesny
do danego komputera przez wielu użytkowników oraz wsparcie do obliczeń
i współdzielenia danych pomiędzy jego użytkownikami. Niestety prace nad
tym systemem nie zostały zakończony i ponieważ nic nie wskazywało, że
kiedykolwiek to nastąpi, Bell Laboratories odłączyło się od tego projektu
i ok roku 1970 stworzyło pierwszą wersję systemu UNIX pracującego na
maszynach PDP-11. W chwili obecnej zarówno OS/390 jak i UNIX istnieją
jako dojrzałe i profesjonalne systemy operacyjne.
Niejako na drugim końcu stoją systemy takie jak rodzina Windows i Ma-
cOS, które od samego początku były projektowane jako systemy nastawione
na łatwość obsługi i przeznaczone na popularne komputery. Co prawda ist-
nieją obecnie wersje zarówno Windows jak i MacOS z przeznaczeniem na
serwery, jednak nie to było ich pierwotnym przeznaczeniem.
Szerszy opis systemów operacyjnych znajduje się w rozdziale 7.
9
PC (ang. Personal Computer) komputer osobisty, ogólnego przeznaczenia.
10
Mówiąc „rodzina INTEL” mamy na myśli procesory tej firmy oraz innych firm kom-
patybilne (zgodne) z nimi na poziomie listy rozkazów, przykładem może być rodzina
procesorów firmy AMD.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.4 Kierunki współczesnej informatyki
35
1.4.8
Sztuczna inteligencja
Pomimo, iż termin sztuczna inteligencja (ang. Artificial Intelligence)
powstał stosunkowo niedawno, to próby stworzenia urządzeń inteligentnych
sięgają dość daleko wstecz. Za pierwsze należy zapewne uznać wysiłki zmie-
rzające w kierunku skonstruowania automatu potrafiącego grać w szachy,
które niestety ze względu na niedostatki w rozwoju ówczesnej techniki, naj-
częściej okazywały się mniej lub bardziej zręcznymi oszustwami.
Pierwsza połowa XX wieku, to okres upływający pod znakiem „robo-
tyzacji” i pierwsze wizje maszyn wyglądających i zachowujących się jak
ludzie. Pod koniec lat 50-tych stajemy się świadkami narodzin informatyki
jako dyscypliny nauki. Nauki zajmującej się przetwarzaniem danych i wy-
korzystującej w tym celu nowe urządzenie nazwane komputerem. Wkrótce,
na fali ogólnoświatowego zachwytu nad możliwościami jakie otworzył on
przed nami, powstają pierwsze proste programy zdolne do zadawania pytań
i udzielania odpowiedzi na pytania zadane przez człowieka. Dziś jednak
wcale nie jest łatwo powiedzieć czym jest inteligencja?; w znacznej mierze
jest to spowodowane brakiem zrozumienia natury ludzkiego mózgu.
Przez lata pojęcie sztucznej inteligencji ulegało przeobrażeniom, zależnie
od bieżącego stanu rozwoju myśli ludzkiej — począwszy od automatu do
grania, przez maszynę potrafiącą wykonywać pewne czynności za człowieka
aż po urządzenie zdolne samodzielnie podejmować decyzje. Nie podejmu-
jemy się w tym miejscu udzielić odpowiedzi na to pytanie. Zamiast tego po-
wiemy czego oczekuje się obecnie od sztucznej inteligencji. Otóż celem jest
rozwój w kierunku stworzenia systemu, który potrafiłby zachowywać się jak
istota inteligentna, tj. na podstawie zgromadzonej wiedzy i znanych przesła-
nek podejmowałby decyzje wykazujące znamiona racjonalności. Pragniemy
podkreślić ogólność ostatniego stwierdzenia. Pod terminem „system” można
rozumieć program komputerowy, maszynę lub . . . cokolwiek innego. Rów-
nież pojęcia „wiedza”, „racjonalność” są tak samo mało precyzyjne jak i
sam termin „inteligencja”.
Sztuczna inteligencja jako nauka ukierunkowana na stworzenie systemu
naśladującego istoty rozumne z istoty rzeczy korzysta z opisu pewnych ich
zachowań, budowy czy obserwowanych mechanizmów nimi rządzących. Nie
dziwi zatem prowadzenie badań związanych ze sztucznymi sieciami neu-
ronowymi, algorytmami genetycznymi, systemami działającymi w oparciu
o logikę rozmytą, czy też badających zachowania populacji — algorytmy
mrówkowe, algorytmy symulujące rój pszczół itp. Można powiedzieć, że za-
kres badań obejmuje wszystko „co się rusza”. Tak jest w istocie a wynika to
z komplementarności tych poddziedzin sztucznej inteligencji. Na przykład
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
36
Wstęp
sztuczne sieci neuronowe stosują stochastyczne algorytmy dopasowania mo-
deli poprzez uczenie nadzorowane lub nie, opierające się na nieprecyzyjnych
(obarczonych pewnym błędem, tzw. szumem) danych numerycznych. Zła-
godzenie wymogów precyzji w procesie tworzenia modeli, a co najważniejsze
dla nas ludzi, możliwość opisu złożonych systemów za pomocą zmiennych
pojmowanych intuicyjnie (na przykład: lodowato, zimno, w sam raz, ciepło,
gorąco) to z kolei zaleta systemów przetwarzających informacje w oparciu o
zbiory rozmyte i wnioskowanie przybliżone. Połączenie obu wspomnianych
wyżej dziedzin pozwala na stworzenie systemu operującego nieprecyzyjnymi
określeniami zależnymi od zaistniałego kontekstu (logika rozmyta) oraz jed-
nocześnie zdolnego do uczenia się (sztuczne sieci neuronowe). Doskonałym
ich uzupełnieniem stają się algorytmy genetyczne poszukujące optymalnego
rozwiązania (na przykład parametrów sieci neuronowej) na drodze kolej-
nych przybliżeń dobieranych poprzez wykorzystanie mechanizmów mutacji
i krzyżowania chromosomów oraz oceny przez tak zwaną funkcję przystoso-
wania.
Jak więc widać, sztuczna inteligencja to bardzo szeroka dziedzina wiedzy
łącząca w sobie matematykę, biologię, fizykę chemię, filozofię, lingwistykę,
. . . , o której precyzyjnie za wiele powiedzieć nie można. Pewne jedynie
jest to, że na dzień dzisiejszy w związku z nią zadajemy więcej pytań niż
otrzymujemy odpowiedzi.
1.4.9
Teoria informacji
Teoria informacji jest jedną z niewielu dziedzin dla których znamy do-
kładną datę narodzin. Jest to rok 1948 kiedy to 32-letni matematyk Claude
Shannon publikuje pracę w piśmie Bell System Technical Journal. Ta wła-
śnie praca uznawana jest za podstawową w tej dziedzinie, jednak zanim
opiszemy wyniki Shannona, spróbujmy ogólnie opowiedzieć czym zajmuje
się ta dziedzina.
Teoria informacji zajmuje się informacją, jej transmisją, jak i również
kodowaniem danych w celu pewniejszego lub szybszego przesłania jej od
nadawcy do odbiorcy. Kodowanie nie należy tu mylić z szyfrowaniem, gdyż
nie jest celem tutaj ukrycie informacji, a wyłącznie zapewnienie, że dotrze
ona do celu w całości lub jeśli nastąpi przekłamanie to o tym się dowiemy.
Najprostszym kodem jaki większość zna jest kod Morse’a, który został skon-
struowany by za pomocą bardzo skromnego zbioru znaków (kropka, kreska)
móc przekazać całe zdania dowolnego języka opartego o litery łacińskie.
Należy podkreślić, że próba przekazania jakiejkolwiek informacji przez
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
1.5 Zadania
37
dowolny nośnik może się nie powieść, lub informacja może zostać zniekształ-
cona. Chyba każdy z nas pamięta dziecięcą zabawę w głuchy telefon, po-
dobnie jest w przypadku rozmowy przez zwykły analogowy telefon, słychać
trzaski i czasami słowa dochodzą zniekształcone. Shannon w swojej pracy
podał warunki jakie muszą być spełnione by informacja dotarła bez znie-
kształceń, co więcej pokazał on drogę w jaki sposób przekazać informację
lepiej bez zmiany parametrów kanału transmisyjnego.
Zarys teorii informacji znajduje się w rozdziale 4.
1.5
Zadania
1. Wymień kluczowe postacie z historii informatyki wraz z ich dokona-
niami? Spróbuj ustawić je chronologicznie.
2. Wymień dwie dziedziny informatyki i krótko je scharakteryzuj.
3. Spróbuj wyjaśnić wpływ komputerów na dzisiejszą informatykę.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
38
Wstęp
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 2
Podstawowe pojęcia
i definicje
Nie przejmuj się, jeśli masz problemy z matematyką.
Zapewniam Cię, że ja mam jeszcze większe.
Albert Einstein
2.1
Algebra Boole’a
Przy projektowaniu i analizowaniu układów cyfrowych w komputerach i
innych systemach cyfrowych stosuje się algebrę Boole’a. Nazwa pochodzi
od nazwiska matematyka George’a Boole’a, który zaproponował jej podsta-
wowe zasady w traktacie zatytułowanym An Investigation of The Laws of
Thought on Which to Found the Mathematical Theories of Logic and Proba-
bilities (Badanie praw myśli, które mogą być podstawą matematycznych teo-
rii logiki i prawdopodobieństwa). W roku 1938 Claude Shannon zasugerował
zastosowanie algebry Boole’a do rozwiązywania problemów projektowania
układów przekaźnikowych. Metody tej użyto następnie do analizowania i
projektowania elektronicznych układów cyfrowych. W konsekwencji, dzisiej-
sze komputery jako urządzenia działające w oparciu o elektronikę cyfrową,
pracują wykorzystując algebrę Boole’a.
2.1.1
Definicja ogólna
Niech dany będzie niepusty zbiór B, w którym wyróżnione są dwa elementy
0, 1. W zbiorze tym określamy działania sumy logicznej „+”, iloczynu
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
40
Podstawowe pojęcia i definicje
logicznego „·”
1
oraz dopełnienia logicznego „
−
”. Przyjmuje się, że priory-
tet powyższych działań określa, że działanie dopełnienia ma pierwszeństwo
przed iloczynem, zaś działanie iloczynu ma pierwszeństwo przed działaniem
sumy.
Algebrą Boole’a nazywamy zbiór B wraz z powyższymi działaniami i
taki, że dla dowolnych elementów x, y, z ∈ B zachodzą następujące prawa:
Prawa przemienności
x + y = y + x
(2.1)
x · y = y · x
(2.2)
Prawa łączności
(x + y) + z = x + (y + z)
(2.3)
(x · y) · z = x · (y · z)
(2.4)
Prawa rozdzielności
x + (y · z) = (x + y) · (x + z)
(2.5)
x · (y + z) = (x · y) + (x · z)
(2.6)
Prawa identyczności
x + 0 = x
(2.7)
x · 1 = x
(2.8)
Prawa dopełnienia
x + x = 1
(2.9)
x · x = 0
(2.10)
Zauważmy, że jeśli w powyższych prawach zamienione zostaną odpo-
wiednio działania sumy i iloczynu oraz jednocześnie elementy 0 i 1 to prawa
te dalej pozostaną w mocy, w wyniku otrzymamy ich drugą wersję. Dla
przykładu spójrzmy na wzór (2.1), jeśli w nim zamienimy znak „+” na „·”,
to otrzymamy prawo (2.2). Dzieje się tak, ponieważ własności we wszyst-
kich algebrach Boole’a są konsekwencjami powyższych praw. Zatem zasada
zamiany działań i elementów wyróżnionych obowiązuje w nich wszystkich
nie zmieniając własności wzorów. Powyższy fakt zwany jest zasadą dual-
ności.
1
W dalszej części będziemy często pomijali symbol „
·”, zatem zapis
AB
będzie równo-
ważny A
·
B
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.1 Algebra Boole’a
41
Twierdzenie 2.1. Następujące własności są prawdziwe w każdej algebrze
Boole’a:
Prawa idempotentności
x + x = x
(2.11)
x · x = x
(2.12)
Drugie prawa identyczności
x + 1 = 1
(2.13)
x · 0 = 0
(2.14)
Prawa pochłaniania
(x · y) + x = x
(2.15)
(x + y) · x = x
(2.16)
Dowód. Udowodnimy po kolei prawa zacytowane w tezie twierdzenia.
Dowód prawa (2.11). Korzystając z prawa identyczności (2.8) mamy
x + x = (x + x) · 1
następnie stosujemy prawo dopełnienia (2.9)
(x + x) · 1 = (x + x) · (x + x)
teraz stosując prawo rozdzielności (2.5)
(x + x) · (x + x) = x + (x · x)
korzystając z prawa dopełnienia (2.10) mamy
x + (x · x) = x + 0
ostatecznie stosując prawo identyczności (2.7) otrzymujemy, że
x + 0 = x
co kończy dowód prawa (2.11). Dowód prawa (2.12) przeprowadza się ana-
logicznie, więc go pominiemy.
Dowód prawa (2.13). Korzystając z prawa dopełniania (2.9) mamy
x + 1 = x + (x + x)
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
42
Podstawowe pojęcia i definicje
następnie stosujemy prawo łączności (2.3)
x + (x + x) = (x + x) + x
teraz stosując prawo idempotentności (2.11)
(x + x) + x = x + x
ostatecznie korzystając z prawa dopełniania (2.9) mamy
x + x = 1
co kończy dowód prawa (2.13). Dowód prawa (2.14) przeprowadza się ana-
logicznie.
Dowód prawa (2.15). Korzystając z prawa identyczności (2.8) otrzy-
mujemy
(x · y) + x = (x · y) + (x · 1)
stosując prawo rozdzielności (2.6)
(x · y) + (x · 1) = x · (y + 1)
następnie stosując drugie prawo identyczności (2.13)
x · (y + 1) = x · 1
i ponownie stosując pierwsze prawo identyczności (2.8) ostatecznie otrzy-
mujemy
x · 1 = x
co kończy dowód prawa (2.15). Dowód prawa (2.16) przeprowadza się ana-
logicznie.
Udowodniliśmy zatem tezę twierdzenia.
Twierdzenie 2.2. W każdej algebrze Boole’a spełnione są następujące prawa
De Morgana:
(x + y) = x · y
(2.17)
(x · y) = x + y
(2.18)
Dowód. Wpierw pokażemy, że jeśli
w + z = 1
i w · z = 0,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.1 Algebra Boole’a
43
to z = w. Dzięki temu będziemy mogli stwierdzić, że własności
w + w = 1
i w · w = 0,
charakteryzują jednoznacznie w.
Spróbujmy wykazać powyższe. Korzystając z prawa identyczności (2.7)
mamy
z = z + 0
dzięki prawu dopełniania (2.10)
z + 0 = z + (w · w)
stosując prawo rozdzielności (2.5)
z + (w · w) = (z + w) · (z + w)
następnie prawo przemienności (2.1)
(z + w) · (z + w) = (w + z) · (w + z)
teraz wykorzystując założenie
(w + z) · (w + z) = 1 · (w + z)
korzystając z prawa dopełnienia (2.9)
1 · (w + z) = (w + w) · (w + z)
ponownie z prawa przemienności (2.1)
(w + w) · (w + z) = (w + w) · (w + z)
stosując prawo rozdzielności (2.5)
(w + w) · (w + z) = w + (w · z)
korzystając z założenia
w + (w · z) = w + 0
na koniec stosując prawo identyczności (2.7) otrzymujemy
w + 0 = w
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
44
Podstawowe pojęcia i definicje
Zatem udowodniliśmy, że przy stawianych założeniach
z = w
Jeśli teraz pokażemy, że
(x + y) + (x · y) = 1
(2.19)
(x + y) · (x · y) = 0
(2.20)
to korzystając z wcześniej udowodnionej jednoznaczności, otrzymamy praw-
dziwość prawa De Morgana (2.17) stawianego w tezie twierdzenia. Zatem
udowodnimy wpierw, że zachodzi (2.19). Korzystając z rozdzielności mamy:
(x + y) + (x · y) = ((x + y) + x) · ((x + y) + y) = . . .
następnie z łączności i przemienności
· · · = (y + (x + x)) · (x + (y + y)) = (y + 1) · (x + 1) = 1 · 1 = 1.
Podobnie udowadnia się (2.20), co ostatecznie pozwala stwierdzić prawdzi-
wość prawa (2.17).
Korzystając z zasady dualności widać natychmiast prawdziwość prawa
(2.18).
2.1.2
Dwuelementowa algebra Boole’a
W informatyce (jak i elektronice cyfrowej) zwykle wykorzystuje się dwuele-
mentową algebrę Boole’a, której zbiór elementów jest postaci B = {0, 1}. Od
tego momentu mówiąc o algebrze Boole’a, będziemy mieli na myśli właśnie
tę dwuelementową wersję.
W przypadku takiej algebry możliwe jest sprawdzenie poprawności rów-
ności za pomocą tzw. metody zerojedynkowej. W metodzie tej rozważa
się wszystkie możliwe przypadki jakie otrzymamy podstawiając za zmienne
wartości 0 lub 1. Sprawdźmy tą metodą na przykład prawo (2.3).
x
y
z
y + z
x + (y + z)
x + y
(x + y) + z
0 0 0
0
0
0
0
0 0 1
1
1
0
1
0 1 0
1
1
1
1
0 1 1
1
1
1
1
1 0 0
0
1
1
1
1 0 1
1
1
1
1
1 1 0
1
1
1
1
1 1 1
1
1
1
1
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
45
Zauważmy, że każde takie wyrażenie można zapisać w jednej z dwóch
możliwych postaci kanonicznych: sumy iloczynów lub iloczynu sum. Aby
to wyjaśnić zilustrujemy ten fakt przykładem, pokazującym jednocześnie
jak upraszcza się skomplikowane wyrażenia booleowskie (przykład 2.1). W
przykładzie tym nad znakami równości w nawiasach umieszczono numery
praw z których korzystano, przy czym prawa przemienności uznaje się za
intuicyjne i będą pomijane w tych oznaczeniach.
Przykład 2.1. Upraszczanie wyrażeń algebraicznych
w = (x + y) (x + y) (x + z)
(2.6)
= [x (x + y) + y (x + y)] (x + z)
(2.6)
=
= [x + xy + yx + yy] (x + z)
(2.6,2.10)
=
= [x + x (y + y) + 0] (x + z)
(2.9,2.7)
=
(x + x0) (x + z)
(2.14,2.7)
=
= x(x + z)
(2.6)
= xx + xz
(2.10)
= xz
v = xyz + xyz + xyz
(2.6)
= x (yz + zy + yz)
(2.11)
=
= x (yz + yz + yz + yz) = x [(yz + yz) + (yz + yz)]
(2.6)
=
= x [z (y + y) + y (z + z)]
(2.9)
= x(z + y)
(2.6)
= xz + xy
Uwaga 2.1. Wprowadzenie w przykładzie 2.1 nawiasów kwadratowych nie
ma charakteru formalnego, zastały one użyte wyłącznie dla poprawy czytel-
ności wyrażenia i należy je traktować jak nawiasy okrągłe.
Zauważmy jednocześnie, że przedostatnia postać wyrażenia v w przykła-
dzie 2.1 jest, z praktycznego punktu widzenia, prostsza niż ostatnia, gdyż
wymaga tylko jednej operacji sumy i jednego iloczynu; druga wymaga dwóch
iloczynów i jednej sumy. Oczywiście ponieważ obie postacie są sobie równo-
ważne, zatem można w zależności od okoliczności wykorzystywać dowolną
z nich, co więcej dowolną z pośrednich postaci.
2.2
Pozycyjne systemy liczbowe
Przypomnijmy jak zapisujemy liczbę naturalną, stosując do tego zapis po-
wszechnie używany zwany zapisem dziesiętnym, lub systemem dziesiętnym.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
46
Podstawowe pojęcia i definicje
Zauważmy, że liczba n−cyfrowa w systemie dziesiętnym ma postać
c
n−1
...c
1
c
0
,
(2.21)
gdzie c
n−1
, ..., c
1
, c
0
są znanymi cyframi systemu dziesiętnego, zatem należą
do zbioru {0, 1, ..., 9}. Powyższy zapis ma wartość równą
w = c
n−1
· 10
n−1
+ · · · + c
1
· 10
1
+ c
0
· 10
0
.
Widać, iż w zapisie (2.21) ta sama cyfra będzie oznaczała inną wartość w
zależności od miejsca występowania w tym napisie. Dla przykładu w napi-
sach 601 i 610 cyfra jeden odpowiednio ma wartość jeden i dziesięć. Zatem
pozycja cyfry determinuje wspólnie z nią samą wartość, stąd systemy licz-
bowe oparte na tej zasadzie będziemy nazywali pozycyjnymi systemami
liczbowymi.
Uwaga 2.2. Zupełnie inna sytuacja występuje w zapisie liczby w systemie
rzymskim. Przypomnijmy, że w systemie tym kolejne liczby od 1, . . . , 9 mają
postać
I, II, III, IV, V, V I, V II, V III, IX
Widać, że w takim zapisie pozycja „cyfry” — o ile w ogóle można mówić w
tym wypadku o cyfrze, nie jest związana z wyznaczaniem jej wartości, lecz
istotna jest postać całej liczby. Taki system zapisu nazywamy addytywnym
systemem liczbowym
.
Przykład definicji systemu dziesiętnego wskazuje drogę uogólnienia jej
na definicję dowolnego pozycyjnego systemu liczbowego. Pozycyjnym sys-
temem liczbowym nazywamy parę (q, C), gdzie q jest liczbą naturalną i
nazywamy ją podstawą systemu, oraz C jest skończonym zbiorem znaków
{0, 1, . . . , q − 1}, zwanych cyframi. W systemie pozycyjnym, jak powie-
dziano na wstępie, liczbę przedstawia się jako ciąg cyfr, przy czym wartość
tej liczby zależy zarówno od cyfr jak i miejsca, na którym się one znajdują
w tym ciągu. Zapis
c
k
c
k−1
. . . c
1
c
0
ma wartość liczbową
w = c
k
q
k
+ c
k−1
q
k−1
+ . . . + c
1
q + c
0
,
(2.22)
gdzie c
0
, . . . , c
k
∈ C. Kolejne potęgi podstawy systemu q nazywa się rzę-
dami. Jeśli q = 10, to otrzymujemy dziesiątkowy system liczbowy, dla
q = 2 dwójkowy (binarny), dla q = 8 — ósemkowy, itd.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
47
W przypadku posługiwania się na raz kilkoma systemami liczbowymi,
stosujemy zapis liczby z informacją o podstawie systemu w jakim została
zapisana. Jest to bardzo ważne gdyż liczby, które „wyglądają” tak samo
mogą mieć inną wartość w różnych systemach liczbowych. Dla przykładu
10
(10)
— liczba o wartości 10 dziesiętnie zapisana w systemie dziesiętnym,
10
(2)
— liczba o wartości 2 dziesiętnie zapisana w systemie dwójkowym,
10
(3)
— liczba o wartości 3 dziesiętnie zapisana w systemie trójkowym.
2.2.1
System dwójkowy
Ponieważ obecne komputery są konstruowane w oparciu o układy cyfrowe
pracujące według reguł dwuelementowej algebry Boole’a (zob. 2.1.2), stąd
w informatyce szczególną wagę przywiązuje się do systemu dwójkowego. W
tym punkcie omówimy dokładnie ten system, konwersję z systemu dziesięt-
nego na dwójkowy i odwrotnie, oraz arytmetykę w systemie dwójkowym.
Konwersja z systemu dwójkowego na system dziesiętny
Korzystając z definicji pozycyjnego systemu liczbowego otrzymujemy, że
podstawą systemu dwójkowego jest liczba 2, oraz cyframi tego systemu są
elementy zbioru {0, 1}. Zapiszmy przykładową liczbę w tym systemie
x = 1011110110
(2)
(2.23)
korzystając z (2.22), otrzymujemy
w = 1 · 2
9
+ 0 · 2
8
+ 1 · 2
7
+ 1 · 2
6
+ 1 · 2
5
+
+ 1 · 2
4
+ 0 · 2
3
+ 1 · 2
2
+ 1 · 2
1
+ 0 · 2
0
Zastępując teraz potęgi liczby 2 odpowiadającymi im wartościami w syste-
mie dziesiętnym, otrzymujemy
w = 1 · 512 + 0 · 256 + 1 · 128 + 1 · 64 + 1 · 32 +
+ 1 · 16 + 0 · 8 + 1 · 4 + 1 · 2 + 0 · 1 = 758
(10)
Widać, że konwersja z systemu dwójkowego do systemu dziesiętnego
sprowadza się do skorzystania ze wzoru (2.22), a następnie obliczenia war-
tości opisanej tym wyrażeniem. Należy pamiętać jedynie o tym, że potę-
gowanie, mnożenie i dodawanie wykonujemy już w systemie dziesiętnym, w
wyniku czego otrzymujemy wartość również w systemie dziesiętnym.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
48
Podstawowe pojęcia i definicje
Zapiszmy teraz dla przykładu kolejne 8 liczb w systemie dziesiętnym
oraz dwójkowym
zapis
zapis
dwójkowy dziesiętny
000
0
001
1
010
2
011
3
100
4
101
5
110
6
111
7
Konwersja z systemu dziesiętnego na system dwójkowy
O ile zamiana z systemu dwójkowego na dziesiętny sprowadza się do doda-
wania i mnożenia, to algorytm odwrotny wymaga więcej uwagi. Załóżmy,
że mamy daną liczbę x w systemie dziesiętnym, aby zapisać ją w systemie
dwójkowym postępujemy według następującej procedury:
1. niech w = x,
2. dzielimy w przez 2,
3. jeśli wynikiem operacji dzielenia jest liczba całkowita, zapisujemy na
boku 0,
4. jeśli wynikiem operacji dzielenie nie jest liczba całkowita — zostaje
reszta, zapisujemy na boku 1,
5. całkowity wynik z dzielenia, po odrzuceniu ewentualnej reszty, zapi-
sujemy jako w,
6. jeśli w jest różne od 0 przechodzimy z powrotem do kroku 2,
7. jeśli w jest równe 0 kończymy procedurę.
Otrzymane w ten sposób cyfry 0 lub 1 zapisywane od prawa do lewa (bardzo
ważne, że właśnie w takiej kolejności!) w kolejności ich otrzymywania dadzą
nam oczekiwaną wartość w systemie dwójkowym.
Zilustrujmy to przykładem, załóżmy, że chcemy zapisać liczbę 758 w
systemie o podstawie 2. W tym celu dzielimy wpierw liczbę 758 przez 2, a
następnie postępujemy dalej według powyższej procedury
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
49
758 | 2 x 379 + 0,
tym razem dzielimy liczbę 379 przez 2 i zapisujemy poniżej poprzedniego
wiersza, zatem mamy
758 | 2 x 379 + 0
379 | 2 x 189 + 1
analogicznie postępujemy dalej
758 | 2 x 379 + 0
379 | 2 x 189 + 1
189 | 2 x 94
+ 1
94 | 2 x 47
+ 0
47 | 2 x 23
+ 1
23 | 2 x 11
+ 1
11 | 2 x 5
+ 1
5 | 2 x 2
+ 1
2 | 2 x 1
+ 0
1 | 2 x 0
+ 1
Powstała w ten sposób kolumna z prawej strony stanowi zapis liczby 758
w systemie o podstawie 2. Kolumnę tą czytając od dołu i pisząc od lewa,
lub czytając od góry i pisząc od prawa, przekształcamy w ostateczną postać
żądanej liczby
1011110110
(2)
,
zauważmy, że otrzymaliśmy postać identyczną z (2.23), a jak sprawdziliśmy
to wcześniej jest to liczba o wartości 758 zapisana w postaci dwójkowej.
Przytoczymy kilka przykładów, powyższej procedury konwersji (przy-
kład 2.2).
Przykład 2.2. Ilustracja konwersji liczby zapisanej w systemie dzie-
siętnym na dwójkowy.
158 | 2 x 79 + 0
108 | 2 x 54 + 0
59 | 2 x 29 + 1
79 | 2 x 39 + 1
54 | 2 x 27 + 0
29 | 2 x 14 + 1
39 | 2 x 19 + 1
27 | 2 x 13 + 1
14 | 2 x 7
+ 0
19 | 2 x 9
+ 1
13 | 2 x 6
+ 1
7 | 2 x 3
+ 1
9 | 2 x 4
+ 1
6 | 2 x 3
+ 0
3 | 2 x 1
+ 1
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
50
Podstawowe pojęcia i definicje
4 | 2 x 2
+ 0
3 | 2 x 1
+ 1
1 | 2 x 0
+ 1
2 | 2 x 1
+ 0
1 | 2 x 0
+ 1
0 | koniec
1 | 2 x 0
+ 1
0 | koniec
0 | koniec
158(10) -> 10011110(2), 108(10) -> 1101100(2), 59(10) -> 111011(2)
Arytmetyka w systemie dwójkowym
Komputery pracujące w oparciu o układy cyfrowe dokonują większość obli-
czeń na liczbach w systemie dwójkowych. Pokażemy teraz sposób wykony-
wania podstawowych działań na liczbach zapisanych w ten sposób.
Dodawanie jest realizowane podobnie jak dla systemu dziesiętnego,
należy jedynie pamiętać, że
1
(2)
+ 1
(2)
= 10
(2)
wynika to z faktu, iż w systemie dwójkowym nie ma cyfry reprezentującej
liczbę 2, 1+1 w tym systemie daje w wyniku 0 na pewnej pozycji, a jedność
jest przenoszona na następną pozycję w liczbie. Jest to podoba sytuacja
jak w przypadku dodawania 1 + 9 w systemie dziesiętnym, otrzymujemy w
wyniku 0, a jedność jest przenoszona na następną pozycję. Przypatrzmy się
następującym działaniom w przykładzie 2.3.
Przykład 2.3. Dodawanie w systemie dwójkowym.
11
00111000
01000001
+ 00010001
+ 00010100
----------
----------
01001001
01010101
Odejmowanie podobnie jak dodawanie wykonywane jest według za-
sady identycznej jak w systemie dziesiętnym, przy czym w przypadku odej-
mowania 0 − 1 w systemie dwójkowym, musimy dokonać zapożyczenia 1 na
następnej pozycji liczby. Obliczenia zawiera przykład 2.4
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
51
Przykład 2.4. Odejmowanie w systemie dwójkowym.
00111001
00101101
- 00001101
- 00010001
----------
----------
00101100
00011100
Mnożenie jest wykonywane analogicznie jak mnożenie w systemie dzie-
siętnym, ilustruje to przykład 2.5.
Przykład 2.5. Mnożenie w systemie dwójkowym.
1111
10001
x
101
x
11
-------------
---------------
1111
10001
0000
+
10001
+
1111
---------------
-------------
110011
1001011
Dzielenie podobnie jak mnożenie wykonujemy tak samo jak w przy-
padku dzielenia w systemie dziesiętnym. Ilustrację tego procesu zawiera
przykład 2.6.
Przykład 2.6. Dzielenie w systemie dwójkowym.
110
1011
-----
-------
10010:11=00000110
1111001:1011=1011
-
11
- 1011
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
52
Podstawowe pojęcia i definicje
-------
---------
1
10000
11
-
1011
-
11
---------
-------
1011
0
-
1011
---------
0
2.2.2
Zapis liczby rzeczywistej w systemie dwójkowym
Do tej pory zamiana z i do systemu dwójkowego była ograniczona wyłącz-
nie do liczb całkowitych. Pozostaje zatem do wyjaśnienia w jaki sposób
należy reprezentować liczbę rzeczywistą w systemie dwójkowym
2
. W celu
lepszego zrozumienia zapisu liczb rzeczywistych w systemie dwójkowym,
przypomnijmy to co było omawiane na początku punktu 2.2. Zauważmy,
że dla liczby całkowitej było powiedziane, że dopiero pozycja cyfry wraz
z jej wartością niesie pełną informację. Podobnie ma się sprawa z częścią
ułamkową. Jeśli mamy liczbę w systemie dziesiętnym postaci:
0, c
−1
c
−2
...c
−n
gdzie c
−1
, c
−2
, . . . , c
−n
∈ {0, . . . , 9} są cyframi, to wartość tej liczby jest
wyliczana za pomocą następującego wzoru:
w = c
−1
10
−1
+ c
−2
10
−2
+ · · · + c
−n
10
−n
.
Jeżeli teraz nasze rozważania przeniesiemy do systemu dwójkowego, to war-
tość będzie wyliczana na podstawie podobnego wzoru, zmieni się jedynie
podstawa, zatem:
w = c
−1
2
−1
+ c
−2
2
−2
+ · · · + c
−n
2
−n
,
oczywiście w tym wypadku cyfry są elementami zbioru {0, 1}.
2
Rozważania prowadzone w tym punkcie mają charakter informacyjny, gdyż będą po-
trzebne w następnym rozdziale. Jednak nie należy postrzegać prezentowanego zapisu
liczby rzeczywistej jako tego, który jest stosowany w komputerze w sposób bezpośredni.
W następnym rozdziale będzie to wytłumaczone obszernie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
53
Stosując powyższy wzór jesteśmy w stanie bezpośrednio zamienić uła-
mek zapisany w systemie dwójkowym na system dziesiętny. Rozważmy
poniższy przykład:
Przykład 2.7. Zamiana ułamka dwójkowego na dziesiętny.
0.11
(2)
= 2
−1
· 1 + 2
−2
· 1 = 0.5 + 0.25 = 0.75
(10)
Do wyjaśnienia pozostaje sposób zamiany w drugą stronę, czyli jak za-
mieniać ułamek dziesiętny na dwójkowy. Ograniczymy się w tym miejscu
wyłącznie do ułamków dodatnich. Schemat postępowania jest podobny do
przedstawionych wcześniej. Mamy następujący algorytm (ułamek zapisany
dziesiętnie oznaczmy przez x):
1. niech w = x,
2. mnożymy w przez 2,
3. jeśli wynikiem operacji mnożenia jest liczba większa od jedności, za-
pisujemy na boku 1,
4. jeśli wynikiem operacji mnożenia jest liczba mniejsza od jedności, za-
pisujemy na boku 0,
5. ułamkową część wyniku — po odrzuceniu ewentualnej części całkowi-
tej, zapisujemy jako w,
6. jeśli w jest różne od 0 przechodzimy z powrotem do kroku 2,
7. jeśli w jest równe 0 kończymy procedurę.
Następnie otrzymane zera i jedynki zapisywane w kolejności otrzymywa-
nia od lewej do prawej stanowią ułamek zapisany w systemie dwójkowym.
Zilustrujmy powyższy algorytm przykładem.
Przykład 2.8. Zamiana ułamka dziesiętnego na ułamek dwójkowy.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
54
Podstawowe pojęcia i definicje
0.75(10) = ? (2)
liczba dwójkowa
|
| część ułamkową przepisujemy
| |
do pierwszej kolumny
0.75 | 2 x 0.75 = 1.5
0.5
| 2 x 0.5
= 1.0
0.0
| koniec
Otrzymaliśmy zatem, że
0.75
(10)
= 0.11
(2)
Jak widać otrzymaliśmy dokładnie wartość z poprzedniego przykładu.
Wykonajmy następne obliczenia:
0.625(10) = ? (2)
0.625 | 2 x 0.625 = 1.25
0.25
| 2 x 0.25
= 0.5
0.5
| 2 x 0.5
= 1.0
0.0
| koniec
Zatem otrzymujemy
0.625
(10)
= 0.101
(2)
Sprawdźmy:
2
−1
· 1 + 2
−2
· 0 + 2
−3
· 1 = 0.5 + 0.125 = 0.625
I kolejny przykład
0.40625(10) = ? (2)
0.40625 | 2 x 0.40625 = 0.8125
0.8125
| 2 x 0.8125
= 1.625
0.625
| 2 x 0.625
= 1.25
0.25
| 2 x 0.25
= 0.5
0.5
| 2 x 0.5
= 1.0
0.0
| koniec
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
55
Zatem
0.40625
(10)
= 0.01101
(2)
Sprawdźmy:
2
−1
· 0 + 2
−2
· 1 + 2
−3
· 1 + 2
−4
· 0 + 2
−5
· 1 = 0.25 + 0.125 + 0.03125 = 0.40625
Przejdźmy teraz do zamiany liczb rzeczywistych większych od jeden, w
takim przypadku, stosujemy dla części całkowitej poznany wcześniej proces,
a dla części ułamkowej omówiony powyżej.
Przykład 2.9. Zamiana liczby rzeczywistej dziesiętnej na postać
dwójkową.
9.25(10) = ? (2)
9 | 2 x 4 + 1
0.25 | 2 x 0.25 = 0.5
4 | 2 x 2 + 0
0.5
| 2 x 0.5
= 1.0
2 | 2 x 1 + 0
0.0
| koniec
1 | 2 x 0 + 1
0 | koniec
Zatem otrzymujemy ostatecznie
9.25
(10)
= 1001.01
(2)
Wykonajmy jeszcze jeden przykład
15.375(10) = ? (2)
15 | 2 x 7 + 1
0.375 | 2 x 0.375 = 0.75
7 | 2 x 3 + 1
0.75
| 2 x 0.75
= 1.5
3 | 2 x 1 + 1
0.5
| 2 x 0.5
= 1.0
1 | 2 x 0 + 1
0.0
| koniec
0 | koniec
Stąd
15.375
(10)
= 1111.011
(2)
Na koniec zauważmy, że nie każdą liczbę którą da się zapisać w postaci
ułamka dziesiętnego da się dobrze przedstawić w postaci ułamka dwójko-
wego, co ilustruje poniższy przykład:
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
56
Podstawowe pojęcia i definicje
Przykład 2.10. Zamiana ułamka dziesiętnego na ułamek dwójkowy
okresowy.
0.3 (10) = ? (2)
0.3 | 2 x 0.3 = 0.6
0.6 | 2 x 0.6 = 1.2
0.2 | 2 x 0.2 = 0.4
0.4 | 2 x 0.4 = 0.8
0.8 | 2 x 0.8 = 1.6
0.6 | ...
Zatem jak widać ułamek może mieć „dobrą” postać dziesiętną, zaś „złą”
dwójkową. W powyższym przykładzie ułamek dwójkowy jest okresowy, za-
tem w którymś momencie musimy zaprzestać procedury, gdyż inaczej pro-
wadzilibyśmy ją w nieskończoność. Jeśli jednak zaprzestaniemy, to będzie to
niedokładna reprezentacja wyjściowego ułamka, dla przykłady ograniczmy
się do pięciu cyfr po przecinku, otrzymamy wtedy:
0.01001
(2)
= 0.25 + 0.03125 = 0.28125
(10)
.
Jak widać błąd takiego zaokrąglenie wcale nie jest mały, jednak pamiętajmy,
że nie jest to „wina” systemu dwójkowego lecz samego procesu dzielenia w
ogóle. Zauważmy, że dla ułamka zwykłago
1
3
jego rozwinięcie w ułamek dzie-
siętny również będzie przybliżone jeśli chcemy je przechować na skończonym
nośniku danych.
2.2.3
Kod szesnastkowy
Wadą systemu dwójkowego jest „rozwlekłość” zapisywanych w ten sposób
liczb. Dla człowieka bywa trudne zapamiętanie ciągu zer i jedynek. Stąd też
często w praktyce informatyka spotykamy się z zapisem liczby w systemie
szesnastkowym lub kodzie szesnastkowym. Z definicji pozycyjnego
systemu liczbowego (zob. 2.2) wynika, że w systemie szesnastkowym mu-
simy mieć szesnaście cyfr, ale jak sobie poradzić w sytuacji, gdy mamy do
dyspozycji cyfry arabskie w zakresie 0, 1, . . . , 9. Problemem ten rozwiązano
poprzez nazwanie kolejnych cyfr tego systemu, poczynając od dziesięciu,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
57
kolejnymi literami alfabetu, zatem A
(16)
= 10
(10)
, B
(16)
= 11
(10)
, itd., do-
puszcza się również stosowanie małych liter zamiast dużych.
Można oczywiście zapytać, czemu nie stosujemy w informatyce systemu
osiemnastkowego, przyjrzyjmy się poniższej tabelce a wszystko się wyjaśni
zapis
zapis
zapis
dwójkowy szesnastkowy dziesiętny
0000
0
0
0001
1
1
0010
2
2
0011
3
3
0100
4
4
0101
5
5
0110
6
6
0111
7
7
1000
8
8
1001
9
9
1010
A
10
1011
B
11
1100
C
12
1101
D
13
1110
E
14
1111
F
15
Widać z powyższego zestawienia, że jedna cyfra kodu szesnastkowego
odpowiada dokładnie czterocyfrowej liczbie systemu dwójkowego. Ponie-
waż bajt informacji (zob. A) składa się z 8 bitów, zatem każdy bajt danych
daje się w sposób jednoznaczny przedstawić za pomocą dwu cyfr kodu szes-
nastkowego, co upraszcza kwestię konwersji; nie wymaga ona w praktyce
obliczeń a jedynie podstawienia. Oto przykład
00011101
(2)
= 1D
(16)
, 1011111
(2)
= BF
(16)
, 11100011
(2)
= E3
(16)
.
2.2.4
Inne pozycyjne systemy liczbowe
Punkt ten należy traktować jako informację poszerzającą wiedzę ogólną,
gdyż inne systemy liczbowe niż dwójkowy i szesnastkowy praktycznie nie
są wykorzystywane w informatyce, lub ich obecność jest marginalna. Dla
przykładu niekiedy można spotkać zapis liczby w systemie ósemkowym.
Korzystając z definicji pozycyjnego systemu liczbowego, zapiszemy tą
samą liczbę w systemach pozycyjnych o różnych podstawach. Przykład
2.11 zawiera ilustrację tego procesu.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
58
Podstawowe pojęcia i definicje
Przykład 2.11. Liczba 758 zapisana w pozycyjnych systemach licz-
bowych o różnych podstawach.
23312
4
= 2 · 4
4
+ 3 · 4
3
+ 3 · 4
2
+ 1 · 4
1
+ 2 · 4
0
= 758
10
1366
8
= 1 · 8
3
+ 3 · 8
2
+ 6 · 8
1
+ 6 · 8
0
= 758
10
2F 6
16
= 2 · 16
2
+ 15 · 16
1
+ 6 · 16
0
= 758
10
Jedną z możliwych metod przejścia od zapisu w systemie o podstawie p
1
do systemu o podstawie p
2
jest zamiana zapisu liczby na system dziesiętny,
a dopiero potem na system o podstawie p
2
. Metoda ta wydaje się natu-
ralna, gdyż ludzie najsprawniej operują systemem dziesiętnym. Ilustruje to
poniższy przykład
Przykład 2.12. Zamiana liczby z systemu 25 na system 11 poprzez
system dziesiątkowy.
Wpierw zamieniamy liczbę z systemu o podstawie 25 na liczbę w systemie
dziesiątkowym
2K
25
= 2 · 25
1
+ K · 25
0
= 2 · 25 + 20 · 1 = 70
10
następnie z systemu dziesiątkowego na jedenastkowy
70 | 11 x 6 + 9
6 | 11 x 0 + 6
Ostatecznie więc otrzymujemy
2K
25
= 69
11
Zauważmy jednocześnie, że w powyższym przykładzie, przy zapisie liczby
w systemie dwudziestopiątkowym, przyjęliśmy podobną notację cyfr jak w
systemie szesnastkowym, zatem wykorzystaliśmy kolejne litery alfabetu.
W szczególnych przypadkach można proces ten jednak znacznie uprościć.
Przyjrzyjmy się przykładowym liczbą w zapisie dwójkowym, czwórkowym i
dziesiętnym.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
59
zapis
zapis
zapis
dwójkowy czwórkowy dziesiętny
00
0
0
01
1
1
10
2
2
11
3
3
11011001
2
→ 3121
4
3321
4
→ 11111001
2
Zauważmy, że zamieniając liczbę dwójkową na czwórkową, grupujemy bity
po dwa, a następnie te dwójki zapisujemy za pomocą odpowiednich liczb
czwórkowych (podobnie czyniliśmy to w zamianie z systemu dwójkowego na
szesnastkowy). Zapisując liczbę czwórkową jako dwójkową, każdą jej cyfrę
zapisujemy za pomocą odpowiedniego dwu wyrazowego ciągu zerojedynko-
wego.
11 01 10 01
3
3
2
1
|
|
|
|
|
|
|
|
3
1
2
1
11 11 10 01
Teraz zapiszmy kolejne liczby w systemach dwójkowym, ósemkowym
i dziesiętnym:
zapis
zapis
zapis
dwójkowy ósemkowy dziesiętny
000
0
0
001
1
1
010
2
2
011
3
3
100
4
4
101
5
5
110
6
6
111
7
7
W tym przypadku aby dokonać przeliczenia, możemy grupować cyfry
kodu dwójkowego po 3.
011 011 001
|
|
|
3
3
1
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
60
Podstawowe pojęcia i definicje
Otrzymujemy zatem
11011001
2
→ 331
8
331
8
→ 11011001
2
Do konwersji z systemu dziesiętnego na inny pozycyjny system liczbowy,
stosujemy analogiczny sposób jak opisany w punkcie 2.2.1, z tą różnicą,
że tym razem resztą z dzielenia mogą być nie tylko cyfry zero lub jeden.
Przykład 2.13 ilustruje tę procedurę
Przykład 2.13. Przykład ilustrujący zamianę liczby 758 zapisanej
dziesiętnie na system czwórkowy, ósemkowy i szesnastkowy
758 (10) -> (4)
758 (10) -> (8)
758 (10) -> (16)
758 | 4 x 189 + 2
758 | 8 x 94 + 6
758 | 16 x 47 + 6
189 | 4 x 47
+ 1
94 | 8 x 11 + 6
47 | 16 x 2
+ 15 (F)
47 | 4 x 11
+ 3
11 | 8 x 1
+ 3
2 | 16 x 0
+ 2
11 | 4 x 2
+ 3
1 | 8 x 0
+ 1
2 | 4 x 0
+ 2
758(10) -> 23312(4)
758(10) -> 1366(8)
758(10) -> 2F6(16)
Nic nie stoi na przeszkodzie aby stosować systemy liczbowe o podstawach
różnych od potęgi 2. Niech na przykład liczba 2K będzie liczbą zapisaną
w systemie o podstawie 25. Zapiszemy ją teraz jako liczbę systemu o pod-
stawie 11. Najbardziej naturalna drogą, zasugerowana na początku tego
podrozdziału, to konwersja (25) → (10) → (11)
2K
25
= 2 · 25
1
+ K · 25
0
= 2 · 25 + 20 · 1 = 70
10
70 | 11 x 6 + 9
6 | 11 x 0 + 6
Ostatecznie więc
2K
25
= 69
11
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.2 Pozycyjne systemy liczbowe
61
Innym podejściem jest pominięcie pośredniego kroku w postaci przeli-
czania na system dziesiętny i operowanie od razy wyłącznie na systemie
źródłowym i docelowym. W przypadku dokonywania konwersji z systemu o
mniejszej podstawie do większej nie nastręcza to żadnych trudności. W tym
wypadku ma zastosowanie wzór 2.22, jednak należy pamiętać, że wszelkie
obliczenia muszą być prowadzone w arytmetyce docelowego systemu liczbo-
wego.
Rozważmy poniższy przykład, niech będzie dana liczba 1111101
(2)
jak
widać zapisana w systemie dwójkowym, załóżmy teraz, że chcemy dokonać
konwersji na system szesnastkowy. Napiszmy wzór na wartość liczby
w = 1 · 2
6
+ 1 · 2
5
+ 1 · 2
4
+ 1 · 2
3
+ 1 · 2
2
+ 0 · 2
1
+ 1 · 2
0
teraz wszystkie obliczenie po prawej stronie równości należy prowadzić w
arytmetyce szesnastkowej, zatem
w = 40 + 20 + 10 + 8 + 4 + 0 + 1 = 70 + D = 7D
(16)
co jak widać zgadza się ze zwykłą regułą prezentowaną w punkcie 2.2.3.
Niestety sytuacja komplikuje się przy dokonywaniu odwrotnej konwer-
sji, wtedy bowiem dzielimy liczbę w systemie źródłowym przez podstawę
systemu docelowego, oraz należy pamiętać o resztach, których ilość jaką
się rozważa jest zależna od systemu docelowego. Weźmy liczbę 96
(16)
i za-
mieńmy ją na system trójkowy, w tym celu przeprowadzamy następującą
serię dzieleń
96(16) -> (3)
96 | 3 x 32 + 0
32 | 3 x 10 + 2
10 | 3 x 05 + 1
05 | 3 x 01 + 2
01 | 3 x 00 + 1
96(16) -> 12120(3)
Wykonajmy sprawdzenie powyższej konwersji, zamieniając postacie w
obu systemach na system dziesiętny
96
(16)
= 9 · 16
1
+ 6 · 16
0
= 144 + 6 = 150
(10)
12120
(3)
= 1 · 3
4
+ 2 · 3
3
+ 1 · 3
2
+ 2 · 3
1
+ 0 = 81 + 54 + 9 + 6 + 0 = 150
(10)
.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
62
Podstawowe pojęcia i definicje
2.3
BCD
Do tej pory zapoznaliśmy się już z systemem dwójkowym, szesnastkowy oraz
innymi. Jak można było zaobserwować, istotnych różnic pomiędzy nimi nie
ma i w zasadzie to jesteśmy w stanie operować dowolnym z nich, a nawet
kilkoma, dokonując odpowiednich konwersji przy przejściu od jednego do
drugiego. Mimo to cały czas odczuwa się jak gdyby wrodzoną skłonność do
operowania systemem dziesiętnym, przejawiającą się chociażby w tym, że
w konwersji najczęściej stosujemy schemat podstawa źródłowa → pod-
stawa 10 → podstawa docelowa. Cały kłopot z systemami liczbowymi
o podstawach innych niż 10 polega na tym, że ciąg cyfr jest dla nas abs-
trakcyjnym napisem, który nabiera znaczenia dopiero, gdy przekształcimy
go do postaci dziesiętnej
3
.
Zilustrujemy problemy o których mówimy za pomocą prostego testu.
Kto bez zastanowiednia odpowie, ile wynosi 1/3 z liczby 111100 (2)? Jak
więc widać, systemem dwójkowym operujemy z konieczności, a najchętniej
(najsprawniej) używamy dziesiętnego. Problemem jest konwersja z jednego
na drugi. Chcąc ułatwić to zadanie wprowadzono system kodowania BCD
(ang. Binary-Coded Decimal). W tym systemie liczby dziesiętne kodujemy
za pomocą ciągu bitów przypisując każdej cyfrze dziesiętnej odpowiadajacy
jej ciąg 4 bitów (patrz tabelka 2.1). Ponieważ mamy jedynie 10 możliwości
więc wystarczy zapamiętać tylko tyle, aby móc sprawnie i szybko przecho-
dzić z systemu dziesiętnego do BCD i odwrotnie. Zobaczmy jak odbywa się
ten proces; zapiszemy liczbę dziesiętną 120 najpierw w systemie dwójkowym
a następnie w formacie BCD.
120 (10) => ? (2)
120 | 2 * 60 + 0
60 | 2 * 30 + 0
30 | 2 * 15 + 0
15 | 2 *
7 + 1
7 | 2 *
3 + 1
3 | 2 *
1 + 1
1 | 2 *
0 + 1
120 (10) = 1111000 (2)
3
Oczywiście wynika to z przyzwyczajenia i wychowania w określonej kulturze. Kiedyś
dla przykładu liczono tuzinami, czy kopami.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.3 BCD
63
Cyfra dziesiętna „Cyfra” BCD
0
0000
1
0001
2
0010
3
0011
4
0100
5
0101
6
0110
7
0111
8
1000
9
1001
-
1010
-
1011
-
1100
-
1101
-
1110
-
1111
Tablica 2.1: Cyfry dziesiętne i odpowiadające im „cyfry” BCD.
Przykład 2.14. Zamiana liczby dziesiętnej na jej postać w kodzie
BCD.
(10) => (BCD)
1 (10) = 0001 (BCD)
2 (10) = 0010 (BCD)
0 (10) = 0000 (BCD)
120 (10) = 00010010000 (BCD)
Łatwo można poczynić następujące spostrzeżenia:
• Pomimo, iż kod BCD do zapisu używa cyfr dwójkowych to otrzymany
ciąg różny jest od odpowiadającej liczby dwójkowej.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
64
Podstawowe pojęcia i definicje
• Konwersja 10 → BCD lub BCD → 10 odbywa się na podobnych zasadach
jak konwersja 2 → 16 lub 16 → 2 — grupujemy bity po 4.
• Kod BCD wymaga więcej pamięci niż „tradycyjny” zapis dwójkowy.
• Konwersja jest naturalna i odbywa się prawie natychmiast.
Przyjrzyjmy się jeszcze dwu przykładom.
751 (10) = 1011101111 (2) = 011101010001 (BCD)
7 (10) = 0111 (BCD)
5 (10) = 0101 (BCD)
1 (10) = 0001 (BCD)
1072 (10) = 10000110000 (2) = 0001000001110010 (BCD)
1 (10) = 0001 (BCD)
0 (10) = 0000 (BCD)
7 (10) = 0111 (BCD)
2 (10) = 0010 (BCD)
W kodzie BCD oczywiście można wykonywać działania arytmetyczne,
ilustruje to przykład 2.15. Na przykładzie tym pokazano dodawanie w ko-
dzie BCD i tylko do dodawania ograniczymy się przy omawianiu działań.
Przykład 2.15. Dodawanie bez przeniesienia w kodzie BCD.
142 (10) = 000101000010 (BCD)
311 (10) = 001100010001 (BCD) +
--------------------------------
010001010011
|
|
|
|
|
0011 (BCD) = 3 (10)
|
|
|
0101 (BCD) = 5 (10)
|
0100 (BCD) = 4 (10)
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.3 BCD
65
Niestety nie zawsze wszystko jest tak dobrze... zauważmy, że możemy
w wyniku dodawania uzyskać na pewnej pozycji liczbę większą od 9, co
spowoduje konieczność dokonania przeniesienia, co ilustruje przykład 2.16.
Przykład 2.16. Ilustracja wystąpienia przeniesienia w dodawaniu
w kodzie BCD.
9 (10) = 1001 (BCD)
6 (10) = 0110 (BCD) +
----------------------
15 (10) = 1111 (BCD) ????
Otrzymany w przykładzie 2.16 wynik nie jest poprawną „cyfrą” kodu
BCD! Pojawia się konieczność korekcji otrzymanych wyników. Korekcja po-
lega na dodaniu liczby dziesiętnej 6 ( 0110 (BCD)) do niepoprawnej grupy 4
bitów; ma to miejsce gdy „cyfra” BCD jest większa od 1001 lub gdy nastąpi
przeniesienie z jednej czwórki bitów do następnej, ilustruje to przykład 2.17.
Przykład 2.17. Dodawanie w kodzie BCD z uwzględnieniem prze-
niesienia.
60 (10) = 01100000 (BCD)
55 (10) = 01010101 (BCD) +
----------------------------
115 (10) = 10110101
korekcja 0110
+
---------------------
100010101
000100010101
|
|
|
|
|
0101 (BCD) = 5 (10)
|
|
|
0001 (BCD) = 1 (10)
|
0001 (BCD) = 1 (10)
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
66
Podstawowe pojęcia i definicje
99 (10) =
10011001 (BCD)
99 (10) =
10011001 (BCD) +
----------------------------
189 (10) = 100110010
korekcja
01100110 +
---------------------
110011000
000110011000
|
|
|
|
|
1000 (BCD) = 8 (10)
|
|
|
1001 (BCD) = 9 (10)
|
0001 (BCD) = 1 (10)
99 (10) = 10011001 (BCD)
11 (10) = 00010001 (BCD) +
----------------------------
110 (10) = 10101010
korekcja 01100110 +
---------------------
100010000
000100010000
|
|
|
|
|
0000 (BCD) = 0 (10)
|
|
|
0001 (BCD) = 1 (10)
|
0001 (BCD) = 1 (10)
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
2.4 Zadania
67
2.4
Zadania
1. Wykonaj uproszczenie następujących wyrażeń algebraicznych, a na-
stępnie sprawdź prawdziwość metodą zerojedynkową.
a) xyz + xy + yz
b) xz + xy + yz
c) (x + y + z)(y + z)
d) (xy + z)(x + yz)
e) (xyz) + (x + y + z)
2. Dokonaj konwersji zapisu następujących liczb z systemu o podstawie
10 na liczby w systemach o podstawach 2, 8 i 16.
a) 172 b) 517
c) 778 d)
13 e)
76
f) 107 g) 300 h) 201
i)
472
j)
802
3. Dokonaj konwersji zapisu następujących liczb z systemu o podstawie
2 na liczby w systemach o podstawach 8, 16 i 10.
a)
11100 b) 1011110001
c) 10001010001 d)
100100100
e)
1110011100
f)
101110001
g)
1001001100 h)
101010000
i)
10100001
j)
1000101
4. Dokonaj konwersji zapisu następujących liczb z systemu o podstawie
16 na liczby w systemach o podstawach 2, 8 i 10.
a)
F2 b) 11F
c) AAA d)
100 e) 1AB
f) 123 g)
FF h)
F0
i)
BAB
j)
307
5. Dokonaj konwersji zapisu następujących liczb z systemu o podstawie
8 na liczby w systemach o podstawach 2, 16 i 10.
a) 123 b) 457
c) 177 d)
65 e)
22
f)
10 g)
27 h)
55
i)
222
j)
512
6. Dokonaj konwersji zapisu liczby z systemu o podstawie 7 na system o
podstawie 5.
a) 565 b) 100
c) 62 d)
12 e) 166
f) 306 g) 255 h) 32
i)
836
j)
56
7. Dokonaj konwersji zapisu liczby z systemu o podstawie 5 na system o
podstawie 11.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
68
Podstawowe pojęcia i definicje
a) 1234 b) 4222
c)
2131 d) 1421 e) 3123
f) 1121 g) 2041 h) 4131
i)
3211
j)
3114
8. Dokonaj konwersji zapisu liczby z systemu o podstawie 13 na system
o podstawie 9.
a) C99 b) 2A5
c)
91 d)
65 e) 3BC
f)
910 g)
B7 h) 18
i)
301
j)
40C
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 3
Architektura i działanie
komputera
3.1
Maszyna Turinga
U podstaw definicji Maszyny Turinga legła pewna obserwacja psycholo-
giczna dotycząca sposobu odczytywania informacji przez człowieka. Alan
Turing zauważył, że niezależnie od sposobu zapisu informacji (np. różne
rodzaje alfabetu) oraz od systemu zapisu
1
, człowiek czytając zawsze robi to
sekwencyjnie.
2
+
4 =
6
-
4 =
Rysunek 3.1: Ilustracja procesu czytania przez człowieka.
Spójrzmy na rysunek (3.1); odczytując znajdującą się na nim informa-
cję, wpierw czytamy liczbę 4, następnie operator +, z kolei drugi argu-
1
Zauważmy, że w różnych kulturach informację zapisuje się od lewa do prawa, od prawa
do lewa, lub z góry na dół.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
70
Architektura i działanie komputera
2
+
4 =
6
-
4 =
Rysunek 3.2: Kartka przekształcona w taśmę
ment dla tego operatora, czyli liczbę 3. Na koniec napotykamy na operator
=, który interpretujemy jako polecenie wykonania wcześniejszego działa-
nia. W ostatniej kratce zapisujemy wynik operacji. Zauważmy, że tylko
dzięki wiedzy wyniesionej ze szkoły wiemy co znaczą poszczególne symbole,
w szczególności + czy =. Z powyższego przykładu widać, że informacja była
odczytywana znak po znaku, lub symbol po symbolu, zatem sekwencyjnie.
W dalszym ciągu Turing zauważył, że nic nie stoi na przeszkodzie, by
naszą przykładową kartkę rozciąć na kolejne „wiersze” działań. A następnie
wiersze te skleić, tak by następowały jeden po drugim (rysunek 3.2). W ten
sposób uzyskaliśmy taśmę, która zawiera dokładnie takie same polecenia jak
macierzysta kartka z przykładami, różni się od niej jedynie formą.
Powyższy przykład jest nakreśleniem idei, która pozwoliła Turingowi na
konstrukcję jego maszyny. Maszyna ta składała się z głowicy czytająco-
piszącej (odpowiednik naszych oczu i ręki), oraz jednostki wykonującej (od-
powiednik naszego umysłu). Głowica znajdowała się nad taśmą z której
odczytywano zapisane informacje oraz na którą zapisywano wyniki. Turing
zakładał, że maszyna ta będzie umiała: przesuwać taśmę
2
, odczytywać za
pomocą głowicy znajdująca się na taśmie informację (głowica zawsze widzi
tylko jeden fragment taśmy leżącej pod nią), zapisywać informacje z powro-
tem na taśmie, wykonywać pewien skończony zbiór operacji.
Należy w tym miejscu podkreślić, że jako maszynę możemy rozważać
wyłącznie jej matematyczny model, wcale nie trzeba takiej maszyny kon-
struować fizycznie.
3.1.1
Definicja Maszyny Turinga
Formalnie poprzez Maszynę Turinga (MT) będziemy rozumieli uporząd-
kowaną czwórkę
M = (Q, Σ, δ, s),
gdzie:
2
Faktycznie Turing zakładał, że to głowica będzie się przesuwała nad taśmą, co oczy-
wiście nie ma wpływu na dalsze rozważania.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.1 Maszyna Turinga
71
• Q — skończony zbiór stanów, w których może znaleźć się maszyna.
• Σ — skończony zbiór dopuszczalnych symboli taśmowych, zwany rów-
nież alfabetem. Zbiór ten musi zawierać co najmniej dwa specjalne
symbole t i ., które oznaczają odpowiednio symbol pusty, oraz sym-
bol końcowy.
• δ — funkcja następnego ruchu, która jest odwzorowaniem δ : Q ×
Σ −→ (Q ∪ {k, t, n} × Σ) × {←, →, −}.
3
Gdzie k — stan końcowy,
t — stan akceptujący, n — stan odrzucający, zaś ←, →, − oznaczają
odpowiednio ruch głowicy w lewo, w prawo oraz pozostanie w miejscu,
przy czym ostatnie trzy symbole nie należą do sumy Q ∪ Σ.
• s – stan początkowy, jest to pewien wyróżniony stan należący do zbioru
Q.
Z powyższego określenia wynika, że zbiory Q i Σ są zbiorami niepustymi,
zakładamy również, że mają one być rozłączne.
Funkcja następnego ruchu często jest również określana jest mianem dia-
gramu (lub tablicy) przejść. Definiuje ona dla każdego stanu, stan następny,
w którym maszyna ma się znaleźć po odczytaniu symbolu z taśmy, ponadto
określa, czy zostanie wykonany ruch głowicy. Co więcej maszyna może się
znaleźć w pewnych specjalnych stanach, zatem może się po prostu zatrzy-
mać — stan k, może się zatrzymać i będzie to oznaczało akceptację czegoś
— stan t, bądź zatrzymać i odpowiedzieć przecząco — stan n.
W istocie MT nie można uznać za kompletny model komputera, ale wiele
jego składników można zamodelować przy pomocy tej maszyny, na przykład
pamięć RAM. Pokażemy teraz dwa proste przykłady Maszyn Turinga.
Przykład 3.1. Nasza Maszyna Turinga 1 (NMT1): zamiana sym-
boli.
Niech alfabet Σ składa się z symboli a, b, oraz koniecznych symboli pustego
i końcowego, zatem Σ = {t, /, a, b}. Przyjmijmy poniższy diagram przejść:
Stan
Odczytany Symbol do
Kierunek
Stan
bieżący
symbol
zapisu
ruchu głowicy kolejny
s
a
b
→
s
s
b
a
→
s
s
t
.
→
k
s
.
.
→
k
3
Funkcja δ może nie być określona dla wszystkich argumentów.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
72
Architektura i działanie komputera
Diagram ten można zapisać również w innej, bardziej sformalizowanej
formie:
q ∈ Q σ ∈ Σ
δ(q, σ)
s
a
(s, b, →)
s
b
(s, a, →)
s
t
(k, ., →)
S
.
(k, ., →)
Sytuację od której rozpoczniemy analizowanie NMT1 przedstawiono po-
niżej:
| a | b | b | a | t | . | ... taśma
NMT1 rozpoczyna działanie w stanie s, odczytując zawartość aktualnie wska-
zywanej komórki taśmy (na rysunku powyżej oznaczono to prostokątem).
Jest tam znak a zatem, zgodnie z tabelką, NMT1 zapisuje w tej komórce
znak b, przesuwa głowicę w prawo (→) i przechodzi do stanu s. Ponownie
odczytuje aktualnie wskazywany przez głowicę znak, jest nim b, zatem zapi-
suje w tej komórce znak a ... itd.
Jak widać, zdefiniowany w powyższym przykładzie „komputer” zamienia
po prostu znak a na b i b na a.
W kolejnym przykładzie, alfabet jest szerszym zbiorem i składa się
z symboli Σ = {t, ., a, b, c, ?}. NMT2 (przykład 3.2) będzie wykonywała
proces powielenia symboli, można ją nazwać „samoreplikującym się roba-
kiem”.
Przykład 3.2. Nasza Maszyna Turinga 2: samoreplikujący się ro-
bak
Tabela stanów:
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.1 Maszyna Turinga
73
Stan
Odczytany Symbol do
Kierunek
Stan
bieżący
symbol
zapisu
ruchu głowicy kolejny
s
a
?
→
s
a
b
?
→
s
b
c
?
→
s
c
.
.
−
k
s
a
a
a
→
s
a
b
b
→
s
a
c
c
→
s
a
t
a
←
s
aa
.
.
−
k
s
aa
a
a
←
s
aa
b
b
←
s
aa
c
c
←
s
aa
?
a
→
s
s
b
a
a
→
s
b
b
b
→
s
b
c
c
→
s
b
t
b
←
s
bb
.
.
−
k
s
bb
a
a
←
s
bb
b
b
←
s
bb
c
c
←
s
bb
?
b
→
s
s
c
a
a
→
s
c
b
b
→
s
c
c
c
→
s
c
t
c
←
s
cc
.
.
−
k
s
cc
a
a
←
s
cc
b
b
←
s
cc
c
c
←
s
cc
?
c
→
s
Poniższa tabela pokazuje jak zmieniać się będzie zawartość taśmy pod-
czas wykonywania programu. Ramka wskazuje komórkę znajdującą się pod
głowicą.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
74
Architektura i działanie komputera
Stan
Zawartość
automatu
taśmy
s
t
a
b
b
c
t
t
t
t
t
s
a
t
?
b
b
c
t
t
t
t
t
s
a
t
?
b
b
c
t
t
t
t
t
s
a
t
?
b
b
c
t
t
t
t
t
s
a
t
?
b
b
c
t
t
t
t
t
s
aa
t
?
b
b
c
a
t
t
t
t
s
aa
t
?
b
b
c
a
t
t
t
t
s
aa
t
?
b
b
c
a
t
t
t
t
s
aa
t
?
b
b
c
a
t
t
t
t
s
t
a
b
b
c
a
t
t
t
t
s
b
t
a
?
b
c
a
t
t
t
t
s
b
t
a
?
b
c
a
t
t
t
t
s
b
t
a
?
b
c
a
t
t
t
t
s
b
t
a
?
b
c
a
t
t
t
t
s
b
t
a
?
b
c
a
b
t
t
t
s
bb
t
a
?
b
c
a
b
t
t
t
s
bb
t
a
?
b
c
a
b
t
t
t
s
bb
t
a
?
b
c
a
b
t
t
t
s
t
a
b
b
c
a
b
t
t
t
s
b
t
a
b
?
c
a
b
t
t
t
s
b
t
a
b
?
c
a
b
t
t
t
s
b
t
a
b
?
c
a
b
t
t
t
s
b
t
a
b
?
c
a
b
t
t
t
s
bb
t
a
b
?
c
a
b
b
t
t
s
bb
t
a
b
?
c
a
b
b
t
t
s
bb
t
a
b
?
c
a
b
b
t
t
s
bb
t
a
b
?
c
a
b
b
t
t
s
t
a
b
b
c
a
b
b
t
t
s
c
t
a
b
b
?
a
b
b
t
t
s
c
t
a
b
b
?
a
b
b
t
t
s
c
t
a
b
b
?
a
b
b
t
t
s
c
t
a
b
b
?
a
b
b
t
t
s
cc
t
a
b
b
?
a
b
b
c
t
s
cc
t
a
b
b
?
a
b
b
c
t
s
cc
t
a
b
b
?
a
b
b
c
t
s
cc
t
a
b
b
?
a
b
b
c
t
s
t
a
b
b
c
a
b
b
c
t
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.2 Bramki logiczne
75
W tym miejscu nasuwa się wniosek, że każdy program zapisany przy
użyciu MT jest rozwlekły i wymaga ogromnej uwagi w czasie pisania, aby
nie popełnić błędu. Skoro jest to takie nieporęczne, to po co się nim wła-
ściwie zajmować? Powód, dla którego to czynimy, to teza Churcha. Opi-
szemy nieformalnie o czym mówi ta teza, otóż dla dowolnego algorytmu
możemy stworzyć odpowiadającą mu Maszynę Turinga
4
. Idąc dalej tym
tokiem rozumowania można założyć, że dowolny problem mający rozwiąza-
nie na znanych nam obecnie popularnych komputerach, można rozwiązać
konstruując odpowiadającą mu Maszynę Turinga. Nie szkodzi, że będzie to
konstrukcja bardzo złożona (a raczej nużąca). Ważne jest, że jak by nie była
złożona, i realizowała nie wiadomo jak skomplikowane zadania, to cały pro-
blem można sprowadzić do bardzo elementarnych działań — manipulowania
symbolami z pewnego ograniczonego alfabetu według ściśle określonych re-
guł.
3.2
Bramki logiczne
Dzisiejsze komputery konstruowane są głównie w oparciu o cyfrowe układy
scalone. W tym punkcie omówimy podstawowy składnik wszystkich cy-
frowych układów scalonych — bramkę logiczną (lub krótko bramkę).
Funkcje logiczne realizowane przez cyfrowy układ scalony są wykonywane
przez zespół bramek logicznych połączonych w różny sposób ze sobą.
Bramka jest układem elektronicznym, którego sygnał wyjściowy jest wy-
nikiem operacji Boole’a na sygnałach wejściowych. Podstawowymi bram-
kami stosowanymi w cyfrowych układach logicznych są bramki logicznego
iloczynu (oznaczenie AND), logicznej sumy (OR), oraz logicznej negacji
(NOT), odpowiadają one trójce zdefiniowanych wcześniej działań w alge-
brze Boole’a (zob. 2.1). Również często spotykanymi bramkami są negacje
iloczynu i sumy logicznej, oznaczane odpowiednio NAND i NOR. Poniżej
przedstawiamy działania realizowane przez te bramki.
4
Jest to teza, którą nie umiemy udowodnić, ponieważ nie da się precyzyjnie zdefniować
„dowolnego algorytmu”.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
76
Architektura i działanie komputera
X
Y
XY
AND
X
Y
X+Y
OR
X
X
NOT
X
Y
XY
NAND
X
Y
X+Y
NOR
X
Y
X Y
⊗
XOR
Rysunek 3.3: Symbole reprezentujące bramki AND, OR, NOT, NAND,
NOR i XOR.
Symbol NOT
AND
OR
NAND
NOR
X
Y
X
X · Y
X + Y
X · Y
X + Y
0
0
1
0
0
1
1
0
1
1
0
1
1
0
1
0
0
0
1
1
0
1
1
0
1
1
0
0
Elektronicy przypisali bramkom pewne symbole graficzne w celu ich ła-
twiejszego zobrazowania na rysunkach zwanych schematami ideowymi (rys.
3.2).
Podstawowe bramki logiczne mają jedno lub dwa wejścia i jedno wyjście.
W praktyce często stosuje się bramki o większej ilości wejść. Dzięki temu
wyrażenie X + Y + Z może być zrealizowane za pomocą jednej bramki OR
o trzech wejściach.
Zwykle nie wszystkie bramki są używane do implementacji. Projektowa-
nie i wytwarzanie cyfrowego układu scalonego jest tym prostsze, im używa
się mniej różnych rodzajów bramek. Okazuje się, że wszystkie operacje
logiczne można zrealizować za pomocą jednej lub kilku bramek logicznych.
Czyli jedne operacje logiczne można zastąpić sekwencją innych. Stąd, zbiory
bramek za pomocą których można zrealizować wszystkie pozostałe opera-
cje logiczne nazywamy zbiorami funkcjonalnie pełnymi. Następujące
zbiory są funkcjonalnie pełne:
• AND, OR, NOT
• AND, NOT
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.2 Bramki logiczne
77
X
X
X
X
X
Y
XY
X
Y
X+Y
Y
X
X+Y
Y
X
XY
Rysunek 3.4: Realizacja bramek AND, OR , NOT za pomocą bramek
NAND lub NOR.
• OR, NOT
• NAND
• NOR
Oczywiste jest, że bramki AND, OR, NOT tworzą zbiór funkcjonalnie pełny,
ponieważ reprezentują one trzy operacje algebry Boole’a. Aby bramki AND
i NOT mogły stanowić zbiór funkcjonalnie pełny, musi istnieć sposób za-
stąpienia operacji OR przy ich pomocy. Można to uczynić, korzystając
z następującej własności (prawo de Morgana — patrz Twierdzenie 2.2):
(X · Y ) = X + Y = X + Y
Na podobnej zasadzie operacje OR i NOT stanowią zbiór funkcjonalnie
pełny. Na rysunku 3.2 przedstawiono sposób realizacji bramek AND, OR,
NOT wyłącznie za pomocą bramek NAND lub NOR. Dzięki temu układy
cyfrowe mogą być i często są realizowane wyłącznie za pomocą bramek
NAND lub NOR.
Bardzo często spotykaną bramką jest XOR (eXclusive OR) — czyli wy-
łączne lub. Funkcja przez tę bramkę realizowana jest wykorzystywana mię-
dzy innymi do obliczeń przy kodach cyklicznych CRC (patrz 4.3.3). Symbol
bramki XOR przedstawia rysunek (3.2), zaś jej działanie poniższa tabela:
X
Y
X ⊕ Y
0
0
0
0
1
1
1
0
1
1
1
0
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
78
Architektura i działanie komputera
3.3
Architektura współczesnego komputera
Mówiąc o architekturze komputera w tym punkcie będziemy mieli na my-
śli jego podstawowe komponenty, które są niezbędne do jego prawidłowego
funkcjonowania, bądź trwale kojarzone z komputerami. Poprzez komputer
będziemy rozumieli wszelkie urządzenia komputerowe, zatem nie tylko kom-
putery osobiste, ale również sterowniki komputerowe czy też komputery po-
kładowe dla samolotów. Dlatego też będziemy pomijali wszelkie urządzenia
wewnętrzne czy zewnętrzne, które powszechnie określa się mianem peryfe-
riów, a które to nie są niezbędne. Przyjmując powyższe uproszczenie, można
wyróżnić następujące trzy zasadnicze składowe dzisiejszego komputera:
Procesor — główny układ wykonujący rozkazy, często też zawierający
w sobie koprocesor numeryczny — realizujący operacje na liczbach
zmiennoprzecinkowych.
Pamięć — wyróżnia się zasadniczo dwa rodzaje pamięci: pamięcią o do-
stępie swobodnym — służy jako magazyn dla rozkazów (program),
danych oraz wyników operacji na tych danych, oraz pamięć stałą w
której „zaszyty” jest podstawowy program komputera (BIOS lub inne
tego rodzaju).
Wejście/Wyjście — (ang. Input/Output (I/O)), zapewniające dostęp do
świata zewnętrznego.
Należy zwrócić uwagę na fakt, że wymienione wyżej elementy nieko-
niecznie muszą występować jako osobne urządzenia. Dla przykładu mikro-
procesory jednoukładowe zawierają większość z tych elementów w sobie tj.
zamknięte w jednej obudowie układu scalonego. Przeznaczenie tego typu
układów to wszelkiego rodzaju sterowniki np. pralki czy maszyny szwalni-
czej. W tych zastosowaniach twórcom często zależy na niewielkich gabary-
tach i zwartości układu.
Komputer złożony z pamięci, procesora i układów wejścia/wyjścia bę-
dzie prawidłowo funkcjonował o ile, coś nada mu rytm pracy, tym elemen-
tem będzie zegar systemowy. Przy czym nie wyróżnia się zwykle tego
elementu jako czegoś osobnego, zakłada się, że jest on niezbędny i pomija
się przy omawianiu uproszczonej architektury. Schematyczna ilustracja ar-
chitektury pokazana jest na rysunku 3.5.
Wymienione elementy składowe muszą komunikować się ze sobą. Komu-
nikacja ta odbywa się poprzez magistrale systemowe. Najprościej mówiąc
magistrale te są rodzajem kanałów przez które płynie informacja, w jedną
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.3 Architektura współczesnego komputera
79
CPU
I/O
Memory
magistrala danych
magistrala adresowa
główna magistrala
Rysunek 3.5: Ilustracja architektury współczesnego komputera.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
80
Architektura i działanie komputera
lub w drugą stronę. Kanały te składają się z kilku, kilkunastu, czy kilku-
dziesięciu przewodników elektrycznych
5
. Zasadniczo wyróżnia się trzy magi-
strale, które zostały omówione poniżej, przy niektórych z nich ważną cechą
charakterystyczną jest tzw. szerokość magistrali, która mówi o ilości
bitów informacji, która może zostać przesłana jednocześnie tą magistralą
6
.
Magistrala danych — (ang. Data Bus) jest kanałem przez który płyną
w obie strony dane, zatem zapewnia przesył do i z procesora, do i z
pamięci itd
7
. Magistrala danych ma pewną szerokość, zwykle 8, 16,
32, lub 64 bity.
Magistrala adresowa — (ang. Address Bus) dostarcza informacji o adre-
sach pod które mają trafić dane, lub spod których mają zostać odczy-
tane
8
. Szerokość magistrali adresowej jest bardzo ważna, mówi ona
o tym jaką przestrzeń adresową możemy obsłużyć przy pomocy tego
procesora. Przypomnijmy, że 2
10
= 1024, zatem na 10-cio bitowej ma-
gistrali adresowej możemy wyznaczyć adresy zaledwie 1024 komórek
pamięci!
Magistrala sterująca — (ang. System Bus) jest kanałem do przesyła-
nia informacji o stanie systemu, zachowaniach urządzeń zewnętrznych
itp. Szerokością tej magistrali interesują się wyłącznie producenci płyt
głównych i układów towarzyszących, dla przeciętnego użytkownika nie
ma to najmniejszego znaczenia.
Spośród opisanych wyżej podstawowych elementów architektury kompu-
tera, procesor jest tym, który w największym stopniu rzutuje na możliwości
jakimi dysponuje system komputerowy. Dlatego też poświęcimy mu szcze-
gólnie dużo miejsca, odkładając jego opis do następnego podrozdziału (zob.
3.4). Teraz skupimy się na omówieniu pozostałych dwu składowych.
Powiedzieliśmy, że procesor jest tym najistotniejszym czynnikiem ma-
jącym wpływ na wydajność systemu, jednak pamięć ma również ogromny
wpływ na sprawność całego układu. Obecnie dysponujemy bardzo szeroką
gamą pamięci o dostępie swobodnym zwanych też pamięciami RAM (ang.
5
Mogą nimi być ścieżki drukowane — linijki miedzi na specjalnym podkładzie na któ-
rym montuje się układy scalone lub inne elementy, a mogą to być odpowiednie struktury
w krzemie wewnątrz układu scalonego.
6
Jest to nierozerwalnie związane z ilością fizycznych połączeń — jedno połączenie może
na raz przesłać jeden bit informacji
7
Oczywiście nie jest to proces jednoczesny, zatem np. najpierw się pobiera dane,
po czym je wysyła.
8
Spotyka się również określenie wystawienie adresu określające proces adresowania.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.3 Architektura współczesnego komputera
81
rejestry
droga
tania
szybka
wolna
operacyjna
CD, DVD
HDD
Rysunek 3.6: Ilustracja zależności kosztów pamięci, ich pojemności i czasu
dostępu.
Random Access Memory), mając tym samym duże możliwości wyboru przy
projektowaniu komputera zależnie od potrzeb i dostępnych środków finan-
sowych. W celu lepszej ilustracji tego faktu, dokonamy porównania pamięci
RAM z innymi nośnikami informacji, które nie muszą występować jako pod-
stawowy składnik komputera
9
. Najłatwiej pogrupować pamięci wszelkiego
typu przypisując każdej z nich odpowiednie miejsce w piramidzie na rysunku
3.6
10
.
W zależności od kierunku przeglądania tej piramidy możemy pamięci
klasyfikować ze względu na:
czas dostępu — jest to czas jaki musi upłynąć od momenty wystawienia
żądania odczytu danej o zadanym adresie do momentu jej uzyskania,
dla przykładu przy pamięci RAM będzie to 10 nanosekund, a dla
twardego dysku nawet 10 milisekund,
cenę — zwykle im większa gęstość zapisu tym wyższa cena, poprzez gęstość
9
Co więcej nawet jeśli występują to komunikacja pomiędzy procesorem a nimi od-
bywa się przez układy wejścia/wyjścia. Zatem nie należy wyciągać błędnych wniosków
i w miejsce pamięci RAM wkładać dysku twardego.
10
Prezentowana piramida jest pewnym rodzajem uproszczenia, nie należy jej traktować
zbyt dosłownie. Okazuje się np. że równie ważnym czynnikiem wpływającym na cenę
poza pojemnością jest technologia wykonania.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
82
Architektura i działanie komputera
zapisu będziemy rozumieli tutaj stosunek pojemności do gabarytów
nośnika informacji
11
. Jednak zależy to mocno od technologii i tak dla
przykładu pamięć RAM jest dużo droższa od płyty CD-R a nawet
CD-R/W.
pojemność — na samej górze są pamięci najszybsze, ale jednocześnie małe
gdyż bardzo kosztowne; na dole pamięci najwolniejsze, ale o bardzo
dużej pojemności a przez to tanie (koszt rozpatrywany jest w przeli-
czeniu na pewną ustaloną jednostkę pojemności, na przykład bajt czy
kilobajt).
Stosując kryteria odwołujące się do fizycznej natury pamięci można je także
pogrupować ze względu na:
lokalizację — czyli położenie w komputerze, przykładowo: wewnątrz pro-
cesora (pamięć podręczna — cache), wewnątrz komputera (pamięć
RAM, ROM), zewnętrzna (wszelkiego typu inne nośniki w tym dys-
kietki);
wydajność — na ogólną wydajność wpływ będą miały następujące czyn-
niki: czas dostępu, szybkość transmisji, długość cyklu dostępu;
trwałość przechowywanej informacji — pamięć ulotna np. RAM jej
zawartość ginie po odcięciu zasilania, nieulotna np. dysk twardy, wy-
mazywalna np. płyta CD-RW, niewymazywalna np. płyta CD-R;
charakter fizycznego zapisu — półprzewodnikowe, magnetyczne, optycz-
ne;
sposób dostępu — sekwencyjny np. pamięci taśmowe, bezpośredni, swo-
bodny np. RAM.
Na ogół w systemie stosuje się kilka różnych rodzajów pamięci co po-
dyktowane jest poszukiwaniem kompromisu pomiędzy kosztem, wydajno-
ścią i możliwościami. Najwydajniejsze pamięci są bowiem jednocześnie naj-
droższe, dlatego ogranicza się ich rozmiar przechowując dane wykorzystując
wolniejsze pamięci, ale o dużo większej pojemności i mniejszym koszcie.
Patrząc na piramidę widzimy, że pamięci stanowiące podstawowy skład-
nik architektury komputera, czyli pamięci o dostępie swobodnym są zwykle
11
Stąd też dysk twardy o tej samej pojemności do komputera biurowego, będzie miał
niższą cenę niż do notebooka, gdzie jego wielkość musi być znacznie mniejsza.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
83
stosunkowo małe i bardzo drogie, zwłaszcza dotyczy to pamięci podręcz-
nych. W chwili obecnej jednak nawet w zakresie pamięci o dostępie swo-
bodnym mamy bardzo szeroki wybór technologii zwłaszcza, że nawet w ra-
mach jednej z nich istnieje możliwość zakupu pamięci taktowanych różnymi
częstotliwościami.
Ostatnim elementem podstawowej architektury komputera są układy
(urządzenia) wejścia/wyjścia. Nie są one konieczne do prawidłowego funk-
cjonowania systemu, ale umożliwiają interakcję pomiędzy nim a otoczeniem,
które stanowi źródło danych podlegających przetworzeniu
12
. Ze względu na
ich dużą różnorodność a także ścisłą zależność od specyfiki rozwiązywanych
zadań nie będziemy ich tutaj bliżej przedstawiać. Nadmieńmy tylko, że
w klasycznym komputerze osobistym można mówić na takich urządzeniach
wejścia/wyjścia jak: port równoległy, port szeregowy (zwykle podłączana
jest do niego mysz lub modem zewnętrzny).
3.4
Procesor — serce komputera
Architekturę procesora omówimy na przykładzie układu Intel 8086, przy
czym zostanie ona uproszczona w sposób wystarczający do omówienia pod-
stawowych cech. Schematyczna ilustracja wnętrza procesora znajduje się
rysunku 3.7. Zasadniczo w procesorze 8086 wyróżnia się dwa główne ele-
menty: układ wykonawczy (EU) (ang. Execution Unit), oraz układ
sterowania magistrali (BUI) (Bus Interface Unit). Przy czym układ
wykonawczy składa się z dalszych podjednostek, które spełniają następu-
jącą rolę:
Rejestry — komórki pamięci wewnątrz procesora o specjalnym przezna-
czeniu (szerszy ich opis można znaleźć w punkcie 3.4.2).
ALU — jednostka arytmetyczno-logiczna, przeznaczona do wykonywania
podstawowych operacji na liczbach całkowitych.
FPU — jednostka zmienno-przecinkowa, zwana również koprocesorem,
zajmująca się realizacją obliczeń na liczbach zmienno-przecinkowych.
IU — jednostka dekodowania rozkazów, zajmująca się dekodowaniem roz-
kazów i żądaniem ewentualnych argumentów dla tych rozkazów.
Z kolei układ sterowania magistrali składa się z następujących jednostek:
12
Choć niekonieczne, trudno sobie wyobrazić działanie bez nich, wszak komputer który
nie komunikuje się ze światem zewnętrznym jest jakby trochę niekompletny.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
84
Architektura i działanie komputera
AU
MMU
ALU
FPU
EU
IU
Reg
BIU
Bus
Rysunek 3.7: Architektura procesora Intel 8086.
AU — jednostka adresująca, która zajmuje się wyliczaniem adresu efek-
tywnego. Adres efektywny to faktyczny adres pod którym znajduje
się żądana dana. Nie jest ona zawsze zgodny z adresem przez który
następuje odwołanie, a to ze względu na różne sposoby adresowania
(patrz 3.4.4).
MMU — jednostka zarządzająca pamięcią, która wspiera pobieranie danej
bądź rozkazu z komórek pamięci.
3.4.1
Cykl pracy procesora
Zadaniem procesora, jak to było powiedziane już wcześniej, jest wykony-
wanie rozkazów zapisanych w pamięci. Samą budową rozkazu zajmiemy się
w punkcie 3.4.3. W tym miejscu skoncentrujemy się na realizacji rozkazów
i jej przebiegu.
Realizacja rozkazu w procesorze odbywa się w cyklach. Cyklem na-
zwiemy pewną sekwencję stałych kroków, których celem jest realizacja bądź
całego rozkazu, bądź jego fragmentu. W przypadku procesora 8086 w zależ-
ności od rodzaju rozkazu mogą wystąpić maksymalnie cztery główne cykle:
pobranie — (ang. fetch) w tym cyklu rozkaz zostaje pobrany z pamięci
do procesora,
odczyt — (ang. read) jeśli rozkaz wymaga pobrania argumentu (argu-
mentów) z pamięci, to zostaje wyznaczony ich adres efektywny (patrz
3.4.4), a następnie argument (argumenty) ten jest pobierany od pro-
cesora,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
85
wykonanie — (ang. execute) operacja, która jest opisana obrabianym roz-
kazem, jest wykonywana,
zapis — (ang. write) jeśli w wyniku operacji powstał rezultat, który ma
być umieszczony w pamięci, to zostaje dla niego wyznaczony adres
efektywny i wykonywany jest zapis.
W przypadku współczesnych procesorów stosuje się różnego rodzaju opty-
malizacje, które mają na celu przyśpieszenie pracy procesora, a w konse-
kwencji całego systemu. Nie inaczej jest w przypadku procesora 8086. Po-
nieważ układ wykonawczy i układ sterowania magistrali pracują niezależ-
nie, to jeśli tylko dane zostały pobrane z BUI do EU, BUI pobiera kolejne
bajty, które czekają w kolejce rozkazów. Operacja ta nosi nazwę pobra-
nia wstępnego (ang. prefetch) i może przebiegać równocześnie z cyklem
wykonywania. Dzięki temu uzyskuje się znaczny wzrost prędkości realizacji
rozkazów
13
.
W przypadku procesora 8086, każdy rozkaz (omówienie szczegółowe roz-
kazów i ich przykładów znajduje się w 3.4.5), a dokładniej jego wykonanie
składa się z co najmniej dwu etapów, zatem można przedstawić następujące
schematy cyklów realizacji rozkazów:
pobranie + wykonanie — rozkaz ADD AX, BX — dodaje wartości pocho-
dzące z dwu rejestrów do siebie, argumentami są rejestry i nie trzeba
wykonywać pobrania argumentów z pamięci,
pobranie + odczyt + wykonanie — rozkaz ADD AX, ZMIENNA — do-
daje do rejestru wartość zmiennej, w tym przypadku musi zostać po-
brana wartość zmiennej z pamięci,
pobranie + wykonanie + zapis — rozkaz MOV ZMIENNA, AX — zapisa-
nie wartości rejestru do zmiennej, adres zmiennej w pamięci musi zo-
stać wyznaczony i następuje zapis pod ten adres,
pobranie + odczyt + wykonanie + zapis — rozkaz ADD ZMIENNA, AX
— rozkaz dodaje zawartość rejestru AX do zmiennej (jej wartość musi
być wpierw pobrana), wynik jest umieszczany w pamięci.
13
W najnowszych procesorach spotyka się jeszcze inne sposoby optymalizacji, przy-
kładem może być przetwarzanie potokowe, które dopuszcza np. jednoczesne obrabianie
pięciu rozkazów.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
86
Architektura i działanie komputera
3.4.2
Rejestry procesora Intel 8086
W procesorze Intel 8086 wyróżniamy następujące rejestry
• Rejestry ogólnego przeznaczenia (ang. General Purpose Registers)
14
:
AX (AH/AL) rejestr akumulatora (ang. Accumulator), rejestr ten
jest przeznaczony do wykonywania podstawowych operacji aryt-
metycznych i logicznych, w szczególności większość wyników tra-
fia właśnie do tego rejestru. Przykładem może być rozkaz ADD
AX, BX
dodający zawartość rejestru AX i BX oraz zapamiętujący
wynik w rejestrze AX.
BX (BH/BL) rejestr bazowy (ang. Basis Register), rejestr ten czę-
sto wykorzystywany jest w parze z AX przy operacjach aryt-
metycznych, ale również jako rejestr pomocniczy przy bardziej
skomplikowanym adresowaniu pamięci.
CX (CH/CL) rejestr licznika (ang. Count Register ), rejestr ten jest
przede wszystkim wykorzystywany przy okazji pętli realizowanej
przy pomocy rozkazu LOOP, gdzie wartość jego jest automatycznie
zmieniana i w ten sposób jest on licznikiem tej pętli przez co
również jednym z warunków jej zakończenia.
DX (DH/DL) rejestr danych (ang. Data Register), rejestr ten na
przykład wykorzystywany jest przy operacji mnożenia MUL AX,
BX
dwu rejestrów 16-to bitowych, w wyniku czego otrzymujemy
liczbę 32 bitową i pierwsze dwa bajty będą pamiętane w rejestrze
AX a ostatnie dwa właśnie w rejestrze DX.
• Rejestry segmentowe (ang. Segment Registers):
CS rejestr segmentu kodu (ang. Code Segment Register), rejestr ten
przechowuje adres segmentu kody programu.
DS rejestr segmentu danych (ang. Data Segment Register), rejestr
ten przechowuje adres segmentu danych programu.
SS rejestr segmentu stosu (ang. Stack Segment), rejestr ten przecho-
wuje adres początku segmentu stosu o ile jest on wykorzystywany
w programie.
14
Prawdę powiedziawszy rejestry te (co widać choćby po ich opisie), są mocno specja-
lizowane, zatem nazywanie ich rejestrami ogólnego przeznaczenia jest mocno na wyrost.
Stosujemy jednak dosłowne tłumaczenie oryginalnej dokumentacji i jednocześnie nazew-
nictwo powszechnie przyjęte w literaturze polskiej.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
87
Rysunek 3.8: Rozmieszczenie flag w rejestrze flagowym (wyjaśnienie ozna-
czeń znajduje się w tekście).
ES rejestr dodatkowy (ang. Extra Segment Register).
• Rejestry wskaźnikowe (ang. Pointer Registers):
SI rejestr źródła (ang. Source Index), najczęściej wykorzystywany
jest przy adresowaniu pośrednim.
DI rejestr przeznaczenia (ang. Destination Index), wykorzystywany
jest podobnie jak rejestr SI.
IP rejestr rozkazów (ang. Instruction Pointer), wspólnie z rejestrem
CS informuje o numerze aktualnie przetwarzanego rozkazu.
• Rejestry stosu (ang. Stack Registers):
SP rejestr wskaźnika stosu (ang. Stack Pointer).
BP rejestr wskaźnika bazy (ang. Base Pointer).
• Rejestry stanu (Status Registers):
FLAGS rejestr flagowy (Status Flags), przechowuje informację o sta-
nie procesora, dokładniejszy opis znajduje się w dalszej części
punktu.
Wszystkie wymienione rejestry są 16-to bitowe, przy czym w przypadku
rejestrów ogólnego przeznaczenia jest możliwość bezpośredniego odwoływa-
nia się do górnej i dolnej ich połowy, zatem do starszego i młodszego bajtu
poprzez odpowiednie nazwy: AH — odwołanie do starszego bajtu, zaś AL
— odwołanie do młodszego bajtu rejestru AX, podobnie dla pozostałych
rejestrów z tej grupy.
Rejestr flagowy jest traktowany jako zbiór bitów, dla których przypisuje
się odpowiednie znaczenie (patrz rysunek 3.8), poza kilkoma wyjątkami nie
ma rozkazów odwołujących się do niego jako całości. Istnieje natomiast cała
grupa rozkazów, które potrafią sprawdzać poszczególne jego bity.
Poniżej znajduje się opis znaczenia poszczególnych bitów rejestru flago-
wego zaś ich rozkład pokazany jest na rysunku 3.8, przy czym bity ustawione
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
88
Architektura i działanie komputera
na wartość 0 lub 1 są zarezerwowane dla następnych generacji procesora.
Najogólniej mówiąc rejestr flagowy, a dokładniej jego bity służą do uzyska-
nia informacji o stanie procesora, lub wyniku ostatnio wykonywanej operacji
i tak:
CF — (ang. Carry Flag) flaga przeniesienia jest ustawiana przez opera-
cje arytmetyczne, jeśli w wyniku ostatnio wykonywanej operacji nastą-
piło przeniesienie na najstarszym bicie, np. dodanie dwu liczb 8-mio
bitowych może dać w wyniku liczbę 9-cio bitową.
PF — (ang. Parity Flag) flaga parzystości jest ustawiana przez opera-
cje jeśli w wyniku ich wykonania liczba bitów o wartości 1 w mniej
znaczącym bajcie wyniku jest nieparzysta.
AF — (ang. Auxiliary Flag) flaga pomocnicza ustawiana głównie przy
operacjach na kodzie BCD. Flaga ta jest ustawiana, gdy w wyniku
operacji nastąpiło przeniesienie z bitu 3 na 4 lub pożyczka z bitu 4 na
3.
ZF — (ang. Zero Flag) flaga zera ustawiana przez operacje arytmetyczne
i logiczne, np. przy operacji porównywania dwu liczb. Jest ustawiana,
gdy wynik działania jest równy zero, w przeciwnym wypadku jest
zerowana.
SF — (ang. Sign Flag) flaga znaku ustawiana przez operacje arytme-
tyczne, gdy najstarszy bit w otrzymanym wyniku jest równy 1, w prze-
ciwnym wypadku jest zerowana.
TF — (ang. Trap Flag) flaga pracy krokowej ustawiona na wartość
1 wprowadza procesor w tryb pracy krokowej (ang. Single Step
Modus). W trybie tym po każdym wykonanym rozkazie wygenerowane
zostaje przerwanie i przejście do specjalnej procedury obsługi. Tryb
ten wykorzystywany jest do testowanie niskopoziomowych procedur,
głównie przez konstruktorów systemów procesorowych. Wyzerowanie
tej flagi powoduje powrót do normalnego trybu pracy.
IF — (ang. Interrupt Flag) flaga zezwolenia na przerwanie ustawiona
na 1 powoduje odblokowanie systemu obsługi przerwań. Wyzerowanie
tej flagi powoduje, że procesor będzie ignorował zewnętrzne przerwa-
nia.
DF — (ang. Direction Flag) flaga kierunku jest wykorzystywana przy
działaniach na łańcuchach znaków. Jeśli jest ustawiona na 1 to rejestry
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
89
Rysunek 3.9: Uproszczony schemat rozkazu procesora Intel 8086 (wyjaśnie-
nie oznaczeń znajduje się w tekście).
DI i SI będą zwiększane przy tych operacjach, w przeciwnym wypadku
zmniejszane.
OF — (ang. Overflow Flag) flaga przepełnienia ustawiana jest przez roz-
kazy arytmetycznie, jeśli wystąpiło przepełnienie, przykładem może
być rozkaz mnożenia.
3.4.3
Budowa rozkazu
Uproszczona postać rozkazu procesora Intel 8086 znajduje się na rysunku
3.9. Rozkaz składa się z 1-go do 6-ciu następujących po sobie bajtów, przy
czym pierwsze dwa opisują w całości rozkaz jako taki, zaś ostatnie cztery są
bądź danymi bezpośrednimi — tak będzie w przypadku rozkazu ADD AX,
05h
(dodaje on do rejestru AX wartość 05 zapisaną szesnastkowo), bądź
adresem gdzie szukać danych, lub gdzie umieszczać wyniki.
Pierwsze dwa bajty nie są jednak interpretowane po prostu jako numer
rozkazu, z rysunku wynika, że są one podzielone i każda z ich części ma
określone znaczenie opisane poniżej:
KOD — jest to kod rozkazu, który ma być wykonany.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
90
Architektura i działanie komputera
D — flaga informująca, czy dane mają być pobierane czy też przesyłane do
rejestru.
W — flaga informująca czy działania będą wykonywane na bajtach czy
słowach.
MOD — informuje gdzie leżą argumenty, w pamięci czy rejestrach.
REG — określa jaki rejestr jest argumentem, lub jest rozszerzeniem roz-
kazu.
R/M — określa rejestr będący argumentem lub rejestr wykorzystywany do
obliczenia adresu względem początku segmentu.
Z powyższego opisu można wywnioskować, że interpretacja poszczególnych
kawałków rozkazu jest zależna od wielu czynników. Dla przykładu część
REG może być informacją mówiącą lub inaczej doprecyzowującą o jaki roz-
kaz chodzi. Zauważmy, że gdyby tylko KOD mówił o tym jaki to rozkaz, to
przy długości 5 bitów
15
możemy mieć zaledwie 2
5
− 1 = 63 rozkazy, podczas
gdy skądinąd wiemy, że w procesorze Intel 8086 mamy do dyspozycji ponad
dwieście rozkazów. Zatem część REG składająca się z 3 bitów jest sposobem
obejścia tego ograniczenia.
Z pewnością przyglądając się postaci rozkazu w omawianym procesorze
można zadać pytanie, skąd mamy wiedzieć jakie wartości poszczególnym
częściom należy nadać by uzyskać zamierzony efekt. Do tego celu służy
specyfikacja rozkazów dla danego procesora, która dokładnie omawia uło-
żenie zer i jedynek dla danego rozkazu. Przyznajemy, że pisanie programu
w ten sposób jest bardzo męczące i w obecnej chwili nikt tego tak ne robi,
a specyfikacja tych rozkazów jest potrzebna wyłącznie wąskiej grupie progra-
mistów piszących asemblery, czyli programy tłumaczące zapis mnemoniczny
na kod maszynowy (patrz 3.4.5).
3.4.4
Adresowanie
W celu lepszego zrozumienia złożoności pracy procesora opiszemy również
sposoby adresacji komórek pamięci. W zależności od tego gdzie dana jest
umieszczona (pamiętana) dostęp do niej jest łatwiejszy, bądź trudniejszy.
Co więcej przekłada się to wprost na czas potrzebny na pobranie tej danej,
dalej ma to wpływ na czas realizacji konkretnego rozkazu. Dzieje się tak
ponieważ dana, która ma być przetworzona zawsze musi zostać pobrana do
15
Bajt złożony jest z 8-miu bitów i odejmujemy po jednym bicie na flagi D, W, S.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
91
procesora, a może przecież znajdować się w rejestrze (wtedy nic nie trzeba
robić), w pamięci RAM (należy ją pobrać) czy nawet na porcie COM (należy
ją odczytać). Co więcej, zanim taka dana będzie pobrana, należy stwierdzić
czy wiemy wprost (natychmiast) gdzie ona się znajduje, czy też może znamy
wyłącznie adres do niej. Wówczas najpierw należy wyznaczyć tzw. adres
efektywny, by na końcu przy jego użyciu pobrać daną.
Celem lepszego zrozumienia złożoności problematyki można posłużyć się
takim prostym przykładem: wyobraźmy sobie, że musimy do kogoś zadzwo-
nić. Po pierwsze możemy pamiętać do tej osoby numer telefonu, wtedy
natychmiast wybieramy numer i trwa to chwilkę. Po drugie, możemy mieć
numer zapisany w notesie, wtedy trwa to odrobinę dłużej. Po trzecie, mo-
żemy nie mieć numeru, ale pamiętamy numer do kolegi, który z pewnością
ten nasz docelowy numer pamięta. Ponieważ kolegi może nie być w domu
może to trwać dość długo. Po czwarte, możemy mieć numer do kolegi, który
owszem ma ten numer docelowy ale zapisany, zatem nie tylko kolega musi
być w domu, ale jeszcze musi odszukać notes z numerem (a jeśli kolega jest
bałaganiarzem?). Po piąte, możemy mieć numer do kolegi, który zna kogoś
kto zna nasz docelowy numer itd.
Poniżej wypisane zostały różne sposoby adresowania, w kolejności od
najprostszego do najtrudniejszego i w przybliżeniu od najszybszego do naj-
wolniejszego
16
. Przykłady zostały podane w zapisie mnemonicznym (patrz
3.4.5).
1. adresowanie natychmiastowe występuje gdy wartość podana jest
bezpośrednio: MOV AX, 34h — załadowanie do rejestru AX wartość
34 szesnastkowo. (Rysunek 3.10)
2. adresowanie bezpośrednie z rejestru występuje gdy operujemy
na dwu rejestrach: MOV AX, BX — załadowanie danej z rejestru BX
do AX. (Rysunek 3.11)
3. adresowanie bezpośrednie z pamięci występuje gdy argument jest
przekazywany przez adres: MOV AX, [0FFh] — załadowanie wartości
spod adresu 0FF szesnastkowo do rejestru AX
17
. (Rysunek 3.12)
4. adresowanie pośrednie przez rejestr bazowy w tym przypadku
adres efektywny jest w rejestrze BX lub BP: MOV AX, [BP] — załado-
16
W przybliżeniu, gdyż, czasami zależy to od konkretnego rozkazu. Jednak z pewnością
operacje na rejestrach są realizowane najszybciej.
17
Zapis w nawiasie kwadratowym oznacza pobranie zawartości komórki adresowanej
przez adres umieszczony w tym nawiasie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
92
Architektura i działanie komputera
wanie zawartości komórki, której adres jest w rejestrze BP, do rejestru
AX. (Rysunek 3.13)
5. adresowanie pośrednie przez rejestr bazowy i offset
18
w tym
przypadku adres jest w rejestrze BX lub BP ale dodatkowo się go
przesuwa: MOV AX, [BP+5] — załadowanie zawartości komórki, któ-
rej adres jest o pięć bajtów dalej niż adres umieszczony w rejestrze
BP, do rejestru AX. (Rysunek 3.14)
6. adresowanie pośrednie przez rejestr indeksowy w tym przy-
padku adres znajduje się w rejestrze indeksowym DI lub SI: MOV AX,
[SI]
— załadowanie wartości komórki, której adres znajduje się w re-
jestrze SI, do rejestru AX. (Ilustracja analogiczna jak na rysunku 3.13
tylko z udziałem rejestru indeksowego)
7. adresowanie pośrednie przez rejestr indeksowy i offset w tym
przypadku adres jest w rejestrze DI lub SI ale dodatkowo jest on prze-
suwany: MOV AX, [SI+6] — załadowanie zawartości komórki, której
adres jest o 6 bajtów dalej niż adres zapisany w rejestrze SI, do reje-
stru AX. (Ilustracja analogiczna jak na rysunku 3.14 tylko z udziałem
rejestru indeksowego)
8. adresowanie pośrednie przez rejestr bazowy i indeksowy adres
komórki jest wyliczany na podstawie zawartości dwu rejestrów: MOV
AX, [BX+SI]
— załadowanie zawartości komórki, której adres jest
sumą adresów rejestru BX i SI, do rejestru AX. (Rysunek 3.15)
9. adresowanie pośrednie przez rejestr bazowy, indeksowy i off-
set podobnie jak poprzednie adresowanie ale dochodzi jeszcze przesu-
nięcie: MOV AX, [BX+SI+5] — załadowanie zawartości komórki, któ-
rej adres jest sumą rejestru BX, SI i wartości 5, do rejestru AX. (Ry-
sunek 3.16)
10. adresowanie układów wejścia/wyjścia — służy do odnoszenia się
portów wejścia/wyjścia w celu wysłania lub pobrania z nich informacji.
Do takich portów podłączona jest np. drukarka.
Jak widać programista ma bardzo szerokie możliwości pobierania za-
wartości komórek pamięci, co więcej prawie wszystkie te sposoby można
mieszać. Powoduje to z jednej strony dużą elastyczność, a z drugiej spore
18
offset to po prostu przesunięcie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
93
OC
ARG
Rysunek 3.10: Adresowanie natychmiastowe.
OC
REG1
REG2
ARG1(AX)
ARG2(BX)
...
IP
BP
SI
...
Rysunek 3.11: Adresowanie bezpośrednie z rejestru.
OC
MEM1
MEM2
ARG2
ARG1
Rysunek 3.12: Adresowanie bezpośrednie z pamięci.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
94
Architektura i działanie komputera
OC
REG
AX
BX
...
IP
BP
SI
...
ARG
Rysunek 3.13: Adresowanie pośrednie przez rejestr bazowy.
OC
OFFSET
AX
BX
...
IP
BP
SI
...
ARG
+
OFFSET
Rysunek 3.14: Adresowanie pośrednie przez rejestr bazowy i offset.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
95
OC
AX
BX
...
IP
BP
SI
...
ARG
+
SI
Rysunek 3.15: Adresowanie przez rejestr bazowy i indeksowy.
OC
OFFSET
AX
BX
...
IP
BP
SI
...
ARG
+
+
Rysunek 3.16: Adresowanie przez rejestr bazowy, indeksowy i offset.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
96
Architektura i działanie komputera
kłopoty dla początkujących adeptów programowania procesora na tak ni-
skim poziomie.
3.4.5
Asembler
Jak można było zauważyć we wcześniejszym punkcie, pisanie programów za
pomocą kodu maszynowego byłoby uciążliwe i monotonne. W konsekwencji
łatwo prowadzące do błędów
19
oraz właściwie uniemożliwiające ich zloka-
lizowanie. W celu ułatwienia procesu programowania procesora stworzono
język asembler. Język ten jest tzw. językiem mnemonicznym, gdyż
składa się z mnemoników: krótkich nazw odpowiadających konkretnym
rozkazom maszynowym konkretnego typu procesora
20
. Co więcej w języku
tym można stosować symboliczny zapis adresów, na przykład zamiast kon-
kretnego adresu zmiennej można zastosować jej nazwę. Uwalnia to progra-
mistę od żmudnego przeliczania adresów, które po za tym, że jest nużące,
może również powodować powstawanie błędów. Ponieważ w większości sy-
tuacji rozkazy są tłumaczone jeden-do-jednego, zatem proces zamiany pro-
gramu zapisanego w języku asembler na kod maszynowy sprowadza się nie-
jako do podstawienia pod dany mnemonik jego reprezentacji binarnej. Fakt
ten powoduje, że osoba programująca w asemblerze niejako pisze w kodzie
maszynowym, co jest jedną z głównych przyczyn dla których pisane w ten
sposób programy są najwydajniejsze pod względem prędkości działania jak
i zajmowanej przez nie ilości pamięci
21
. Niestety jak się za chwilę przeko-
namy pisanie w tym języku jest żmudne i z pewnością nie efektywne pod
względem prędkości tworzenia programów.
Poniżej przedstawiamy przykładowe rozkazy procesora Intel 8086, dla
ułatwienia zastały one pogrupowane według przeznaczenia. Przy większości
rozkazów występuje informacja o tym na jakie flagi w rejestrze flagowym ten
rozkaz może mieć wpływ. Dodatkowo podany jest czas realizacji danego
rozkazu w jednostkach cyklu zegarowego tzw. taktu. Przy czym podajemy
zakres czasu wykonania rozkazu, najkrócej będą realizowane rozkazy na
19
Chyba nikt nie wątpi, że pisząc sześć kolejnych bajtów metodą zero-jedynkową bardzo
łatwo coś przeoczyć czy też zamienić miejscami.
20
Bardzo ważne jest zrozumienie, że język ten jest ściśle związany właśnie z typem
procesorem, zatem dla innego procesora będzie inna lista rozkazów, być może podobna
i podobne funkcje realizująca ale inna. I tak Intel będzie miał inną listę rozkazów niż
Motorola, ale AMD będzie miało w pewnym podzbiorze zgodną z Intelem.
21
Oczywiście zakłada się w tym momencie, że osoba pisząca w tym języku doskonale
się nim posługuje, a przeciwnym razie można napisać program długi, nieczytelny i nieko-
niecznie szybki czy mały.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
97
rejestrach najdłużej zaś np. na komórkach pamięci adresowanych pośrednio
(patrz 3.4.4).
Rozkazy przesunięć
• MOV AX, BX — rozkaz przesłania zawartości rejestru BX do AX.
Flagi: brak. Czas: 2-14.
• PUSH SI — odłożenie na stos zawartości rejestru SI. Flagi: brak.
Czas: 14.
• POP DX — pobranie ze stosu wartości do rejestru DX. Flago:
brak. Czas: 12.
• XCHG AL, BL — wymiana wartości pomiędzy młodszymi bajtami
rejestrów AX i BX. Flagi: brak. Czas: 4-20.
• PUSHF — przesłanie zawartości rejestru znaczników na stos. Flagi,
które mogą ulec zmianie: Brak. Czas: 10.
• POPF — pobranie ze stosu wartości i zapisanie jej do rejestru
znaczników. Flagi: wszystkie. Czas: 8.
• IN AX, DX — pobranie wartości z portu o adresie danym w re-
jestrze DX do rejestru AX. Flagi: brak. Czas: 8-14.
• OUT DX, AX — wysłanie zawartości rejestru rejestru AX do portu
o adresie danym w rejestrze DX. Flagi: brak. Czas: 8-14.
Rozkazy arytmetyczne i logiczne
• ADD AX, BX — rozkaz dodania zawartości rejestru BX do AX,
wynik zostanie zapamiętany w AX. Flagi: AF, CF, OF, PF, SF,
ZF. Czas: 3-25.
• SUB AX, BX — rozkaz odjęcia zawartości rejestru BX od AX,
wynik zostanie zapamiętany w rejestrze AX. Flagi: AF, CF, OF,
PF, SF, ZF. Czas: 3-25.
• CMP AX, BX — rozkaz porównania zawartości rejestru BX i AX.
Flagi: AF, CF, OF, PF, SF, ZF. Czas: 3-14.
• INC AX — zwiększenie zawartości rejestru AX o 1. Flagi: AF,
OF, PF, SF, ZF. Czas: 2-23.
• DEC AX — zmniejszenie zawartości rejestru AX o 1. Flagi: AF,
OF, PF, SF, ZF. Czas: 2-23.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
98
Architektura i działanie komputera
• MUL BL — pomnożenie rejestru AX (zawsze) przez młodszy bajt
rejestru BX, wynik zostanie zapamiętany w AX i DX. W przy-
padku tego rozkazu liczby zapisane w rejestrach są traktowane
jako liczby bez znaku. Flagi: CF OF. Czas: 70-143.
• IMUL CL — pomnożenie rejestru AX (zawsze) przez młodszy bajt
rejestru CX, wynik zostanie zapamiętany w AX i DX. W przy-
padku tego rozkazu liczby zapisane w rejestrach są traktowane
jako liczby ze znakiem. Flagi: CF, OF. Czas: 80-164.
• DIV CL — dzielenie zawartości rejestru AX (zawsze) przez młod-
szy bajt rejestru CX. W przypadku tego rozkazu liczby trakto-
wane są jako liczby bez znaku. Flagi: brak. Czas: 80-320.
• IDIV CL — dzielenie zawsze zawartości rejestru AX przez młod-
szy bajt rejestru CX. W przypadku tego rozkazu liczby trakto-
wane są jako liczby ze znakiem. Flagi: brak. Czas: 101-194.
• NOT AX — negacja logiczna bitów rejestru AX. Flagi: brak. Czas:
3-24.
• XOR BX, CX — różnica symetryczna bitów w rejestrach BX i CX.
Flagi: CF, OF, PF, SF, ZF. Czas: 3-25.
• SHL AX, 1 — przesunięcie logiczne w lewo. Flagi: CF, OF, PF,
SF, ZF. Czas: 2-30.
• SAL AX, 1 — przesunięcie arytmetyczne w lewo. Flagi: CF, OF,
PF, SF, ZF. Czas: 2-30.
• ROL AX, 1 — przesunięcie cykliczne w lewo. Flagi: CF, OF.
Czas: 2-30.
• RCL AX, 1 — przesunięcie cykliczne z przeniesieniem w lewo.
Flagi: CF, OF. Czas: 2-30.
Rozkazy skoków
• JZ etykieta — rozkaz wykonania skoku warunkowego do ety-
kiety
22
, skok zostanie wykonany jeśli flaga ZF=1. Flagi, które
mogą ulec zmianie: brak. Czas: 16 — jeśli wystąpił skok, 4 —
w przeciwnym razie.
22
Poprzez etykietę rozumiemy pewne miejsce w programie, które posiada pewną nadaną
nazwę — zwaną etykietą.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.4 Procesor — serce komputera
99
• JMP etykieta — rozkaz wykonania skoku bezwarunkowego do
etykiety. Flagi: brak. Czas: 16.
Rozkazy przerwań
• INT — skok do podprogramu. Flagi: TF, IF. Czas: 52-72.
• IRET — powrót z podprogramu. Flagi: AF, CF, DF, IF, PF, SF,
TF, ZF. Czas: 32-44.
Rozkazy sterujące stanem procesora
• HLT — zatrzymanie procesora aż do wystąpienia przerwania.
Flagi: brak. Czas: 2.
• NOP — nic nie rób, pusty rozkaz. Flagi: brak. Czas: 3.
Omówimy teraz klika elementarnych przykładów programów w asemble-
rze, celem lepszego zrozumienia sposobu programowania procesora.
Spójrzmy na przykład 3.3, program ten (a dokładniej fragment pro-
gramu) wczytuje do rejestrów AX i BX odpowiednio wartości zmiennych
oraz wykonuje dodawanie. Wynik zostaje zapamiętany w zmiennej SUMA.
Następnie to samo wykonywane jest dla różnicy.
Przykład 3.3. Fragment programu w asemblerze
MOV AX, ZMIENNA1
MOV BX, ZMIENNA2
ADD AX, BX
MOV SUMA. AX
MOV AX, ZMIENNA1
SUB AX, BX
MOV ROZNICA, AX
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
100
Architektura i działanie komputera
3.5
Reprezentacja informacji
Ponieważ obecne komputery są konstruowane w oparciu o cyfrowe układy
scalone realizujące operacje dwuelementowej algebry Boole’a (zob. 2.1),
zatem wszelka informacja zapamiętywana w komputerze i przez niego prze-
twarzana ma reprezentację zero–jedynkową. Zatem chcąc przedstawić w
komputerze w jakiś sposób zwykłe znaki typu „A”, „3”, „+” itp. należy
przyjąć pewną umowę co do ich oznaczania za pomocą ciągów bitów.
Mówiąc o informacji należy pamiętać, że mówimy o wszelkich danych
przetwarzanych za pomocą komputera. Dane wprowadzane za pomocą kla-
wiatury, czyli znaki alfabetu, cyfry i znaki takie jak „!”, „?”, itd. nazywane
są znakami alfanumerycznymi. Obliczenia w komputerze prowadzone
są już na liczbach, które powstają na skutek konwersji pomiędzy zapisem
„słownym” a jego reprezentacją numeryczną. By lepiej uzmysłowić pro-
blem, spróbujmy zapytać co znaczy napis „12”? Odpowiedzią będzie, że
jest to liczba o wartości 12, ale skąd to wiemy? Przecież jeśli napiszemy
„XII”, to również jest to liczba o wartości 12, choć zapis wygląda inaczej.
Podobnie jak w przypadku nauki słów języka naturalnego, uczymy się odczy-
tywać liczby i zmieniać napisy je reprezentujące na ich wartość numeryczną.
Taki sam proces musi zachodzić w komputerze, aby dodać dwie liczby na-
leży znać ich wartość, aby ją znać musi istnieć procedura zamiany napisu
reprezentującego liczbę na jej wartość numeryczną. Takie procedury są czę-
ścią oprogramowania podstawowego w każdym komputerze. Niezależnie od
tego jak taki proces przebiega, musi istnieć sposób reprezentacji znaków
alfanumerycznych (3.5.1), liczb naturalnych (3.5.2), całkowitych (3.5.3) i
rzeczywistych (3.5.5) w komputerze.
3.5.1
Znaki alfanumeryczne
Litery, cyfry i pozostałe znaki alfabetu łacińskiego są zapisywane w kom-
puterze, podobnie jak wszelka informacja, za pomocą ciągów zer i jedynek,
a zbiór tych znaków nosi miano znaków alfanumerycznych. Proces za-
miany znaku wpisanego z klawiatury, lub innego urządzenia wczytującego,
na jego reprezentację cyfrową nazwiemy kodowaniem. Jednym z najczę-
ściej stosowanych standardów kodowania informacji w komputerze jest kod
ASCII (ang. American Standard Code for Information Interchange — zob.
dodatek D), w którym zdefiniowano kody 128 znaków stanowiących podsta-
wowy zbiór znaków stosowanych w informatyce (zob. dodatek B). Tych 128
znaków odpowiada literom i cyfrom alfabetu łacińskiego oraz dodatkowo
pewnym znakom sterującym. Dodatkowo zostało opisane w tym standar-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
101
ą
ć
ę
ł
ń
ó
ś
ź
ż
B1 E6 EA B3
F1
F3
B6 BC BF
Ą
Ć
Ę
Ł
Ń
Ó
Ś
Ź
Ż
A1 C6 CA A3 D1 D3 A6 AC AF
Tablica 3.1: Kodowanie polskich znaków według standardu ISO 8859-2 (he-
xadecymalnie).
dzie następne 128 znaków, które w głównej mierze składają się ze znaków
semigraficznych, służących do tworzenie tabel czy ramek, oraz dodatkowo
ze znaków narodowych. Oczywiście zestaw tych znaków będzie zależał
od kraju, czyli języka narodowego, ale również od producenta sprzętu kom-
puterowego.
Manipulując tekstem z wykorzystaniem kodu ASCII zawsze musimy wie-
dzieć przy użyciu jakiej strony kodowej został on napisany. Strony ko-
dowe to wersje kodu ASCII różniące się interpretacją symboli o numerach
od 128 do 255. Na przykład dla języka polskiego stworzono stronę kodową
ISO 8859-2 nazywaną popularnie ISO Latin-2, gdzie poszczególnym lite-
rom charakterystycznym dla naszego języka przypisano następujące warto-
ści liczbowe (tabela 3.5.1). Niestety oprócz powyższego standardu powstało
także wiele innych; łączne zestawienie częściej spotykanych zawiera dodatek
C.
Problem ten stanie się jeszcze bardziej wyraźny jeśli operujemy na tek-
stach wielojęzycznych. Ponadto udostępniana przestrzeń 128 znaków, które
możemy dowolnie zdefiniować dla wielu celów jest niewystarczająca (język
chiński, symbole matematyczne). Problem ten często był rozwiązywany po-
przez wprowadzanie specjalnych znaków sterujących zmieniających sposób
interpretacji kodów po nich następujących; na przykład
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
102
Architektura i działanie komputera
W celu ujednolicenia sposobu interpretacji kodów liczbowych jako zna-
ków, oraz zapewnienia możliwości reprezentowania za ich pomocą zarówno
tekstów pochodzących z przeróżnych zakątków świata jak i pewnych dodat-
kowych symboli zaproponowano nowy sposób kodowania znaków znany pod
nazwą Unicode.
Oto zasadnicze cele dla których Unicode został stworzony oraz jego pod-
stawowe właściwości:
Jednoznaczność Każdemu znakowi zakodowanemu za pomocą Unicode
odpowiada zawsze ta sama wartość liczbowa i odwrotnie.
Uniwersalność „Repertuar” dostępnych znaków obejmuje wszystkie po-
wszechnie używane języki oraz symbole.
16-bitowa reprezentacja Każdy znak reprezentowany jest w postaci 16-
bitowej liczby. Pozwala to na reprezentację ponad 65 tysięcy znaków
(w 1996, gdy obowiązywał Unicode Standard 2.0 pozostawało jeszcze
ponad 18 tysięcy wolnych miejsc). Ponadto można zdefiniować około
miliona dodatkowych znaków poprzez zastępczy mechanizm rozsze-
rzeń (ang. surrogate extension mechanism), który bez żadnych pro-
blemów może być równolegle wykorzystywany z podstawową wersją.
Efektywność Stosowanie Unicode ułatwia znacznie manipulowanie tek-
stami, gdyż identyfikacja znaku nie zależy od sekwencji sterujących
czy znaków następujących bądź poprzedzających.
Identyfikacja nie reprezentacja Standard ten określa jakie kody odpo-
wiadają jakim znakom. Nie definiuje natomiast jak znaki te mają
wyglądać, proszę spojrzeć na poniższy przykład
Identyfikacja
Wygląd
kod=litera_a
a a a a a
Znaczenie W celu umożliwienia wykorzystania algorytmów operujących
na tekstach (na przykład sortowanie) zdefiniowano tablicę własności
znaków. Własności tych nie określa na ogół ani nazwa znaku ani jego
położenie w tabeli kodów.
Czysty tekst Unicode odpowiada za kodowanie czystego tekstu (ang. plain
text) bez żadnych dodatkowych informacji typu język w jakim tekst
napisano, rodzaj czcionki czy jej wielkość.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
103
Logiczny porządek Kodowany tekst przechowywany jest w porządku lo-
gicznym, to znaczy w porządku w jakim są pisane znaki a nie w ich
faktycznej kolejności w jakiej występują w dokumencie. Rozróżnie-
nie to istotne jest w przypadku języków, w których tekst piszemy od
prawej do lewej, co ilustruje poniższy przykład
Ujednolicenie Wszystkie powtarzające się znaki zastąpione zostały jed-
nym znakiem. Nie wprowadza się sztucznych podziałów — w pew-
nych językach ten sam znak ma inną nazwę lub funkcję (na przykład
","
jest separatorem tysięcy w liczbie dla języka angielskiego zaś dzie-
siątek dla francuskiego). Wciąż jest to jednak ten sam znak, zatem
zwykle wszystkie one zostają zastąpione jednym. „Zwykle”, gdyż nie-
które znaki pomimo to pozostawiono, chcąc zapewnić kompatybilność
z pewnymi już istniejącymi standardami.
3.5.2
Liczby naturalne
Liczba naturalna zapisana za pomocą zer i jedynek, będzie ciągiem bitów
powstałym w wyniku zamiany zapisu dziesiętnego na dwójkowy (zob 2.2.1).
Wówczas, dysponując n bitami, możemy przedstawić wszystkie liczby z prze-
działu [0, 2
n
− 1]. Jeśli założymy, że n = 8 wówczas możemy przedstawić
256 różnych liczb naturalnych z przedziału [0, 255], na przykład:
00000000
2
= 0
10
00000001
2
= 1
10
00011000
2
= 24
10
10000000
2
= 128
10
11111111
2
= 255
10
3.5.3
Liczby całkowite
W przypadku liczb całkowitych nasuwa się podobny wniosek jak dla liczb
naturalnych, by reprezentować je po prostu za pomocą zapisu dwójkowego
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
104
Architektura i działanie komputera
tej liczby. Co jednak począć ze znakiem? Musimy jakoś odróżnić liczby
całkowite ujemne od całkowitych dodatnich.
Rozważmy jeden z możliwych sposobów: przeznaczony zostanie jedne
bitu (np. najstarszego) na znak. Ten sposób zapisu liczby ujemnej zwany
jest reprezentacją znak–moduł. Przyjmijmy teraz, że 0 na najstarszym
bicie oznacza, iż pozostałe bity reprezentują liczbę dodatnią, zaś ujemną,
gdy bit ten jest równy 1. Stosując taką konwencję, na n bitach będziemy
mogli zapisać 2
n
liczb z przedziału [−2
n−1
+ 1, 2
n−1
− 1].
Jeśli założymy na przykład, że n = 8, wówczas możemy zapisać 256
różnych liczb, z przedziału [−127, 127], przy czym zero może być reprezen-
towane na dwa sposoby:
+0
10
= 00000000
2
−0
10
= 10000000
2
Rozważmy następujące działania, by upewnić się, że zapis ten spełnia
nasze oczekiwania. W tym celu weźmy następujące liczby i ich reprezentację
zero–jedynkową
+57
10
= 00111001
2
−13
10
= 10001101
2
przy czym, zgodnie z wcześniejszą umową, pierwszy bit od lewej jest bitem
znaku.
Działanie 57−13 możemy rozważać jako (+57)−(+13), albo jako (+57)+
(−13). Rozważmy przykład:
00111001
( =
+ 57 )
+ 10001101
( =
- 13 )
----------
11000110
( =
- 69 )
Otrzymaliśmy −69!!!, co z pewnością nie jest poprawnym wynikiem.
Jak widać z powyższego przykładu, taka reprezentacja nie prowadzi do
prawidłowych wyników przy „klasycznej” technice dodawania. A zatem w
przypadku dodawania liczb o znakach przeciwnych należy to uwzględniać
i zamiast dodawać, należy odjąć bity reprezentujące wartość a dopiero na
koniec przeprowadzić analizę znaku wyniku. Rozważmy zatem przykład
0 0111001
( =
+ 57 )
+ 1 0001101
( =
- 13 )
-----------
0 0101100
( =
+ 44 )
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
105
Tym razem otrzymaliśmy poprawny wynik, ale niestety kosztem do-
datkowych operacji związanych z ustalaniem znaku. W szczególności, gdy
w wyniku odejmowania otrzymamy, jak w powyższej sytuacji, wynik do-
datni, to znak należy ustawić na dodatni. Te dodatkowe operacje nie są
naturalne z punktu widzenia algebry Boole’a, a co więcej zajmują niepo-
trzebnie czas procesora.
Jak więc widać z powyższych rozważań, operowanie na liczbach ze zna-
kiem wcale nie jest takie oczywiste jak byśmy sobie tego życzyli. Wymaga,
oprócz samego wykonania działania, szeregu czynności, które mają na celu
ustalenia poprawnego znaku wyniku. Aby ominąć te niedogodności wpro-
wadzono reprezentację uzupełnień do dwu.
3.5.4
Reprezentacja uzupełnień do dwu
Reprezentację uzupełnień do dwu opracowano w celu wyeliminowania pro-
blemów jakie występowały w przypadku stosowania reprezentacji znak-mo-
duł. Podobnie jak w poprzedniej reprezentacji, najbardziej znaczący bit
informuje o znaku liczby. Jednak inaczej interpretuje się pozostałe bity.
Zanim jednak zdefiniujemy precyzyjnie nowy sposób zapisu przyjrzyjmy
się poniższemu przykładowi
00001110 ( + 14 )
+ 1xxxxxxx ( - 14 )
----------
00000000 (
0 )
Mamy w powyższym przykładzie pewne działanie w którym chcemy dokonać
sumowania liczby 14 zapisanej w postaci binarnej i liczby −14. W wyniku
tego dodawanie chcemy otrzymać 0, przy czym wszystkie te liczby mają być
zapisane zero–jedynkowo. Inaczej mówiąc chciałbym dodać 14 + (−14) tak
by otrzymać 0, wykonując naturalne dodawanie w systemie dwójkowym,
bez zastanawiania się czy coś jest znakiem czy nie. W powyższym przykła-
dzie łatwo wywnioskować jaką postać powinien mieć drugi składnik sumy,
zapiszmy ponownie to działanie
00001110
+ 11110010
----------
00000000
Widzimy teraz, że po dodadniu otrzymamy faktycznie 0. Z wyjątkiem faktu,
że będziemy mieli przeniesioną 1 na 9−ty bit, ale nie stanowi to problemu,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
106
Architektura i działanie komputera
gdyż prowadzimy obliczenia (w tym przypadku) na 8−miu bitach. Drugi
składnik sumy jest uzupełnieniem dwójkowym liczby 14 zapisanej na
8−miu bitach. Po tym wprowadzeniu możemy wprowadzić pojęcie uzupeł-
nienia dwójkowego.
Uzupełnieniem dwójkowym liczby x zapisanej za pomocą n bitów
nazywamy liczbę x
u
2
= 2
n
− x.
Rozważmy następujące przykłady
• Niech x = 0101. Uzupełnieniem dwójkowym jest x
u
2
= 2
4
− 0101 =
10000 − 0101 = 1011.
• Niech y = 1011. Uzupełnieniem dwójkowym jest y
u
2
= 2
4
− 1011 =
0101.
Otrzymaliśmy zatem, że y
u
2
= x. Ponieważ jednak y = x
u
2
, więc osta-
tecznie możemy zapisać, że (x
u
2
)
u
2
= x. Obserwacja ta, potwierdzona ana-
litycznie, nasuwa wniosek, że uzupełnienie dwójkowe danej liczby reprezen-
tuje liczbę do niej przeciwną.
Wprawdzie ten sposób zapisu jest dla człowieka dość kłopotliwy, stosuje
się go jednak powszechnie, gdyż ułatwia on implementację podstawowych
operacji arytmetycznych. Kłopoty pojawiają się wyłącznie przy dokonywa-
niu konwersji z systemu dziesiętnego na uzupełnień do dwu i odwrotnie.
Jednak konwersję tę wykonuje się wyłącznie przy wprowadzaniu danych lub
ich wyprowadzaniu, pomiędzy tymi operacjami dane pozostają w kodzie
uzupełnień do dwu, co nikomu nie przeszkadza. Ponieważ operacji konwer-
sji jest dużo mniej niż działań na nich, więc opłaca się je wykonywać zamiast
stosować reprezentację znak-moduł i wykonywać dodatkowe operacje przy
każdym działaniu.
Konwersja pomiędzy systemem dziesiętnym a systemem uzupeł-
nień do dwu
Do konwersji liczb pomiędzy zapisem uzupełnień do dwu a reprezentacją
dziesiętną można stosować tablicę wartości (tab. 3.2). Ale ten sposób jest
żmudny i niewygodny dla komputera. Stąd w praktyce wykorzystuje się
jeden z dwu poniższych algorytmów. Pierwszy z nich sprowadza się do
operacji dopełnienia i sumy, drugi korzysta wprost z definicji dopełnienia i
wymaga odejmowania.
Algorytm 1
1. Weźmy dowolną liczbę ujemną x daną w zapisie dziesiętnym.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
107
Tablica 3.2: Tabela zawierająca porównanie reprezentacji znak-moduł i uzu-
pełnień do dwu.
Reprezentacja Reprezentacja
Reprezentacja
dziesiętna
znak-moduł
uzupełnienia do dwu
+7
0111
0111
+6
0110
0110
+5
0101
0101
+4
0100
0100
+3
0011
0011
+2
0010
0010
+1
0001
0001
+0
0000
0000
-0
1000
—
-1
1001
1111
-2
1010
1110
-3
1011
1101
-4
1100
1100
-5
1101
1011
-6
1110
1010
-7
1111
1001
-8
—
1000
2. Wykonujemy konwersję modułu liczby x na zapis dwójkowy, przy
czym musi być w tym momencie ustalone na ilu bitach będziemy re-
prezentowali tę liczbę.
3. Bierzemy uzupełnienie Boole’a każdego bitu liczby (łącznie z bitem
znaku).
4. Traktując wynik poprzedniego kroku, jako liczbę całkowitą pozba-
wioną znaku, dodajemy 1.
5. Wynik jest zapisem w kodzie uzupełnień do dwu liczby x.
Algorytm 2
1. Weźmy dowolną liczbę ujemną x daną w zapisie dziesiętnym.
2. Wykonujemy konwersję modułu liczby x na zapis dwójkowy, przy
czym musi być w tym momencie ustalone na ilu bitach będziemy re-
prezentowali tę liczbę.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
108
Architektura i działanie komputera
3. Uzyskana reprezentacja liczby x jest pewnej długości, oznaczmy ilość
jej bitów przez k.
4. Zapiszmy w systemie dwójkowym liczbę 2
k
.
5. Odejmijmy od tak zapisanej liczby liczbę x w systemie dwójkowym.
6. Wynik jest zapisem w kodzie uzupełnień do dwu liczby x.
Przykład 3.4. Ilustracja algorytmu 1 zamiany liczby dziesiętnej na
kod uzupełnień do dwu.
1) Weźmy liczbę -14
2) Moduł liczby w kodzie dwójkowym na 8 bitach => 00001110
3) Uzupełnienie Boole’a 00001110 => 11110001
4) Wykonujemy dodawanie
11110001
+ 00000001
----------
11110010 <= Liczba -14 w kodzie uzupełnień do dwu
Przykład 3.5. Ilustracja algorytmu 2 zamiany liczby dziesiętnej na
kod uzupełnień do dwu.
1) Weźmy liczbę -14
2) Moduł liczby w kodzie dwójkowy na 8 bitach => 00001110
3,4) 8-ta potęga 2 => 100000000
5) Wykonujemy odejmowanie
100000000
- 00001110
----------
11110010 <= Liczba -14 w kodzie uzupełnień do dwu
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
109
3.5.5
Liczby rzeczywiste
Stosując przedstawianą w poprzednich punktach notacje możliwe jest repre-
zentowanie dodatnich i ujemnych liczb całkowitych z określonego przedziału.
Ponadto, jeśli umówimy się, że pewna grupa bitów oznacza część całkowitą
pozostałe zaś część ułamkową, możliwe stanie się reprezentowanie liczb ze
składnikiem ułamkowym. Nie jest to jednak rozwiązanie optymalne, gdyż
z góry narzuca nam ilość bitów przeznaczonych na zapis części całkowitej
i ułamkowej. W takiej sytuacji z jednaj strony dochodziłoby do „marnowa-
nia miejsca” przeznaczonego na zapis liczby (tak będzie gdy przykładowo
liczba będzie całkowita, wtedy część ułamkowa w ogóle nie będzie wykorzy-
stywana). Z drugiej zaś strony, i jest to argument dużo ważniejszy, takie
rozwiązanie narzuca arbitralnie precyzję zapisu takiej liczby. Rozwiązanie
takie, zwane zapisem stałoprzecinkowym, jest czasami wykorzystywane
gdy obliczenia prowadzone są zawsze z pewną dokładnością, czego przykła-
dem mogą być kalkulacje walutowe.
Rozważmy następujący przykład. Załóżmy, że dysponujemy 8 bitami na
zapis liczby. Daje nam to 256 różnych wartości. Jeśli ustalimy, że pierwsze 4
bity od lewej to część całkowita, a pozostałe to ułamkowa, wówczas możliwa
stanie się reprezentacja liczb z przedziału [0.0, 15.9375] przy czym najmniej-
sza odległość pomiędzy kolejnymi liczbami (tzw. granulacja), to 1/16 czyli
0.0625. Chcąc teraz zwiększyć zakres reprezentowanych liczb, możemy na
część całkowitą przeznaczyć 6 bitów. Możliwa stanie się wówczas reprezen-
tacja liczb z przedziału [0.0, 63.75] z dokładnością 1/4 czyli 0.25. Zwykle po-
trzeba by zarówno zakres reprezentowanych liczb jak i ich dokładność były
odpowiednio duże, co wiązałoby się z przeznaczeniem odpowiedniej ilości
bitów na obie części. Co jednak w przypadku, gdyby operacje były doko-
nywane tylko na liczbach bardzo małych (albo bardzo dużych)? Wówczas
część odpowiedzialna za reprezentacje części całkowitej (lub ułamkowej) nie
byłaby w ogóle wykorzystywana.
Sposobem obejścia tych ograniczeń jest zastosowanie modyfikacji po-
wszechnie przyjętej notacji naukowej do zapisu liczb binarnych. W dziesięt-
nej notacji naukowej liczbę bardzo dużą, np. 456000000000000 można zapi-
sać jako 4.56 × 10
14
, a bardzo małą 0.0000000000000456 jako 4.56 × 10
−14
.
W ten sposób, stosując dynamiczne przesunięcie przecinka oraz używając
potęgi liczby 10 do określenia jego rzeczywistego położenia, możemy repre-
zentować dowolne liczby za pomocą tylko kilku cyfr.
Takie samo podejście można zastosować do liczb binarnych. Zauważmy,
że można zapisać ogólny wzór dla reprezentacji naukowej w dowolnym po-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
110
Architektura i działanie komputera
zycyjnym systemie liczbowym w postaci:
z
m
M × B
z
c
C
,
gdzie: M — mantysa, C — wykładnik (cecha), B — używane podstawa, z
m
— znak mantysy, z
c
— znak cechy.
Zatem przechodząc do systemu dwójkowego, mamy:
z
m
M × 2
z
c
C
,
przy czym zarówno mantysa jak i cecha zakodowane są binarnie. Przyj-
mując taki zapis i mając każdym ciągu bitów o określonej długości, który
reprezentuje liczbę w oparciu o powyższą notację, należy wyróżnić cztery
grupy bitów. Grupa pierwsza reprezentuje znak takiej liczby (wystarczy
jeden bit), druga mantysę, trzecia znak cechy (znów jeden bit), i ostatnia
cechę
23
. Mantysa będzie zawierać informację o cyfrach znaczących liczby,
zaś cecha będzie informowała na ile duża bądź też na ile mała jest ta liczba.
Zauważmy również, że podstawa B nie musi być przechowywana, gdyż jest
z góry ustalona (w rozważanym przypadku wynosi 2). Można też zauważyć,
że nie trzeba pamiętać znaku cechy jeśli przyjmie się następującą notację
z
m
M × 2
C−K
C
,
gdzie K
C
jest stałą zależną od konkretnej implementacji. W tej sytuacji
ujemny wykładnik wystąpi gdy wartość cechy będzie mniejsza od zadanej
stałej. Innym podejściem jest zapamiętanie cechy w postaci liczby w syste-
mie uzupełnień do dwu, wtedy w sposób naturalny omijamy problem znaku.
Niemniej jednak pozostaje jeszcze pewien problem jak optymalnie za-
pamiętać mantysę. Zauważmy, iż liczbę rzeczywistą można przedstawić na
wiele równoważnych sposobów stosując omawiany tok rozumowania, a mia-
nowicie:
4.56 × 10
−14
= 456 × 10
−16
= 0.456 × 10
−13
W celu uniknięcia pewnych problemów numerycznych oraz celem ułatwienia
obliczeń wymaga się aby liczby te były w jakiś sposób znormalizowane. To
znaczy przyjmuje się, że wartość mantysy ma spełniać pewną nierówność,
która dla liczb w systemie dziesiętnym miała by postać:
1.0 ≤ M < 10.0
23
Zauważmy, że to jest tylko pewna propozycja, tak naprawdę nie ma znaczenia kolej-
ność występowania poszczególnych grup.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.5 Reprezentacja informacji
111
zaś dla liczb w systemie dwójkowym, następującą nierówność (zapisaną dzie-
siętnie):
1.0 ≤ M < 2.0
Można spytać czemu właśnie taką nie równość a nie inną? Odpowiedź na
to pytanie jest prosta, jeśli przeliczymy lewą nierówność na zapis dwójkowy,
wtedy otrzymamy:
1.0 ≤ M
Z powyższego wynika, że lewy bit mantysy jest zawsze równy 1, zatem nie
ma potrzeby go przechowywać — wystarczy pamiętać tylko te bity mantysy,
które występują po kropce, czyli
1.b
n
. . . b
0
gdzie b
i
, (i = 0, . . . , n) są cyframi systemu binarnego.
W celu lepszego zrozumienia dotychczasowych rozważań przyjrzyjmy
się następującemu przykładowi. Załóżmy, że dysponujemy 8 bitami. Niech
pierwszy bit od lewej oznacza znak, kolejne 3 mantysę zaś ostatnie 4 bity
będą cechą. Jako wartość stałej K
C
przyjmijmy 7. Najmniejsza liczba do-
datnia jaką możemy w ten sposób reprezentować to +1.0 × 2
−7
zapisane
jako 00000000 czyli 0.0078125, największa zaś to +1.875 × 2
8
zapisana jako
01111111 czyli 480. Chcąc uzyskać podobne rezultaty stosując wcześniejszy
sposób zapisu liczb (stałopozycyjny), otrzymano by, że część ułamkowa mu-
siałaby mieć 7 bitów (0.0000001
2
= 2
−7
= 0.0078125
10
), zaś część całkowita
bitów 9 (wprawdzie na 9 bitach można zapisać liczbę o wartości większej
od 480, gdyż 111111111.0
2
= 511
10
, jednak 8 bitów to za mało, bowiem
11111111.0
2
= 255
10
). Dodając do tego wszystkiego bit znaku otrzymaliby-
śmy łącznie 17 bitów.
Przy tak przyjętej reprezentacji możliwe jest przedstawienie liczb z na-
stępujących zakresów:
– liczby ujemne między −480.0 a −0.0078125
11111111 = −1.111 × 2
8
= −1.875 × 256 = −480
10000000 = −1.000 × 2
−7
= −1.0 × 0.0078125 = −0.0078125
– liczby dodatnie między 0.0078125 a 480
Zakresy te nie obejmują pięciu obszarów:
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
112
Architektura i działanie komputera
– liczby ujemne mniejsze niż −480, określane jako przepełnienie uje-
mne;
– liczby ujemne większe niż −0.0078125, określane jako niedomiar uje-
mny;
– zero;
– liczby dodatnie mniejsze niż 0.0078125, określane jako niedomiar do-
datni;
– liczby dodatnie większe niż 480, określane jako przepełnienie do-
datnie;
Należy zatem zwrócić uwagę na następujące fakty. W tak przyjętym
formacie nie da się przedstawić zera (gdy stosowana była notacja uzupeł-
nieniowa do dwóch, możliwe było reprezentowanie wszystkich liczb całkowi-
tych od −2
n
do 2
n
− 1, gdzie n było liczbą bitów przeznaczonych na zapis
liczby). W praktyce stosuje się specjalny wzór bitowy do oznaczenia zera.
Należy jasno zdawać sobie sprawę, że za pomocą notacji zmiennopozy-
cyjnej nie reprezentuje się większej liczby pojedynczych wartości. Maksy-
malna liczba różnych wartości, które mogą być przedstawione za pomocą 8
bitów nadal wynosi 2
8
. Ponadto stosowanie takiej reprezentacji powoduje,
że liczby nie są równomiernie rozmieszczone na osi liczbowej, jak miało to
miejsce w przypadku liczb stałopozycyjnych. Możliwe wartości są rozłożone
gęściej na początku osi, a rzadziej w miarę oddalania się od początku.
W przypadku tak ustalonego formatu następuje wymienność między za-
kresem a dokładnością. Jeśli zwiększymy liczbę bitów wykładnika, to posze-
rzymy w ten sposób zakres liczb możliwych do wyrażenia. Ponieważ jednak
tylko ustalona liczba różnych wartości może być wyrażona, zredukujemy
w ten sposób gęstość tych liczb i tym samym dokładność.
We współczesnych komputerach przyjęto właśnie taki sposób przedsta-
wiania liczb rzeczywistych. Dokładne informacje na temat ilości bitów i ich
interpretacji, oraz wszelkie dodatkowe ustalenia zebrane zostały w Normie
IEEE 754
24
.
Epsilon maszynowy
Precyzją p zmiennopozycyjnego systemu liczbowego nazywać będziemy liczbę
bitów użytych do zapisu mantysy (wliczając w to pierwszy bit o stałej war-
tości). W naszych dotychczasowych rozważaniach p = 4 (3 bity na zapis
24
Dokładnie nazwa brzmi: IEEE Standard 754 for Binary Floating-Point Arithmetics
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.6 Zadania
113
mantysy + 1 bit domyślny o stałej wartości 1). Stąd każda liczba rzeczywi-
sta x zapisana z precyzją p może być wyrażona jako
x = z
m
(1.b
p−2
. . . b
1
b
0
)
2
= 1 + 2
C−K
C
(3.1)
Najmniejszą taką liczbę x, większą od 1.0 jest
x = (1. 0 . . . 0
| {z }
p−2
1)
2
= 1 + 2
−(p−1)
Różnica pomiędzy tą liczbą a 1.0 nazywana jest epsilonem maszynowym
25
.
Podajemy tutaj definicję za [Ove01], zgodnie z tym co napisano, wynosi on
ε = (0. 0 . . . 0
| {z }
p−2
1)
2
= 1 + 2
−(p−1)
Dla dowolnej liczby x przedstawionej w postaci (3.1) definiuje się
ulp(x) = 0. 0 . . . 0
| {z }
p−2
1
2
× 2
C−K
C
= 2
−(p−1)
× 2
C−K
C
= ε × 2
C−K
C
Jeśli x > 0 (x < 0) wówczas ulp (ang. Unit In The Last Place) informuje o
odległości od następnej, tj. większej (poprzedniej, tj. mniejszej) (reprezen-
towanej w przyjętym systemie) liczby.
3.6
Zadania
1. Stosując dwójkową reprezentację znak-moduł zapisz następujące liczby
całkowite (zakładamy, że liczba dwójkowa powinna zajmować wielo-
krotność 8 bitów).
a)
-20 b)
+20
c)
+47 d) -18 e) +37
f) -128 g) +372 h) -420
i)
-42
j)
-15
2. Stosując dwójkową reprezentację uzupełnień do dwu zapisz następu-
jące liczby całkowite (zakładamy, że liczba dwójkowa powinna zajmo-
wać wielokrotność 8 bitów).
a) -20 b) +87 c) +65 d) -18 e)
+27
f) -99 g) -300 h) +77
i)
-77
j)
+503
25
Czasem epsilon maszynowy definiowany jest jako połowa tej różnicy
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
114
Architektura i działanie komputera
3. Przedstaw poniższe dziesiętne liczby rzeczywiste jako rzeczywiste liczby
dwójkowe.
a)
0.5625 b)
7.4375 c) 11.0625 d)
4.6875
e)
2.8125
f)
13.875
g)
9.625
h) 14.75
i)
15.375
j)
5.0625 k)
3.3125
l)
8.1875
4. Przedstaw poniższe dwójkowe liczby rzeczywiste jako rzeczywiste liczby
dziesiętne.
a) 1111.01
b) 1011.101
c) 1000.111
d)
1.1011
e)
0.1111
f)
1100.0001 g)
100.0111 h) 1001.001
i)
101.1101
j)
10.1001 k) 1101.011
l)
1010.1
5. Załóżmy, że operujemy następującym zmiennopozycyjnym formatem
zapisu liczby rzeczywistej: na zapis przeznaczamy 8 bitów, najstarszy
bit, to bit znaku, kolejne 3 to mantysa, ostatnie 4 to cecha. Wartość
stałej K
C
przyjmujemy równą 7. Jakie liczby rzeczywiste reprezentują
poniższe ciągi:
a) 01000000 b) 10100101
c) 00010010 d) 10101001
e) 00000100
f)
10100010 g) 01111101 h) 10001110
i)
00101011
j)
10011111 k) 01010110
l)
10000011
6. Dane są tabelki przejść oraz początkowy stan taśmy dla następują-
cych trzech Maszyn Turinga, napisz tabelę ruchów dla każdej z nich.
(Prostokąt oznacza początkową pozycję głowicy)
a) Tabela przejść
Stan
Odczytany Symbol do
Kierunek
Stan
bieżący
symbol
zapisu
ruchu głowicy kolejny
s
a
b
→
s
s
b
a
→
s
s
t
a
→
s
s
.
.
−
k
Początkowy stan taśmy
b
a
b
a
t b a a b b .
b) Tabela przejść
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
3.6 Zadania
115
Stan
Odczytany Symbol do
Kierunek
Stan
bieżący
symbol
zapisu
ruchu głowicy kolejny
s
a
a
→
s
s
b
b
→
s
s
t
t
→
1
s
.
.
−
k
1
a
a
→
1
1
b
a
→
1
1
t
t
→
s
1
.
.
−
k
Początkowy stan taśmy
b
b
a
t a a b b t a .
c) Tabela przejść
Stan
Odczytany Symbol do
Kierunek
Stan
bieżący
symbol
zapisu
ruchu głowicy kolejny
s
a
a
→
s
s
b
b
→
s
s
t
a
←
1
s
.
.
−
k
1
a
a
→
1
1
b
a
→
1
1
t
a
←
2
1
.
.
−
k
2
a
b
→
2
2
b
b
→
2
2
t
b
←
1
2
.
.
−
k
Początkowy stan taśmy
a
a
b
t a b t b .
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
116
Architektura i działanie komputera
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 4
Teoria informacji
Wiadomości są symbolami informacji, których znaczenie musi być
wyuczone.
Mehlis
4.1
Informacja vs. wiadomość
Mówimy dziś: informacja rządzi Światem. Gdy jednak zapytamy czym
jest informacja z trudem z lawiny odpowiedzi wyłowimy jakąś sensowną
i przekonywującą. Informacja nie jest bowiem czymś co można zobaczyć
lub dotknąć. Niestety informacja jest czymś zasadniczym w informatyce,
czymś niezastampialnym, gdyż cała informatyka zasadza swoje istnienie na
przetwarzaniu informacji. Zatem brak informacji oznacza w konsekwencji
brak informatyki. Drugim pojęciem silnie związanym z informatyką i infor-
macją jest wiadomość. Niestety ani informacji ani wiadomości nie można
precyzyjne zdefiniować
1
. Dlatego też przyjmuje się, że oba te pojęcia są
niedefiniowalne i rozumienie ich sprowadza się do intuicji. Podobnie my
spróbujemy te pojęcia wyjaśnić.
Zastanówmy się nad poniższymi dwoma wypowiedziami:
Jest trzynasta. Godzinę temu była dwunasta.
Jest trzynasta. Godzinę temu był ostatni w tym dniu samolot do
Polski.
Zauważmy, że obie wypowiedzi składają się z dwóch zdań. O ile w pierw-
szym przypadku wyraźnie widać, że każde ze zdań przekazuje tą samą wia-
1
Głównie dlatego, że próba ich definicji sprowadza się do używania wcześniej nie zde-
finiowanych pojęć, itd.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
118
Teoria informacji
domość (więc jedno z nich jest zbędne) o tyle w drugim usunięcie jednego
z nich pozbawia nas części. . . no właśnie — informacji. Co więcej dla tej
samej informacji mogą istnieć różne wiadomości, które ją niosą, dla przy-
kładu dwie poniższe wypowiedzi niosą tę samą informację:
Nazywam się Bond.
My name is Bond.
Dalej prowadząc te rozważania można zauważyć, że ta sama wypowiedź
może mieć różną wartość w zależności od tego kto lub gdzie ją wypowiada
2
.
Rozważmy kolejny przykład, wypowiedź: „Pada śnieg”, co innego będzie
znaczyć (będzie mieć inną wartość), gdy padnie z ust mieszkańca stacji
badawczej gdzieś na Antarktydzie, a co innego jeśli wypowie ją członek ka-
rawany idącej przez Saharę. Dlaczego tak się dzieje? Tu niestety musimy
odwołać się do intuicji, która podpowiada nam, że wiadomość jest rodza-
jem nośnika (sposobem jej zapisu) informacji, informacja jest zaś treścią
wiadomości. Wiele osób próbowało odpowiedzieć bardziej formalnie na po-
stawione pytanie, poniżej przedstawiamy próbę zdefiniowania informacji,
sposobu jej opisu i mierzenia.
A. Mazurkiewicz podaje następującą definicję informacji:
Informacją nazywamy wielkość abstrakcyjną, która może być
przechowywana w pewnych obiektach, przesyłana między pew-
nymi obiektami, przetwarzana w pewnych obiektach i stosowana
do sterowania pewnymi obiektami. Przez obiekty rozumie się tu-
taj organizmy żywe, urządzenia techniczne oraz systemy takich
obiektów.
4.2
Geneza i zakres teorii informacji
W ogólności pod pojęciem teorii informacji rozumiemy zagadnienia zwią-
zane z kodowaniem, przesyłaniem i dekodowaniem wiadomości. Jako datę
narodzin teorii informacji przyjęto uważać rok 1948, kiedy to w czasopi-
śmie The Bell System Technical Journal [Sha48] pojawiła się praca Claude
Shannona zatytułowana A Mathematical Theory of Communication. Cie-
kawe również jest to, że jest to jedna z tych dziedzin, które niesamowicie
2
Zatem otoczenie również wnosi dodatkową informację lub mówiąc inaczej jest jej
kontekstem.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4.2 Geneza i zakres teorii informacji
119
szybko się rozwijały i ich wartość zaważono od samego początku
3
Należy zaznaczyć, że przed Shannonem również inni zajmowali się po-
dobnymi zagadnieniami. Warto wspomnieć choćby o budowaniu kodów
przez Samuela Morsa, który w 1838 wymyślił używany do dziś kod. Kod
Morsa przyporządkowuje kolejnym literom alfabetu kropki i kreski, przy
czym Mors zastosował zasadę, że im dana litera częściej jest stosowana to
ma krótszy kod i odwrotnie
4
. Co prawda bazując na obecnej wiedzy, można
by poprawić kod Morsa o 15% dla języka angielskiego, jednak w tamtych
latach kod ten naprawdę był świetny.
W 1943 roku Kongres amerykański zlecił wykonanie połączenia telegra-
ficznego łączącego Waszyngton z Baltimore. W założeniu chciano umieścić
przewody pod ziemią, jednak okazało się, że zakłócenia są tak duże, że osta-
tecznie zawieszono je na słupach. Odpowiedź na pytanie dlaczego tak się
działo znajdziemy w teorii fizycznej, tu wystarczy jeśli zaakceptujemy fakt,
że przenoszenie sygnału elektrycznego jakąkolwiek drogą niesie ze sobą nie-
bezpieczeństwo zniekształcenia tego sygnału. Przekładając to na wcześniej
wprowadzoną terminologię możemy powiedzieć, że na skutek zniekształce-
nia wiadomości poprzez własności jej nośnika zniekształcona zostaje rów-
nież informacja niesiona przez tę wiadomość. Zauważono, że częściowym
rozwiązaniem problemu może być wolniejsze telegrafowanie. I tu również
znajdujemy odniesienie do codzienności, jeśli jesteśmy w głośnym pomiesz-
czeniu to zupełnie bezsensowne jest szybkie mówienie do kogoś, nasz głos
utonie w ogólnej wrzawie. Dużo lepiej jest mówić wolno i wyraźnie.
W przypadku telegrafowania spowolnienie transmisji było nie dobrym
rozwiązaniem, zatem próbowano pokonać trudności ustalając kilka wartości
prądu i odpowiadające mu sygnały. Zatem próbowano zwiększyć ilość liter
w alfabecie służącym do zapisu wiadomości
5
. W 1924 roku Harry Nyqu-
ist opublikowanej pracę wyjaśniającej na drodze matematycznej zależności
pomiędzy szybkością telegrafowania a liczbą wyróżnionych wartości prądu
jakich w tym celu użyto. W pracy tej stwierdzono, że jeśli kolejne sygnały
wysyła się w ustalonych odstępach czasu, to następujący związek jest praw-
dziwy
W = K log
2
n,
3
Dla przykładu pierwsza międzynarodowa konferencja, która dotyczyła wyłącznie teo-
rii informacji odbyła się w 1950 roku, a w 1953 roku pojawiło się czasopismo poświęcone
wyłącznie tej teorii.
4
Intuicja nam podpowiada, że jest to słuszne, w latach poźniejszych potwierdzono to
formalnie i podano warunki konstruowana kodów optymalnych
5
Zauważmy, że Mors stosował tylko dwa symbole.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
120
Teoria informacji
gdzie W oznacza szybkość telegrafowania, n — liczbę różnych wartości
prądu a K jest stałą charakteryzującą szybkość wysyłania sygnałów. Z
powyższego wzoru wynika, że prędkość wysyłania sygnału rośnie logaryt-
micznie wraz ze wzrostem ilości różnych sygnałów występujących we wia-
domości. Stąd już łatwo wysunąć wniosek, że ze względu na charakter funk-
cji logarytm od pewnego momentu nie warto dodawać kolejnych sygnałów,
gdyż daje to znikomy zysk prędkości.
Cztery lata później Nyquist wykazał, że w każdym wysyłanym sygnale
elektrycznym część energii jest zbędna; można ją usunąć a mimo to nadany
sygnał będzie można odtworzyć. Składowe te nazwał nadmiarowymi, obec-
nie mówmy też o redundancji — nadmiarowości. W 1928 Hartley po raz
pierwszy w historii, podaje definicję ilości informacji. Jeśli przyjmiemy,
że wiadomość składa się z n - symboli alfabetu, który składa się z S liter,
to miara H ilości informacji wynosi
H = n log
2
S.
Jak później udowodnił to Shannon wzór Hartleya nie jest zawsze prawdziwy.
Jest on słuszny tylko w przypadku, gdy dodatkowo zostanie założone, że
wybór poszczególnych symboli jest niezależny oraz, że wystąpienia poszcze-
gólnych liter alfabetu są niezależne.
W dalszym ciągu Shannon pracował nad teorią informacji i ostatecznie
wykazał, że można nie zmniejszająć prędkości transmisji sygnału przekazać
go możliwie wiernie przez kanał transmisyjny. Należy podkreślić, że praca
Shannona wskazywała na możliwość rozwiązania tego problemu jednak nie
podawała efektywnej metody jak to zrealizować. Spowodowało to rozłam w
dalszych pracach nad teorią informacji na dwa główne nurty: teoretyczny
— koncentrował się wokół poszukiwania miar ilości informacji, oraz prak-
tyczny — w którym próbowano znaleźć najlepsze sposoby kodowania by
przekazywać informację w sposób optymalny.
Podamy teraz kilka sposobów kontroli czy informacja, która zastała prze-
kazana (przesłana) jest poprawna, przy czym skoncentrujemy się na algoryt-
mach stosowanych w komputerach i służących kontroli poprawności prze-
syłanych danych. Zatem koncentrujemy się wyłącznie na wiadomościach
przekazywanych za pomocą kodu dwójkowego.
4.3
Metody kontroli poprawności danych
Informacje, które są dostarczane do komputera jak i do wszelkiego typu
urządzeń mu towarzyszących, w odróżnieniu od tych, którymi posługuje się
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4.3 Metody kontroli poprawności danych
121
człowiek, muszą być przekazywane bezbłędnie i jednoznacznie. Nie znaczy
to, że człowiek nie powinien dostać informacji bezbłędnej, ale zwykle jeśli
dostanie ją w jakimś stopniu uszkodzoną to „domyśli” się części brakującej.
Komputer nie posiada tej cechy, zatem musi otrzymywać informację w for-
mie oryginalnej, lub należy tak tę informację zakodować by mógł on w razie
jej uszkodzenia ją odtworzyć. Niestety często zdarza się, że dane, będąc
przekazywane w różny sposób, potrafią docierać niekompletne lub uszko-
dzone. Istnieje kilka metod pozwalających wykryć niepoprawnie przeprowa-
dzoną transmisję, a nawet wskazać, gdzie ten błąd nastąpił. Przedstawione
zostaną tutaj najpopularniejsze z nich. Ich cechą wspólną jest wydłużenia
oryginalnego komunikatu przez dopisanie na jego końcu pewnego ciągu bi-
tów, którego długość i sposób interpretacji jest zależny od przyjętej metody
postępowania.
4.3.1
Bit parzystości
Najprostszym sposobem zabezpieczania informacji jest dodanie do niej bitu
parzystości. W tym sposobie zabezpieczenia, do każdego komunikatu jest
dopisywany dodatkowy bit. Bit ten ma wartość 1 — gdy liczba jedynek
w komunikacie oryginalnym była nieparzysta, lub 0 — w przeciwnym przy-
padku.
Przykład 4.1. Obliczenie i dodanie bitu parzystości do oryginalnej
wiadomości.
Komunikat przeznaczony do zakodowania: 10011011
Liczba "jedynek": 5 - nieparzysta
Dodatkowy bit bedzie miał wartość 1
Komunikat po dopisaniu bitu parzystości: 100110111
|
bit parzystości
W przypadku tej metody nadawca wysyła komunikat z dopisanym bi-
tem parzystości. Po otrzymaniu informacji odbiorca oblicza bit parzystości
dla otrzymanej wiadomości (czyli dla ciągu bitów po opuszczeniu ostatniego
bitu — bitu parzystości). Jeśli otrzymany bit zgodny jest z bitem parzysto-
ści z komunikatu oznacza to, że wszystko jest w porządku.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
122
Teoria informacji
Niestety tego typu kontrola sprawdzi się jedynie w najprostszych sytu-
acjach. O tym, że jest to proste zabezpieczenie, świadczą poniższe przy-
kłady.
Przykład 4.2. Błędy nie wykrywalne przez bit parzystości.
Komunikat oryginaly...............................: 10011011
Bit parzystości dla oryginalnego komunikatu.......: 1
Błąd 1: zamiana miejscami bitu 7 i 8
Komunikat zniekształcony..........................: 01011011
Bit parzystości dla zniekształconego komunikatu...: 1
Błąd 2: ustawienia wartości bitów 4 i 5 na przeciwne
Komunikat zniekształcony..........................: 10000011
Bit parzystości dla zniekształconego komunikatu...: 1
Błąd 3: pierwsze 6 bitów, bez względu na ich rzeczywistą wartość,
ustawiana jest na 1
Komunikat zniekształcony..........................: 10111111
Bit parzystości dla zniekształconego komunikatu...: 1
Tego typu przekłamania zdarzyć się mogą tym łatwiej im dłuższe ko-
munikaty będą przesyłane, oraz im gorszym medium będzie prowadzona
transmisja (światłowód będzie wprowadzał mała ilość przekłamań, a łącze
podczerwone we mgle ogromną).
4.3.2
Suma kontrolna
Kolejny sposób zabezpieczania danych to obliczenie i dopisanie sumy kon-
trolnej do oryginalnej wiadomości. W tym przypadku nadawany komunikat
dzielony jest na „porcje” jednakowej długości, jeśli zdarzy się, że wiadomość
składa się z ilości bitów niepodzielnej przez długość porcji to do oryginalnej
wiadomości dopisywana jest odpowiednia ilość zer. Porcje następnie są do-
dawane do siebie. Przy czym suma jest przedstawiana na takiej ilości bitów
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4.3 Metody kontroli poprawności danych
123
jak i porcje danych. Jeśli pojawi się przepełnienie, to jest ono ignorowane
6
.
Ostatecznie suma kontrolna jest dopisywana na końcu wiadomości.
Przykład 4.3. Obliczanie sumy kontrolnej przy porcji równej 3
bity.
Komunikat oryginalny..........: 10011011
Komunikat uzupełniony zerami..: 010011011
Kolejne porcja................: P1=011, P2=011, P3=010
Obliczanie sumy...............:
S1=P1=011
S2=S1+P2=110
S3=S2+P3=1000
pierwsza jedynka od lewej stanowi przepełnienie,
zatem jest pomijana, stąd S3=000
Komunikat przesyłany (z dopisaną sumą kontrolną): 00010011011
To zabezpieczenie jest pewniejsze od poprzedniego, poniższe przykłady
ilustrują w jaki sposób błędy w komunikacie przenoszą się na sumę kontro-
lną.
Przykład 4.4. Błędy wykryte przez sumę kontrolną.
Komunikat oryginalny..........: 10011011
Komunikat uzupełniony zerami..: 010011011
Kolejne porcja................: P1=011, P2=011, P3=010
Suma..........................: 000
Błąd 1: zamiana miejscami bitu 7 i 8
Komunikat oryginalny..........: 10011011
Komunikat zniekształcony......: 01011011
Komunikat uzupełniony zerami..: 001011011
Kolejne porcja................: P1=011, P2=011, P3=001
Suma..........................: 111
6
Możemy je także potraktować jako kolejną „porcję” danych i dodać do istniejącej
sumy.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
124
Teoria informacji
Błąd 2: ustawienie wartości bitów 4 i 5 na przeciwne
Komunikat oryginalny..........: 10011011
Komunikat zniekształcony......: 10000011
Komunikat uzupełniony zerami..: 010000011
Kolejne porcja................: P1=011, P2=000, P3=010
Suma..........................: 101
Niestety i ten sposób nie jest pozbawiony wad, ilustrują to poniższe
przykłady.
Przykład 4.5. Błędy nie wykrywalne przez sumę kontrolną.
Komunikat oryginalny..........: 10011011
Komunikat uzupełniony zerami..: 010011011
Kolejne porcja................: P1=011, P2=011, P3=010
Suma..........................: 000
Błąd 1: pierwsze 6 bitów, bez względu na ich rzeczywistą wartość,
ustawiana jest na 1
Komunikat oryginalny..........: 10011011
Komunikat zniekształcony......: 10111111
Komunikat uzupełniony zerami..: 010111111
Kolejne porcja................: P1=111, P2=111, P3=010
Suma..........................: 000
Błąd 2: omyłkowe potraktowanie sygnału jako jeden z bitów
komunikatu (8, wartość 0) i zamiana miejscami
porcji P2 i P3
Komunikat oryginalny..........: 10011011
Komunikat zniekształcony......: 011010011
Komunikat uzupełniony zerami..: 011010011
Kolejne porcja................: P1=011, P2=010, P3=011
Suma..........................: 000
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4.3 Metody kontroli poprawności danych
125
Z powyższych przykładów widać, że zastosowanie sumy kontrolnej nie
daje się już tak łatwo „oszukać” jak wykorzystanie bitu parzystości, ale
wciąż nie jest to metoda pewna detekcji błędów transmisji.
4.3.3
Kod CRC
Próbą ominięcia niedoskonałości wyżej omawianych sposobów zabezpiecza-
nia danych jest kod CRC (ang. Cyclic Redundancy Code) — cykliczny
kod nadmiarowy. W tej metodzie do danych dopisywany jest kod CRC,
który jest otrzymywany przez nieco bardziej złożoną procedurę obliczeniową
niż poprzednio. W praktyce cały algorytm daje się sprowadzić do elemen-
tarnych operacji i może być bardzo łatwo zaimplementowany sprzętowo.
Do obliczenia kodu CRC potrzebny jest tak zwany wielomian gene-
racyjny. Stanowi on podstawę do obliczeń i dlatego jego znajomość jest
niezbędna zarówno dla nadawcy jak i odbiorcy. Wielomianem generacyj-
nym to łańcuch bitów, w którym kolejne pozycje są współczynnikami przy
odpowiednich potęgach wielomianu. Na przykład wielomian postaci
x
4
+ x
2
+ 1
możemy zapisać jako
1x
4
+ 0x
3
+ 1x
2
+ 0x
1
+ 1x
0
co ostatecznie daje następujący ciąg zerojedynkowy
10101
Zarówno najstarszy jak i najmłodszy bit wielomianu generacyjnego musi
być równy 1, a ciąg przeznaczony do zakodowania musi być od niego dłuż-
szy. Przy obliczeniach obowiązuje arytmetyka modulo 2, przy czym nie
uwzględnia się przeniesień przy dodawaniu i pożyczek przy odejmowaniu.
Operacje te są zatem równoznaczne z funkcją XOR. Na przykład
10110011
11110000
+ 11001010
- 10100110
----------
----------
01111001
01010110
Do ciągu danych należy dodać na końcu tyle bitów zerowych ile wynosi
stopień wielomianu generacyjnego (w przykładzie 4.6 wynosi 4). Następnie
należy rozszerzony tak ciąg danych podzielić przez wielomian generacyjny.
Dzielenie jest wykonywane według następującego algorytmu:
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
126
Teoria informacji
1. Rozpoczynamy od bitu danych położonego z lewej strony.
2. Jeśli jest on równy 1, to poniżej przepisujemy wielomian generacyjny.
3. Jeśli 0, to wpisujemy same zera.
4. Wykonujemy dodawanie modulo 2 (czyli stosujemy funkcje XOR).
5. Próba odczytu z ciągu danych kolejnego bitu danych.
6. Jeśli próba się powiodła to idziemy do kroku 2.
7. W przeciwnym razie koniec.
Reszta, która pozostanie z dzielenia, jest właśnie poszukiwanym kodem
CRC. Bity te należy wpisać na koniec ciągu danych zamiast uprzednio do-
danych bitów zerowych.
Przykład 4.6. Obliczanie kodu CRC.
Ciag z danymi..............: 10011011
Generator..................: 10101
Ciag z dopisanymi zerami...: 100110110000
100110110000 : 10101
10101.......
-----.......
00110.......
01100......
00000......
-----......
01100......
11001.....
10101.....
-----.....
01100.....
11001....
10101....
-----....
01100....
11000...
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
4.3 Metody kontroli poprawności danych
127
10101...
-----...
01101...
11010..
10101..
-----..
01111..
11110.
10101.
-----.
01011.
10110
10101
-----
00011
0011 <- kod CRC
Ciag z dopisanym kodem CRC...: 100110110011
Przy sprawdzaniu poprawności danych stosuję się taki sam algorytm,
lecz tym razem dla całego ciągu bitów (łącznie z kodem CRC), jeśli trans-
misja była bezbłędna, reszta z dzielenia będzie wynosiła zero.
W praktycznych zastosowaniach używa się następujących wielomianów
CRC-16 = x
16
+ x
15
+ x
2
+ x
0
CRC-16/CCITT = x
16
+ x
12
+ x
5
+ x
0
CRC-32 = x
32
+ x
26
+ x
23
+ x
21
+ x
16
+ x
12
+ x
11
+
x
10
+ x
8
+ x
7
+ x
5
+ x
4
+ x
2
+ x
1
+ x
0
Dla uproszczenia zapisu binarną postać wielomianu podaje się w zapi-
sie szesnastkowym pomijając najbardziej znaczący bit. Wówczas podane
powyżej wielomiany zapisać można jako
CRC-16
=
1.1000.0000.0000.0101
8005
CRC-16
7
=
1.0001.0000.0010.0001
1021
CRC-32
= 1.0000.0100.1010.0001.0001.1101.1011.0111
04A11DB7
Szczególnie dwa ostatnie wielomiany godne są polecenia, przy ich wy-
korzystaniu możliwe jest: wyłapanie wszystkich błędów pojedynczych i po-
dwójnych, błędów z nieparzystą liczbą bitów, błędów seryjnych o długości
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
128
Teoria informacji
mniejszej od 16 bitów oraz 99.99% błędów seryjnych 18-bitowych i dłuż-
szych.
4.4
Zadania
1. Oblicz wartości sumy kontrolnej dla następujących ciągów bitów (suma
kontrolna zapisywana jest na 4 bitach).
a) 1001 1110 0111 1100 1101 0101
b) 1001 0110 0101 0001 0000 0010
c) 0010 0101 1010 1100 1010 1000
d) 0101 0100 1000 0100 1000 0101
2. Oblicz wartości kodu CRC dla ciągów bitów z poprzedniego ćwiczenia.
Jako wielomian generacyjny przyjmujemy 10101.
3. Który z poniższych ciągów nie uległ przekłamaniu podczas transmisji?
(Wielomian generacyjny jak w poprzednim przykładzie).
a) 1000 0100 0100 1000 1010 0100 0100
b) 0110 0100 0100 0100 0000 1100 0101
c) 0000 0010 0010 1000 1001 0010 0110
d) 0110 0010 0010 1000 1001 0010 1111
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 5
Algorytmy i struktury
danych
Programy stanowią w końcu skonkretyzowane sformułowania
abstrakcyjnych algorytmów na podstawie określonej reprezentacji
i struktur danych.
Niklaus Wirth
5.1
Pojęcie algorytmu
Słowo algorytm, jak to wyjaśniono w punkcie 1.2.1, pochodzi od nazwiska
arabskiego matematyka. Oznacza ono procedurę czy też przepis na reali-
zację jakiegoś zadania. Przykładem może być tu wspominany algorytm
Euklidesa znajdowania największego wspólnego dzielnika liczb (zob. 1.2.1),
czy wyznaczanie podziału kąta na dwie równe części za pomocą cyrkla i li-
nijki. Ale równie dobrze algorytmem możemy nazwać procedurę wymiany
uszkodzonego elementu w komputerze.
Pierwsze opisy, które później nazwano algorytmami, dotyczyły rozwią-
zań zadań matematycznych. Już w starożytnym Egipcie i Grecji stworzono
wiele metod, które pozwalały rozwiązywać pewne zadania w sposób algo-
rytmiczny. Intuicyjnie algorytm kojarzy się z metodą rozwiązywania zada-
nia, z przepisem postępowania czy ze schematem działania. Należy jednak
podkreślić, że nie każda metoda czy schemat jest algorytmem. Algorytm
powinien spełniać następujące wymagania:
1. Musi posiadać określony stan początkowy, czyli operację od której
zaczyna się jego realizacja.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
130
Algorytmy i struktury danych
2. Ilość operacji potrzebnych do zakończenia pracy musi być skończona
— warunek dyskretności.
3. Musi dać się zastosować do rozwiązywania całej klasy zagadnień, a nie
jednego konkretnego zadania — warunek uniwersalności.
4. Interpretacja poszczególnych etapów wykonania musi być jednoznaczna
— warunek jednoznaczności.
5. Cel musi być osiągnięty w akceptowalnym czasie — warunek efek-
tywności
1
.
6. Musi posiadać wyróżniony koniec.
Wymaga się zatem, aby algorytm składał się ze skończonej liczby operacji
(poleceń) sformułowanych w sposób jednoznaczny (i jasny
2
) oraz możliwy do
wykonania w skończonym i zarazem rozsądnym czasie. Poprzez „rozsądny”
rozumiemy czas akceptowalny dla danego zadania, w dalszym ciągu zostanie
to jeszcze szerzej omówione. Zaś „jasny” oznacza tyle co zrozumiały dla
ludzi znających zasady konstruowania i czytania algorytmów.
W przeszłości matematycy czasami próbowali rozwiązywać różne pro-
blemy w sposób algorytmiczny, ale na ogół nie przywiązywano większej wagi
do precyzji opisu kolejnych kroków procedury. Wraz z rozwojem matema-
tyki pojawiły się problemy, co do których nie było pewności czy można je
rozwiązać w sposób algorytmiczny, czy też nie. Dopiero wówczas zaczęto
zastanawiać się nad tym, jak precyzyjnie sformułować pojęcie algorytmu.
Aby wykazać, że dany problem można rozwiązać w sposób algorytmiczny
wystarczy podać konkretny algorytm rozwiązania tego problemu. Jeśli jed-
nak chcemy udowodnić, że dany problem nie da się rozwiązać algorytmicz-
nie potrzeba dowieść, że nie istnieje algorytm rozwiązania danego problemu.
A to powoduje, że potrzebna jest ścisła definicja algorytmu. W latach dwu-
dziestych XX w. zagadnienie ścisłego, w sensie matematycznym, określenia
pojęcia algorytmu było jednym z głównych problemów matematyki. Defi-
nicje te zostały opracowane m. in. przez Alana Turinga, E. L. Posta i A.
Churcha. Na podstawie tych definicji wykazano, że w matematyce istnieje
wiele problemów, których nie można rozwiązać w sposób algorytmiczny.
1
Warunek ten nie jest konieczny do poprawności działania algorytmu, ale z drugiej
strony nikt nie będzie używał poprawnego algorytmu na którego wynik będzie musiał
czekać kilkaset lat...
2
Podobnie jak poprzednia uwaga, nie jest to warunek konieczny, ale z drugiej strony
szkoda tracić czas na analizę niejasnych procedur.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.1 Pojęcie algorytmu
131
Zainteresowanie algorytmami wzrastało wraz z rozwojem informatyki.
W latach pięćdziesiątych pojawił się nowy wykonawca algorytmu — kom-
puter. Oznaczało to z jednej strony potencjalny wzrost prędkości prze-
twarzania danych, a co za tym idzie coraz więcej algorytmów stawało się
rozwiązalnych w skończonym czasie. Lecz z drugiej strony, wymagało to do-
pracowania formalizmu definicji algorytmów, jak i powstania języków pro-
gramowania, za pomocą których te algorytmy miały być zapisywane i wpisy-
wane do komputera. Spróbujmy zastanowić się nad rolą algorytmów i języka
programowania. Jak to zostało powiedziane we wcześniejszych rozdziałach
(zob. 3), komputer dysponuje pewnym określonym zestawem operacji. Aby
więc przekazać mu do wykonania jakieś zadanie, należy opisać algorytm,
a następnie zapisać go przy pomocy tych instrukcji, które dany komputer
potrafi wykonać; instrukcje te muszą być przekazane w formie zrozumia-
łej dla niego. Wyrażony w ten sposób algorytm nazywa się programem
3
.
Początkowo jedynym językiem komunikowania się człowieka z komputerem
był język wewnętrzny maszyny a następnie asembler (zob. 3.4.5). Jednak
trudności jakie temu towarzyszyły, doprowadziły szybko do powstania wielu
nowych, niezależnych od konkretnego komputera, języków programowania
(zob. 6).
Wraz z rozwojem informatyki algorytm stał się pojęciem podstawowym.
Jest on, z jednej strony, narzędziem pracy informatyka, służącym do roz-
wiązywania z pomocą komputera różnego rodzaju problemów, z drugiej zaś,
stanowi przedmiot badań. Interesujące jest nie tylko, jak skonstruować
algorytm rozwiązujący dane zagadnienie, ale także czy jest on poprawny
oraz realizowalny w skończonym czasie, tzn. czy daje prawidłowe rezultaty
i czy czas jego wykonania jest „rozsądny”. „Rozsądny” w tym kontekście
oznacza, że czas realizacji jest miarą względną, nie zaś bezwzględną. Przy-
kładowo dla algorytmu obliczającego pewne skomplikowane zadanie nume-
ryczne (np. symulacja położenia planet), zaakceptujemy czas obliczenia
rzędu minut, jeśli jednak poszukujemy pierwiastków trójmianu kwadrato-
wego, taki czas wydaje się być zbyt długi. Problematyka związana z pro-
jektowaniem, oceną jakości i poprawności algorytmów nosi nazwę analizy
algorytmów.
3
Oczywiście w skład dużego programu może wchodzić wiele pomniejszych algorytmów,
jednak można je wszystkie postrzegać jako jeden złożony algorytm realizujący pewne
złożone zadanie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
132
Algorytmy i struktury danych
5.2
Struktury danych
Dzisiejsze komputery w dużym stopniu służą do przechowywania i wyszu-
kiwania informacji, której jest coraz więcej. Ponadto oczekujemy również
możliwości kategoriowania tej informacji i jej hierarchizacji. Wszystko po to
by móc znaleźć potrzebne dane szybciej i dokładnej
4
. Wszelka informacja
przechowywana w komputerach jest tylko pewnym wycinkiem świata rze-
czywistego, można powiedzieć iż stanowi ona jedynie pewien abstrakcyjny
model. Co więcej model ten albo inaczej mówiąc wycinek rzeczywistości
może być inny w zależności od tego dla jakich potrzeb będzie on konstru-
owany. Dla przykładu jeśli potrzebujemy stworzyć program do ewidencji
pacjentów w szpitalu (abstrakcyjny model pacjenta) będziemy potrzebowali
innych danych o fizycznie istniejącym pacjencie niż w programie do ewi-
dencji dłużników, chodź w obu przypadkach możemy mówić o tej samej
osobie. Zatem abstrakcja w tym miejscu oznacza ignorowanie tych cech da-
nego rzeczywistego obiektu, które nie są dla rozwiązania danego problemu
potrzebne
5
.
W przypadku przystępowania do rozwiązania problemu za pomocą kom-
putera należy najpierw zastanowić się jakie dane będziemy przetwarzać,
a następnie w jaki sposób będą one w komputerze reprezentowane — czyli
jakie struktury danych będą je przechowywały. Często przy wyborze spo-
sobu reprezentacji bierze się pod uwagę pewne ograniczenia maszyny wy-
nikające chociażby z architektury dzisiejszych komputerów. Dla przykładu
wiemy, że liczby zmiennoprzecinkowe są reprezentowane z pewną dokład-
nością. Zatem wybór reprezentacji często nie jest łatwy, co więcej bywa
często tak, że daną informację można reprezentować na kilka sposobów i
każdy z nich ma pewne wady i zalety. Prowadząc dalej to rozumowanie
dochodzimy do wniosku, że wybór struktury danych determinuje wybór al-
gorytmów na nich operujących. To w konsekwencji prowadzi do określonej
wydajności i sprawności całego programu.
5.2.1
Typ danych
Jeśli przypomnimy sobie pewne elementarne pojęcia z matematyki to wśród
nich znajdziemy takie elementy jak liczby rzeczywiste czy liczby całkowite.
Dalej mówimy o zmiennych całkowitych lub zmiennych rzeczywistych, czyli
4
Najprostszym przykładem może być poszukiwanie informacji za pomocą wyszukiwa-
rek internetowych: zwykle znajdujemy wiele stron zawierających dane słowo. Jednak
odszukanie naprawdę przydatnej dla nas informacji spoczywa niestety na nas.
5
Wynika stąd wprost, że model jest zawsze uproszczeniem rzeczywistości.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.2 Struktury danych
133
elementach odpowiednio zbioru liczb całkowitych i rzeczywistych. W przy-
padku algorytmów przetwarzających dane i dalej języków programowania w
których te algorytmy są zapisywane również wprowadza się pojęcie zmiennej
i jej typu, czyli zbioru dopuszczalnych jej wartości
6
.
Zwykle wyróżnia się typy proste oraz typy złożone. Do typów pro-
stych zalicza się z reguły typy liczbowe takie jak całkowity czy rzeczy-
wisty; typ znakowy — dla zmiennych zapamiętujących znaki alfanume-
ryczne; typ logiczny
7
— dla zmiennych logicznych, i wiele innych które
są już zależne od konkretnego języka programowania. Z kolei typy złożone
są konglomeratami zmiennych prostych lub innych typów złożonych, i tu
zasadniczo wyróżnia się tablicę, rekord, plik, zbiór. Omówimy teraz
kolejno wymienione typy złożone, przy czym skupimy się wyłącznie na naj-
ważniejszych ich cechach bez wchodzenia w niuanse implementacyjne czy
też warianty tych typów. Szersze omówienie zarówno struktur danych jak
i algorytmów można znaleźć w specjalistycznych książkach.
5.2.2
Tablica
Tablica (ang. array) jest jedną z najpowszechniej stosowanych struktur da-
nych, ponadto występuje na poziomie implementacyjnym w prawie wszyst-
kich językach programowania. Jest to struktura danych pozwalająca zapa-
miętywać wyłącznie elementy tego samego typu. Wyobraźmy sobie pojem-
nik na płyty CD, nie mamy możliwości włożyć do niego np. kasety VHS.
Kolejną cechą tablic jest dostęp swobodny (ang. random access) do jej
elementów — oznacza to, że dostęp do dowolnego elementu tablicy odbywa
się w taki sam sposób, oraz że można do nich się odwoływać w dowolnej ko-
lejności. Tu znów posłużmy się analogią ze stojakiem na płyty CD: po każdą
z płyt można sięgnąć w ten sam sposób — swobodnie. W przypadku tablic
do odwołania się (sięgnięcia) do konkretnego jej elementu stosuje się indek-
sowanie. To znaczy podajemy oprócz nazwy tablicy numer elementu do
którego chcemy się odwołać. Dla przykładu niech T będzie nazwą zmiennej
tablicowej, odwołanie do elementu o indeksie 1 i zapisanie do niego wartości
3 będzie miało postać:
T[1] := 3
6
Istnieją języki programowani w których nie ma konieczności informowania jakiego
typu jest dana zmienna, jednak nie będziemy ich tu szczegółowo omawiać. Według naszej
opinii u początkujących informatyków wprowadzają one niepotrzebne zamieszanie i uczą
złych nawyków.
7
Zwany również typem boolowskim.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
134
Algorytmy i struktury danych
W prezentowanym przykładzie zastosowano znak := oznacza on przypisanie
wartości, dla odróżnienia od znaku =, który będzie oznaczał porównanie
dwu wartości. Przy czym zapis powyższy jest sprawą umowną, która jest
zależna od przyjętej symboliki, lub języka programowania, jeśli jest to zapis
w konkretnym już języku
8
.
Definicję typu tablicowego będziemy zapisywali w następujący sposób:
type tablica = array[1..10] of Integer
i zapis ten oznacza definicję typu o nazwie tablica, który będzie się składał
z dziesięciu elementów typu całkowitego, przy czym pierwszy dopuszczalny
indeks będzie miał wartość 1, ostatni zaś 10. Przy definiowaniu typu tabli-
cowego dla celów analizy algorytmu, dopuszcza się często indeksu dowolne,
tj. powyższa definicja mogłaby mieć postać:
type tablica = array[-1..8] of Integer
i również oznaczałaby typ tablicowy złożony z liczb całkowitych, jednak o
innych dopuszczalnych wartościach najmniejszych i największych niż w po-
przednim przykładzie
9
Nic też nie stoi na przeszkodzie by mówić o tablicach wielowymiaro-
wych, w których każdy z indeksów może przebiegać inny przedział wartości.
Jeśli chodzi o intuicję dla dwuwymiarowej tablicy to jest ona prosta, jeśli
przypomnimy sobie określenie macierzy w matematyce. Jest to jest to wła-
śnie tablica dwuwymiarowa. Jako przykład tablicy trójwymiarowej można
podać choćby kostkę Rubika, natomiast jeśli chodzi o większą ilość wymia-
rów to tu już wyobraźnia zawodzi
10
. Niemniej jednak można podać prosty
przykład uzasadniający stosowanie tego typu konstrukcji. Rozważmy wielo-
piętrowy budynek — jego adres jest pierwszym wymiarem, następnie piętro
— drugi wymiar, korytarz — trzeci, numer pokoju na korytarzu — czwarty.
Oczywiście można ten przykład rozwinąć bez problemu na 5 czy 6 wymiarów
dołączając miasto, kraj itp.
5.2.3
Rekord
Jak można było zauważyć pewną wadą tablicy jest konieczność przechowy-
wania elementów tego samego typu
11
. W pewnych sytuacjach jest to nie-
8
My zapożyczyliśmy symbolikę z języka Pascal.
9
Nie można tej własności przenieść na języki programowania — nie wszystkie pozwa-
lają na coś takiego.
10
Przynajmniej piszących te słowa autorów.
11
Co prawda konkretne realizację tablic, w istniejących językach programowania, do-
puszczają wkładanie do tablicy elementów różnych typów, ale tak naprawdę są to nowe
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.2 Struktury danych
135
dogodne, ale do takich celów zastał zaprojektowany rekord (ang. record),
który jest najbardziej ogólną metodą na stworzenie struktury danych. W
rekordzie istnieje możliwość zapamiętania dowolnej ale określonej ilości da-
nych dowolnych typów. Elementy występujące w rekordzie nazwiemy jego
polami. Jako przykład takich konstrukcji może służyć rekord danych oso-
bowych, gdzie będzie zapamiętane imię, nazwisko, wiek itp. Dopuszcza się
również, by elementami (składowymi) rekordu były inne typy złożone, czyli
np. tablice, rekordy, zbiory itd.
Głównym przeznaczeniem rekordu jest powiązanie różnych informacji w
jedną logiczną całość, tak by móc się do niej odwoływać wspólnie. Przykła-
dowo jeśli znajdziemy poszukiwaną osobę z imienia i nazwiska, z pewnością
będą nas interesowały dodatkowe informacje z nią związane, jak np. adres
zamieszkania
12
.
Typ rekordowy będziemy definiowali w następujący sposób:
type osoba = rekord
imie: napis;
nazwisko: napis;
wiek: Integer;
end
Powyższy przykład definiuje rekord składający się z imienia. nazwiska,
wieku
13
. W przeciwieństwie do tablicy w rekordzie nie ma mowy o 5-tym
czy 2-gim elemencie, mówimy wyłącznie o polu o określonej nazwie. Zatem
odwołanie od konkretnego pola odbywa się poprzez określenie o jaki rekord
nam chodzi i o jakie jego pole, zwykle te nazwy oddzielone są kropką
14
.
Przyjmując definicje rekordu osoba z powyższego przykładu, odwołanie się
do jego pól może mieć postać:
o: osoba;
wypisz(o.imie);
o.wiek := 12;
Powyższy zapis oznacza definicję zmiennej o nazwie „o”, która jest typu
„osoba”, a następnie odwołanie się do imienia z tego rekordu i wypisanie
go, po czym wpisanie wartości do pola „wiek” w tym rekordzie.
konstrukcje struktur złożonych, tzw. tablice z wariantami.
12
Faktycznie adres zamieszkania może stanowić również rekord.
13
W definicji użyto typu „napis”, który wcześniej nie był zdefiniowany, ale przyjmujemy
jego intuicyjne znaczenie.
14
„Zwykle” ponieważ zależy to od przyjętej notacji — kropkę stosuje większość języków
programowania.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
136
Algorytmy i struktury danych
Wprowadza się również pojęcie rekordu z wariantami, jest to taka kon-
strukcja, która może mieć pewne pola alternatywne, dla przykładu dla osoby
można zapamiętać wiek, lub datę urodzenia. Jednak nie będziemy tej wersji
omawiali tu szerzej, zainteresowany czytelnik może znaleźć opis tej struk-
tury danych np. w książce [Wir01].
5.2.4
Zbiór
Kolejną strukturą danych, o której warto wspomnieć jest zbiór (ang. set).
Jest to odpowiednik pojęcia z matematyki, zatem dla każdego zbioru mamy
określone operacje: przecięcia (część wspólna), sumy, różnicy, przyna-
leżności.
Definicja typu zbiorowego ma następującą postać:
type T = set of typBazowy;
oznacza ona, że T jest zbiorem elementów typu typBazowy. Wartościami
zmiennej typu T są wszystkie możliwe podzbiory elementów typu bazowego.
Zbiór jest ciekawą konstrukcją, która nie posiada cech swoich poprzed-
ników. To znaczy nie możemy odwołać się do 3-go elementu, ponieważ
elementy w zbiorze nie mają kolejności, ani też nie możemy odwołać się
poprzez nazwę elementu, gdyż jej nie posiadają. Za to łatwo możemy odpo-
wiedzieć na pytania, czy zbiór jest pusty, czy dany element należy do zbioru
itp.
15
5.2.5
Plik
Omawiane do tej pory struktury danych charakteryzowały się tym, że była
znana ich wielkość
16
. Zatem stosunkowo łatwo było je przechowywać w pa-
mięci. Niestety istnieje całą rzesza dynamicznych struktur danych takich
jak kolejki, drzewa, grafy itp., które nie posiadają tej cechy. Przejrzyjmy się
jednej z takich struktur danych, a mianowicie plikowi. Plik reprezentuje
strukturę danych, która odpowiada koncepcji ciągu. Ciąg jest sekwencyjną
strukturą danych, gdzie elementy są ustawione jeden po drugim. Elemen-
tami ciągu mogą być rekordy, tablice i inne typy złożone, przy czym ich
ilość jest nieograniczona, zatem zawsze można dopisać następny element do
ciągu
17
. Podstawowe operacje na ciągach to: pobranie elementu pierwszego,
15
Jest to dokładny odpowiednik pojęcia zbioru znanego z matematyki.
16
Oczywiście o ile znana była wielkość ich elementów.
17
O ile oczywiście wystarczy nośnika danych.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.3 Metody opisu algorytmów
137
dodanie elementu na koniec, połączenie dwu ciągów w jeden ciąg. Fizycz-
nie ciąg jest reprezentowany poprzez plik sekwencyjny, gdyż to pozwala
odwzorować charakter ciągu i operacji na nim wykonywanych.
Definicja typu plikowego ma postać:
type T = file of typBazowy;
Dla pliku zdefiniowane są podstawowe operacje, takie jak: utworzenie
pliku, otwarcie pliku, dopisanie elementu na końcu pliku, odczy-
tanie następnego elementu pliku.
5.3
Metody opisu algorytmów
Jak wspomniano wcześniej algorytm jest pewnego rodzaju sformalizowa-
nym zapisem pewnej procedury. W celu uniknięcia nieporozumień co do
znaczenia pewnych słów, która mogłaby spowodować złą interpretację algo-
rytmu, wprowadza się umowne sposoby zapisu algorytmów. I tak zasadni-
czo wyróżnia się zapis przy pomocy: schematu blokowego, metajęzyka
programowania oraz ograniczonego podzbioru języka naturalnego.
Omówimy pokrótce każdy z tych sposobów.
5.3.1
Schemat blokowy
Schematy blokowe są uniwersalną i dającą odpowiedni stopień ogólności
formą zapisu algorytmu. Cechuje je przy tym duża przejrzystość i czytel-
ność. Schematy te odzwierciedlają dobrze strukturę algorytmu w tym takie
elementy jak rozgałęzienia czy punkty decyzyjne. Punkt decyzyjny to
miejsce w którym podejmowana jest decyzja, którą z gałęzi (dróg) algo-
rytmu pójść, decyzja ta jest podejmowana na podstawie pewnego warunku
lub ich zespołu. Zatem punkt decyzyjny jest miejscem rozgałęzienia algo-
rytmu. Rysunek 5.1 zawiera podstawowe elementy schematu blokowego,
których znaczenie jest następujące:
Stan — Określa zwykle moment startu i końca.
Zapis/odczyt — Wskazuje miejsce w których odbywa się zapis danych
(bądź ich odczyt) na nośniki informacji.
Instrukcje — Blok instrukcji, które mają być wykonane.
Decyzja — Wyliczenie warunku logicznego znajdującego się wewnątrz sym-
bolu i podjęcie na jego podstawie decyzji.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
138
Algorytmy i struktury danych
Rysunek 5.1: Przykładowe symbole stosowane na schematach blokowych.
Łącznik — Połączenie z inną częścią schematu blokowego, np. gdy nie
mieści się on na jednej stronie.
Schemat blokowy, zwany również siecią działań, tworzony jest według
pewnych reguł:
1. schemat blokowy składa się z bloków połączonych zorientowanymi li-
niami;
2. bloki obrazują ciąg operacji;
3. zawsze wykonywane są albo wszystkie instrukcje w bloku albo żadna;
4. dalsze operacje nie zależą od poprzednich wariantów, chyba że zależ-
ności te zostały przekazane za pomocą danych;
5. kolejność wykonania operacji jest ściśle określona przez zorientowane
linie łączące poszczególne bloki;
6. do każdego bloku może prowadzić co najwyżej jedna linia;
7. linie mogą się łączyć a punkty takiego połączenia określane są jako
punkty zbiegu.
Na rysunku 5.2 znajduje się fragment algorytmu do obliczania pierwiast-
ków trójmianu. Łączniki A i B informują, że dalsze części algorytmu znaj-
dują się na osobnym schemacie lub schematach. Wtedy tamte schematy
muszą zaczynać się od odpowiedniego łącznika.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.3 Metody opisu algorytmów
139
Rysunek 5.2: Schemat blokowy — fragment algorytmu znajdowania pier-
wiastków trójmianu.
5.3.2
Schemat zapisu algorytmu za pomocą pseudo-języka
Inną metodą przedstawienia algorytmu jest użycie zapisu za pomocą pew-
nego pseudo-języka programowania. Zaletą tego podejścia jest bar-
dzo łatwa późniejsza implementacja za pomocą już konkretnie wybranego,
istniejącego języka programowania
18
. Wadę stanowi natomiast mniejsza
przejrzystość. Dla osób nie przywykłych do analizowania kodu źródłowego
programów, dużo czytelniejsze jest przedstawienie w postaci schematu blo-
kowego. Poniżej przedstawiamy typowe operacje użyte do opisu algorytmu
za pomocą omawianej metody, przy czym dla porównania, tam gdzie to jest
18
Dzieje się tak ponieważ większość konstrukcji podstawowych takich jak warunek, czy
pętla, mają podobną postać w różnych językach.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
140
Algorytmy i struktury danych
Rysunek 5.3: Instrukcja warunkowa if zapisana w postaci schematu blo-
kowego: a) warunek if (W) instrukcje, b) if (W) instrukcje1 else
instrukcje2
.
sensowne, przedstawiamy za pomocą rysunku ich postać blokową.
Podstawowe instrukcje służące do opisu algorytmów:
• instrukcja podstawienia
a:=b;
W wyniku wykonania tej instrukcji zmienna a przyjmuje wartość zmien-
nej b.
• instrukcja warunkowa
if (warunek) then
begin
instrukcje realizowane gdy warunek jest spełniony
end
else
begin
instrukcje realizowane gdy warunek jest niespełniony
end
Podstawowa instrukcja warunkowa, wpierw wyliczany jest warunek
w nawiasie
19
, następnie jeśli jest on prawdziwy wykonywane są in-
19
„Wyliczany” oznacza w tym miejscu tyle co wyznaczana jest jego wartość logiczna.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.3 Metody opisu algorytmów
141
Rysunek 5.4: Pętla while i do--while zapisana w postaci schematu bloko-
wego.
strukcje w pierwszym bloku, w przeciwnym razie w drugim bloku,
po słowie else. Często używany jest również w uproszczonej wersji,
bez części „w przeciwnym razie”. Ilustracja graficzna znajduje się na
rysunku 5.3.
• instrukcje pętli do–while i while
do
begin
... ciąg instrukcji powtarzanych
dopóki warunek jest spełniony ...
end
while (warunek);
while (warunek)
begin
... ciąg instrukcji powtarzanych
dopóki warunek jest spełniony ...
end
Są to dwie pętle, umożliwiające wykonywanie cykliczne instrukcji,
które znajdują się w ich wnętrzu. Przy czym instrukcje te są wy-
konywane tak długo, jak długo warunek ma wartość logiczną prawda.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
142
Algorytmy i struktury danych
Rysunek 5.5: Pętla for zapisana w postaci schematu blokowego.
Różnica pomiędzy tymi dwoma pętlami sprowadza się do kolejności
wykonania instrukcji wewnętrznych i sprawdzenia warunku. Pierw-
sza z nich wpierw wykonuje instrukcje a następnie sprawdza warunek,
druga zaś odwrotnie. Ilustracja graficzna omawianych pętli znajduje
się na rysunku 5.4.
• instrukcji pętli for
for i:=1 to 10 step 1 do
begin
... instrukcje powtarzane 10 razy ...
end
Pętla ta wykonuje cyklicznie instrukcje zawarte pomiędzy słowani
begin
i end. Przy czym wykonanie zaczyna się od przypisania zmien-
nej i wartości 1 — początek (P), po czym następuje sprawdzenie czy
i
nie przekracza wartości granicznej 10 — warunek końca (K). Dalej
jeśli warunek ten jest fałszywy wykonane zostają instrukcje, następnie
zostaje zwiększona zmienna i o wartość występującą po słowie step
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.4 Podstawowe algorytmy
143
(S) i na koniec następuje przejście do sprawdzania warunku (K). Ilu-
stracja graficzna z odpowienim oznaczeniem literowym znajduje się na
rysunku 5.5. Można jeszcze dodać, że zamiast słowa to można zasto-
sować słowo downto, które informuje, że zmienna ma być zmniejszana
o zadany krok a nie zwiększana. Można również pomijać jawne wska-
zanie wartości kroku, w takim przypadku przyjmuje się, że jest on
równy 1.
Zdarza się również, że w schematach blokowych wstawia się nieformalne
instrukcje wyrażone w języku naturalnym. Można spotkać taki oto zapis
if (plik=OTWARTY) then
begin
Zapisanie danych do pliku
end
else
begin
Komunikat o błędzie
end
Gdzie oczywiście zapisy ,,Zapisanie danych na dysk’’ i ,,Komunikat
o błędzie’’
są tylko informacjami o tym co w tym miejscu ma wystąpić, a
czego z jakiś przyczyn nie chcemy w danej chwili wyspecyfikowywać. Czę-
sto są to po prostu odwołania do innych procedur, które są dobrze znane
i opisane gdzie indziej.
5.4
Podstawowe algorytmy
Pokażemy teraz kilka algorytmów zapisanych bądź w pseudo-języku, bądź,
gdzie to będzie zbyt skomplikowane, ograniczymy się jedynie do nieformal-
nego zarysowania ich idei. Algorytmy te reprezentują pewne charaktery-
styczne typy występujące w algorytmice. Z konieczności ograniczymy się do
kilku podstawowych grup.
5.4.1
Algorytmy obliczeniowe
Jest to cała gama algorytmów służących do wyliczania pewnych wartości
bądź rozwiązywania problemów numerycznych. Przykładami takich al-
gorytmów mogą być NWD czy NWW, w tym miejscu pokażemy oblicza-
nie pierwiastków trójmianu, przykład 5.1. W prezentowanym przykładzie,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
144
Algorytmy i struktury danych
użyto procedury wypisz, co do której przyjmujemy intuicyjnie jej działanie
polegające na wyświetleniu podanego w cudzysłowie napisu.
Przykład 5.1. Algorytm obliczania rzeczywistych pierwiastków rów-
nania kwadratowego.
if (A=0) then
begin
wypisz("To nie jest równanie kwadratowe");
end
else
begin
D:=B^2-4*A*C;
if (D<0) then
begin
wypisz("Nie ma rzeczywistych rozwiązań");
end
else
begin
if (D>0) then
begin
R1:=(-B-Sqrt(D))/(2*A);
R2:=(-B+Sqrt(D))/(2*A);
end
else
begin
R1:=-B/(2*A);
R2:=R1;
end
end
wypisz("Pierwiastkami są: ", R1, R2);
end
5.4.2
Algorytmy sortowania
Bardzo często czynnością wykonywaną przez każdego z nas, często w sposób
nieświadomy, jest procedura sortowania. Mówiąc inaczej jest to algorytm
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.4 Podstawowe algorytmy
145
porządkowania, czy też układania pewnego zbioru elementów według zada-
nego klucza. Bardzo istotnym jest tu wskazanie klucza, który będzie wy-
różnikiem na którym będzie dokonywana operacja porównania. Zauważmy,
że jeśli mamy zbiór osób, i teraz ustawimy je rosnąco względem wzrostu,
to nie jest to równoznaczne z porządkiem względem wagi, a już na pewno
względem długości włosów.
Jako przykład prostego algorytm sortowania opiszemy sortowanie przez
wstawianie, zwane również sortowaniem przez proste wstawianie. Spójrzmy
wpierw na rysunek 5.6, znajdują się na nim w linii zatytułowanej START
liczby całkowite w losowej kolejności.
Rysunek 5.6: Ilustracja procesu sortowania przez wstawianie.
Naszym zadaniem jest poukładanie tych ośmiu liczb rosnąco, w tym
celu bierzemy pod uwagę wpierw element drugi. Dla tak wyróżnionego ele-
mentu sprawdzamy czy nie można go wstawić gdzieś przed nim, tj. w tym
konkretnym przypadku czy nie jest on mniejszy od pierwszego elementu.
Zauważamy, że nie jest, zatem pozostawiamy go na miejscu i przechodzimy
do następnego — trzeciego elementu. Dla niego sprawdzamy wpierw czy
nie możemy go wstawić na pierwsze miejsce, rzeczywiście możemy, gdyby-
śmy nie mogli to sprawdzilibyśmy jeszcze miejsce drugie. Całą procedurę
powtarzamy kolejno dla pozostałych elementów.
Spróbujmy zapisać opisany algorytm za pomocą pseudo-języka. Przy
pierwszej próbie zapisania ten algorytm będzie miał on następującą postać:
for i:=2 to n do
begin
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
146
Algorytmy i struktury danych
x:=a[i];
"wstaw x w odpowiednie miejsce w ciągu a[1]...a[i-1]";
end
Teraz sprecyzujemy pseudokod procesu wyszukiwania miejsca wstawie-
nia elementu x, oraz uzupełnimy powyższy algorytm o ten fragment. W efek-
cie otrzymamy prostą implementację algorytmu sortowania przez wstawia-
nie zaprezentowaną w przykładzie 5.2. Zauważmy jednocześnie, że algorytm
ten działa niejako jak procedura układania książek na półce, wyjmujemy
rozważaną książkę, następnie przesuwamy w prawo książki od niej więk-
sze, a następnie wsadzamy ją w miejsce zwolnione i dla niej przeznaczone.
Teraz by można było tę książkę wyjąć należy mieć wolną rękę, która ją przy-
trzyma. Podobnie w algorytmie: musimy liczbę gdzie przechować by móc
przesunąc na jej miejsce inne. Stąd w przykładzie 5.2, występuje przypisa-
nie a[0]:=a[i], które właśnie zapamiętuje w pomocniczej komórce tablicy
— nie wykorzystywanej do przechowywania elementów — element, który w
danej chwili rozważamy.
Przykład 5.2. Algorytm sortowania przez wstawianie.
for i:=2 to n do
begin
a[0]:=a[i];
j:=i-1;
while (a[0] < a[j])
begin
a[j+1]:=a[j];
j:=j-1;
end
a[j+1]:=a[0];
end
5.4.3
Algorytmy wyszukujące
Drugim często spotykanym zagadnieniem jest poszukiwanie informacji o za-
danym kluczu. Czyli mamy na przykład zbiór osób, które posiadają jakąś
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.4 Podstawowe algorytmy
147
Rysunek 5.7: Ilustracja procesu przeszukiwania połówkowego.
cechę (klucz), niech to będzie wzrost. Następnie szukamy osoby o wzroście
178cm. Możemy spotkać się z dwoma przypadkami, pierwszy to taki gdy
osoby te są w dowolnym porządku — czyli nie poukładane, oraz drugi, gdy
mamy grupę osób ustawioną względem tego klucza — jak na wojskowej pa-
radzie. Jeśli będziemy rozpatrywali pierwszy przypadek, to nie pozastaje
nam nic innego jak brać po jednym z elementów i sprawdzać czy pasuje
do naszego wzorca, taki sposób nosi też nazwę wyszukiwania liniowego.
Jednak w drugim przypadku możemy poradzić sobie lepiej, to znaczy efek-
tywnej jeśli zastosujemy wyszukiwanie połówkowe lub binarne.
Wyjaśnimy ten sposób realizacji procedury szukania na przykładzie.
Spójrzmy na rysunek 5.7, w pierwszym wierszu są przedstawione liczby cał-
kowite posortowane od najmniejszej do największej. Będziemy poszukiwali
wartości 15, jeśli spróbujemy jej szukać tak jak w zbiorze nieuporządkowa-
nym i zaczniemy naszą procedurę od pierwszego elementu, to znajdziemy
tę wartość w czwartym kroku.
Możemy jednak poszukiwać inaczej, wpierw wybieramy element środ-
kowy w tym ciągu
20
. Porównujemy wartość tego elementu z wartością
szukaną, jeśli jest to ta wartość to zwracamy numer tego elementu. W
przeciwnym razie wiemy, że poszukiwany element jest bądź na prawo, bądź
na lewo od środka
21
. I dalej rozważamy tylko ten fragment ciągu, w któ-
rym potencjalnie znajduje się nasz element
22
. Cały proces powtarzamy dla
okrojonego zbioru, jeśli znajdziemy element zwracamy jego pozycję, jeśli
dojdziemy do zbioru pustego zwracamy informację, że nie znaleźliśmy tego
elementu. Proces ten jest właśnie zilustrowany na rysunku 5.7.
20
Jeżeli jest parzysta ilość elementów, to umawiamy się że jest to jeden z elementów
leżących przy środku. Ważne jest tylko by zawsze to robić konsekwentnie.
21
Zauważmy, że to jest miejsce w którym wykorzystujemy wiedzę o uporządkowaniu
zbioru. Gdyby te elementy były ułożone przypadkowo nie można by było wysunąć takiego
wniosku.
22
Potencjalnie, gdyż zaczynając poszukiwania nie wiemy czy on w ogóle jest w tym
zbiorze.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
148
Algorytmy i struktury danych
Zauważmy, że element poszukiwany 15 został znaleziony w trzech kro-
kach, zatem o jeden krok szybciej niż w przypadku przeszukiwania linio-
wego. Możemy oczywiście wzruszyć ramionami i stwierdzić, że to niewielka
oszczędność czasu. Jednak zauważmy, że poszukiwanie jakiegokolwiek ele-
mentu w tym zbiorze będzie zajmowało co najwyżej cztery kroki w przy-
padku wyszukiwana połówkowego, zaś aż 9 w przypadku wyszukiwania li-
niowego. Oczywiście gdy mamy pecha i poszukujemy akurat elementu wy-
stępującego na końcu. Ale często to włąśnie te najgorsze przypadki bierze się
pod uwagę przy analizowani sprawności (wydajności) algorytmów. Drugą
taką miarą jaką się rozważa jest średnia ilość kroków, jaką trzeba wykonać
w przypadku jednego bądź drugiego algorytmu.
5.5
Rekurencja vs. iteracja
W tym punkcie zasygnalizujemy dwa podstawowe podejścia do realizacji
prostych algorytmów: podejście iteracyjne i podejście rekurencyjne.
Zacznijmy od wyjaśnienia pojęcia rekurencji.
Obiekt nazwiemy rekurencyjnym, jeśli częściowo składa się z siebie
samego lub jego definicja odwołuje się do niego samego. Innym słowem,
które jest odpowiednikiem rekurencji jest rekursja.
Z rekurencją mamy do czynienie również w życiu codziennym — wy-
starczy ustawić na przeciw siebie dwa lusterka i zobaczyć jaki otrzymamy
obraz. Powinniśmy zobaczyć lusterko, a w nim lusterko, a w nim lusterko,
a w nim . . .
Siła rekursji wyraża się w możliwości definiowania nieskończonego zbioru
obiektów za pomocą skończonego wyrażenia. Dokładnie na tej samej za-
sadzie, nieskończoną liczbę obliczeń można zapisać za pomocą skończo-
nego programu rekurencyjnego. Narzędziem umożliwiającym tworzenie pro-
gramów rekurencyjnych jest funkcja (można też mówić o procedurze, czy
podprogramie). Funkcją nazwiemy zbiór instrukcji, który posiada nazwę,
wtedy nazwa ta stanowi jednocześnie nazwą tej funkcji. Do funkcji można
przekazać dane poprzez jej argumenty, można też żądać od niej zwrotu po-
liczonych wartości
23
. Jeśli jakaś funkcja zawiera odwołanie do siebie samej
to nazwiemy ją funkcją rekurencyjną.
Podobnie jak pętle, które pozwalają nam iterować (czyli powtarzać wie-
lokrotnie zestaw instrukcji), funkcje rekurencyjne dopuszczają możliwość
wykonywania powtórzeń z tym wszakże wyjątkiem, że nieskończonej ich
23
To co przyjmuje funkcja i co zwraca określa jej twórca.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.5 Rekurencja vs. iteracja
149
liczby
24
. Wiąże się z tym konieczność rozwiązania problemu stopu. Za-
sadniczym wymaganiem w takiej sytuacji jest uzależnienie rekurencyjnego
wywołania funkcji od warunku, który w pewnym momencie przestaje być
spełniony co w konsekwencji powoduje zatrzymanie procesu rekurencji. W
celu wykazania, że proces wywołań rekurencyjnych się skończy, należy po-
kazać, że osiągnięty będzie warunek stopu.
Algorytmy rekurencyjne są szczególnie odpowiednie wtedy, gdy rozwa-
żany problem lub przetwarzane dane są zdefiniowane w sposób rekurencyjny.
Dla przykładu rozważmy dwa sposoby realizacji funkcji obliczającej silnię.
Pierwszy z nich, pokazany w przykładzie 5.3 realizuje silnię za pomocą pętli,
zatem w sposób iteracyjny. Przy czym przyjmijmy na potrzeby tego roz-
działu, że zapis silnia i := s będzie oznaczał, że funkcja silnia i będzie
zwracała wartość s — wyliczoną wartość silni.
Przykład 5.3. Funkcja obliczająca silnię — podejście iteracyjne.
silnia_i(n)
begin
i:=0;
s:=1;
while (i<n) do
begin
i:=i+1;
s:=s*i
end
silnia_i := s;
end
Drugi sposób realizacji silni jest pokazany w przykładzie 5.4 i jest to
podejście rekurencyjne.
Przykład 5.4. Funkcja obliczająca silnię — podejście rekurencyjne.
24
Oczywiście ta nieskończona ilość operacji jest wyłącznie teoretyczna, w praktyce prze-
cież realizacja wykonania funkcji odbywa się na komputerze, który nie jest wieczny.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
150
Algorytmy i struktury danych
silnia_r(n)
begin
if (n=0) then
w := 1;
else
w := n*silnia_r(n-1);
silnia_r := w;
end
Przykład 5.5. Przebieg wywołań rekurencyjnych przy obliczaniu
wartości 5!.
s_r(5)
.
|
.
5*s_r(4)
.
.
|
.
.
4*s_r(3)
.
.
.
|
.
.
.
3*s_r(2)
.
.
.
.
|
.
.
.
.
2*s_r(1)
.
.
.
.
.
|
.
.
.
.
.
1*s_r(0)
.
.
.
.
.
.
|
.
.
.
.
.
. <---1
.
.
.
.
.
. |
.
.
.
.
. <---1*1
.
.
.
.
. |
.
.
.
. <---2*1
.
.
.
. |
.
.
. <---3*2
.
.
. |
.
. <---4*6
.
. |
<---5*24
|
120
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.5 Rekurencja vs. iteracja
151
Jednak nie zawsze funkcje, która jest dana wzorem rekurencyjnym po-
winno się realizować takim algorytmem. W istocie istnieją bardziej skom-
plikowane schematy rekurencyjne, które mogą i powinny być przekształcane
do postaci iteracyjnych. Dobry przykład stanowi tutaj zagadnienie oblicza-
nia liczb ciągu Fibonacciego. Ciąg Fibonacciego, dla n > 1, zdefiniowany
jest następująco
f ib
n
+1
:= f ib
n
+ f ib
n−1
natomiast wyrazy 1 i 0 przyjmują wartość 1.
Rekurencyjna implementacja funkcji obliczającej liczby ciągu Fibonac-
ciego jest zaprezentowana w przykładzie 5.6.
Przykład 5.6. Funkcja obliczająca n-tą liczbę ciągu Fibonacciego
— podejście rekurencyjne.
fib_r (n)
begin
if (n=1) then
w := 1;
if (n=0) then
w := 1;
w := fib_r(n-1)+fib_r(n-2);
fib_r := w;
end
Podejście rekurencyjne nie zdaje egzaminu w tym przypadku; każde wy-
wołanie powoduje dwa dalsze wywołania, tj. całkowita liczba wywołań ro-
śnie wykładniczo (patrz rysunek 5.8). Co szybko prowadzi do wyczerpania
stosu i jednocześnie działa wolno, gdyż funkcja dla tych samych danych jest
wyliczana kilkukrotnie
25
. W tym przypadku lepiej użyć funkcji iteracyjnej,
jak to zaprezentowano w przykładzie 5.7.
25
Nawet kilkadziesiąt, bądź kilkaset razy.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
152
Algorytmy i struktury danych
fib(5)
fib(2)
fib(3)
fib(4)
fib(3)
fib(2)
fib(1)
fib(2)
fib(1)
Rysunek 5.8: Drzewo wywołań dla rekurencyjnego obliczania 5-ego wyrazu
ciągu Fibonacciego.
Przykład 5.7. Funkcja obliczająca n-tą liczbę ciągu Fibonacciego
— podejście iteracyjne.
fib_i (n)
begin
i:=1;
x:=1;
y:=1;
while (i<n)
begin
z:=x;
i:=i+1;
x:=x+y;
y:=z;
end
fib_i := x;
end
Celem lepszego uzmysłowienia różnic powyższych funkcji dokonajmy po-
równania czasu wykonania programów powyższych programów. Poniższa
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.6 Analiza złożoności
153
tabela zawiera czasy dla algorytmu rekurencyjnego. Wersja iteracyjna ob-
licza 1000-ny wyraz w czasie nie mierzalnym przy wykorzystaniu stopera.
Test przeprowadzono na komputerze 486 DX 4 120 MHz, w środowisku
MS-DOS
26
.
wyraz czas (s)
30
2
31
2.56
32
3.54
33
5.10
34
7.11
35
12.67
36
18.84
37
29.40
38
48.12
39
75.82
40
>90.0
5.6
Analiza złożoności
Często ten sam problem można rozwiązać za pomocą różnych algorytmów,
co było pokazane choćby w punkcie 5.5. W takim razie należy się zastano-
wić jakie są różnice pomiędzy tymi algorytmami, oraz czy różnice te mają
wpływ na wybór konkretnego algorytmu do implementacji. Przy porówny-
waniu algorytmów zwykle bierze się pod uwagę ich efektywność (szybkość
działania), zapotrzebowanie na zasoby pamięciowe systemu, wreszcie ich
czytelność. Tak naprawdę czytelność jest rzeczą względną i zależy od dłu-
gości praktyki osoby czytającej, stąd też rzadko jest brana pod uwagę przy
porównywaniach. Istotne różnice, z punktu widzenia praktyki, to prędkość
działania algorytmu i jego zapotrzebowanie na pamięć. Przy czym od razu
należy zaznaczyć, że różnice między algorytmami są najczęściej bez zna-
czenia przy przetwarzaniu małej ilości danych, ale rosną razem z nią, i to
liniowo, logarytmicznie, z kwadratem, wykładniczo itd.
W celu porównywania algorytmów pod względem ich prędkości działa-
nia, wprowadzono pojęcie złożoności obliczeniowej. Dysponując takim
pojęciem, posiadamy pewną miarę, która pozwala na porównywanie różnych
algorytmów, ocenę efektu poprawienia istniejącego algorytmu, czy wreszcie
możemy szacować czas realizacji danego zadania.
26
Test przeprowadzono specjalnie na starym komputerze, by widać było wyraźniej róż-
nice.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
154
Algorytmy i struktury danych
Złożoność obliczeniowa określa, ilu zasobów wymaga użycie danego al-
gorytmu lub jak jest ono kosztowne. Koszt ten można oczywiście mierzyć
na wiele różnych sposobów, zależnych od postawionego zadania. Stąd czas
wyrażany jest za pomocą umownych jednostek.
Rozważmy następujący przykład, mamy funkcje zmiennej całkowitej n
daną następującym wzorem:
f (n) = n
2
+ 100n + log
10
n + 1000
Dla małych wartości n ostatni składnik jest największy. Jednak wraz ze
wzrostem n maleje jego znaczenie na rzecz pozostałych. Ostatecznie, gdy
n
przekroczy wartość 100000 jego znaczenie w ogólnym wyniku jest margi-
nalne. Również pozostałe czynnik, oprócz n
2
, mają coraz mniejszy wkład.
To właśnie głównie od pierwszego składnika zależy wartość funkcji i dla
dużych n można przyjąć, że funkcja ta jest postaci
f (n) = cn
2
gdzie c jest pewną stałą.
W wyniku takiej obserwacji jak powyższa wprowadzono pewne notacje
mające na celu określenie złożoności oblicznieowej danego algorytmu. No-
tacji tych jest kilka, my przedstawimy chyba najprostsza z nich — notację
wielkie O.
Dla danej pary funkcji f i g o dodatnich wartościach rozważymy nastę-
pujące definicje.
Definicja 5.1. Notacja „wielkie O” Powiemy, że funkcja f(n) jest rzędu
O(g(n)), jeśli istnieją dodatnie liczby c i N takie, że 0 ≤ f(n) ≤ cg(n) dla
wszystkich n ≥ N.
Na przykład wyrażenie
n
2
+ 100n + log
10
n + 1000
można zapisać jako
n
2
+ 100n + O(log
10
n)
co oznacza, że część „obcięta” jest zawsze mniejsza niż pewna ustalona stała
pomnożona przez log
10
n.
Własności notacji „wielkie O”.
Własność 1 Jeśli f(n) jest O(g(n)) i g(n) jest O(h(n)), to f(n) jest O(h(n)).
Inaczej: O(O(g(n))) jest O(g(n)).
Własność 2 Jeśli f(n) jest O(h(n)) i g(n) jest O(h(n)), to f(n)+g(n) jest
O(h(n)).
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
5.7 Zadania
155
5.7
Zadania
1. Napisz funkcję do obliczania x
y
, gdzie x, y są liczbami naturalnymi,
przy czym dopuszczamy, że y może być 0. Napisz wersję iteracyjną
i rekurencyjną.
2. Dla iteracyjne wersji funkcji określonej w poprzednim zadaniu narysuj
schemat blokowy.
3. Mając poniższy schemat blokowy zamień go na zapis w pseudo-języku
programowania, zastanów się co robi ten algorytm.
Rysunek 5.9: Schemat blokowy pewnego algorytmu.
4. Napisz funkcję rekurencyjną, która realizuje algorytm wyszukiwania
połówkowego opisany w punkcie 5.4.3.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
156
Algorytmy i struktury danych
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 6
Języki programowania
Jedne języki zaprojektowano po to, aby rozwiązać problem, inne, aby
wykazać słuszność teorii.
Dennis M. Ritchie
Jeden język nie musi być koniecznie lepszy od drugiego tylko z tego
powodu, że ma cechę, której ten drugi nie posiada.
Bjarne Stroustrup
6.1
Czym jest język programowania?
Tytułowe pytanie może być postawione przez każdą osobę, która po raz
pierwszy spotyka się z pojęciem języka programowania. Istnieje na nie bar-
dzo prosta odpowiedź: język programowania jest takim sposobem zapisu al-
gorytmu, by komputer mógł go wykonać. W literaturze [Mac99] spotkamy
podobną definicję
Język programowania jest językiem, który jest przeznaczony do
wyrażania programów komputerowych oraz taki, że można w nim
wyrazić dowolny program komputerowy.
Jeśli jednak zastanowić się szerzej nad tym pojęciem, to można by posta-
wić pytanie: „Czy nie wystarczyłby język polski, czy też angielski? A jeśli
tak to po co tworzymy nowy język?”. Odpowiedź na tak postawione pytanie
jest w chwili obecnej zdecydowanie negatywna. Komputery dopiero uczą się
rozpoznawać polecenia wydawane przez człowieka, przy czym polecenia te
są wydawane za pomocą małego podzbioru słów języka naturalnego.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
158
Języki programowania
Od języka programowania wymaga się by był na tyle prosty aby kom-
puter mógł łatwo go „zrozumieć” i na tyle elastyczny, by pozwalał wyrazić
(zapisać) za jego pomocą dowolny algorytm. Zatem można zadać pytanie,
czemu istnieje tyle języków programowania, czy nie wystarczyłby jeden?
Okazuje się, że w zależności od tego co chcemy opisać, jakie zjawiska z życia
codziennego zamodelować w języku maszyny, potrzebujemy do tego innych
słów czy też innych konstrukcji językowych. Różnorodność języków pro-
gramowania prowadzi do tego, że w jednych jest łatwiej pisać bazy danych
a w innych obliczenia numeryczne. Istnieją też takie języki, które w ogóle
nie wspierają pewnych operacji i nie da się za ich pomocą zrealizować części
zadań.
Możemy zatem zadać kolejne pytanie, czy nie można stworzyć jednego
uniwersalnego języka programowania, w którym łatwo można by pisać do-
wolne programy, czy to obliczeniowe, czy też bazy danych. Niestety jak w
większości dziedzin życia, okazuje się że wszystko co uniwersalne przestaje
być optymalne i odwrotnie. A mnogość problemów dla których mają być
pisane programy wymusza często tworzenie specjalistycznych języków. Ję-
zyk uniwersalny zawierałby tak dużo słów i styli pisania, że nikt nie umiał
by się nim posługiwać. Możemy wyobrazić sobie, że konstruujemy język
naturalny w którego skład wchodzą wszystkie słowa języków nowożytnych,
czy istniałby ktoś kto nauczy się tego języka? Ponadto za tworzeniem no-
wych języków programowania przemawia fakt pojawiających się coraz to
wydajniejszych komputerów, a co za tym idzie możliwości wymyślania co-
raz nowszych narzędzi dla programistów.
Języki programowania zostały skonstruowane by stać się pomostem po-
między człowiekiem a komputerem. Pomostem pomiędzy myśleniem abs-
trakcyjnym a chłodną precyzją maszyny. Spróbujmy zastanowić się nad zda-
niami wypowiadanymi przez człowieka codziennie. Spostrzeżemy, że wiele
z tych zdań jest nie precyzyjnych, a mimo to drugi człowiek nie ma kłopotu
z ich zrozumieniem. Weźmy dla przykładu zdanie: „Proszę idź do sklepu i
kup litr mleka”. W zdaniu tym ani nie podajemy lokalizacji sklepu, ani też
nie podajemy rodzaju mleka czy sposobu jego zapakowania. Dlaczego tak
się dzieje? Osoba z nami mieszkająca z reguły wie jakie mleko najczęściej
spożywamy, również sklep wybierze dobrze sobie znany lub też najbliższy.
Zatem prośba zostanie spełniona. W przypadku komputerów musimy for-
mułować swoje polecenia bardzo precyzyjnie, gdyż można powiedzieć, że
komputer nie ma własnych przyzwyczajeń, czy też intuicji i niekoniecznie
musi się domyślać co też wydający polecenie chciał powiedzieć. Zauważmy,
że jeśli tylko trochę zmienimy powyższe zdanie: „Skocz do sklepu i kup
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
159
mleko”, stanie się ono dodatkowo niezrozumiałe poprzez dwuznaczność jaką
zawiera w sobie zwrot „skocz” (czy komputer umie podskakiwać?).
Nasze krótkie rozważania prowadzą do dwu pojęć ściśle związanych z ję-
zykami programowania: składni i semantyki.
6.1.1
Składnia i semantyka
Składnia jest to zbiór elementów języka z których buduje się zdania oraz
reguł gramatycznych według których te zdania się konstruuje, uwzględ-
niając w tym „interpunkcję”. Szczególnie ten ostatni element jest często
frustrujące dla początkujących programistów. Pytają: „A co to za róż-
nica czy stawiam tu kropkę czy nie?” Możemy jedynie zauważyć, że ma to
znaczenie również w języku codziennym. Wyobraźmy sobie dialog dwojga
osób, z których pierwsza pyta: „Ty mnie chyba nie lubisz?”, a druga od-
powiada: „Nie lubię” lub „Nie, lubię”. Fakt wystąpienia bądź pominięcia
przecinka zmienia zupełnie znaczenie zdania. Większość języków programo-
wanie posiada bardzo sztywne reguły składniowe, co może być na początku
przyczyną irytacji (bo wciąż czegoś ten komputer od nas chce). Jednak w
końcowym efekcie okazuje się dla nas korzystne, bo wykryte zostają przy-
padkowe błędy.
Semantyka odpowiada regułom znaczeniowym, czyli nadającym
znaczenie zdaniu. Mówiąc inaczej mamy zdanie napisane poprawnie gra-
matycznie, ale jego interpretacja jest inna niż chcieliśmy, ponieważ popeł-
niliśmy błąd semantyczny. Cała składnia byłaby bezwartościowa gdybyśmy
nie nadali znaczenia słowom, które ona ze sobą wiąże. Błędy semantyczne
wynikają z niewłaściwego zrozumienia przez nas znaczenia bądź konkret-
nych słów, bądź całej konstrukcji zdania, a być może po prostu przejęzy-
czenia. Powiemy do kolegi „Podaj mi książkę”, jednak się przejęzyczyliśmy
ponieważ chodziło nam o zeszyt. Jak widać nie mamy żadnych szans na
automatyczne wykrycie takiego rodzaju błędów. Objawiają się one jedynie
w niespodziewanych efektach działania programu. W językach programo-
wania dąży się do formalnej i bardzo precyzyjnej semantyki, nie może być
nie jednoznaczności jak w zdaniu „Skocz do sklepu”.
6.2
Ewolucja języków programowania
Podajemy tu krótki rys historyczny języków programowania, który ułatwi
zrozumienie ich kolejnych generacji. Przypomnijmy to co było powiedziane
we wstępie, że pierwszym programistą była Ada Augusta hrabina Lovelace,
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
160
Języki programowania
która napisała całkiem pokaźny zbiór programów na nie istniejącą maszynę
analityczną. Potem języki programowania musiały czekać na swoje ponowne
narodziny aż do połowy lat pięćdziesiątych ubiegłego wieku, kiedy to po-
wstawały pierwsze komputery elektronowe i należało zacząć je oprogramo-
wywać. Spójrzmy na przykład 6.1, który zawiera fragment programu dla
komputera IBM 650 (przykład zaczerpnięto z [Mac99]).
Przykład 6.1. Kawałek programu dla komputera IBM 650
LOC
OP
DATA
INST
COMMENTS
1107
46
1112
1061
A może użyjemy pętlę?
1061
30
0003
1019
1019
20
1023
1026
Zapamiętaj C
1026
60
8003
1033
1033
30
0003
1041
1041
20
1045
1048
Zapamiętaj B
1048
60
8003
1105
1105
30
0003
1063
1063
44
1067
1076
Czy tu wołamy operację 02?
1067
10
1020
8003
8003
69
8002
1061
Idź do podprogramu 01
Kolumna LOC zawiera numer adresu pod którym znajduje się instrukcja,
OP
zawiera kod operacji, DATA dane, INST adres instrukcji, która ma być
wykonana jako następna. Cóż . . . należy przyznać, że czytelność powyższego
programu jest przytłaczająca . . .
Na szczęście w tym samym czasie w firmie IBM Johna Backusa prowadził
badania nad stworzeniem języka wygodniejszego, czytelniejszego z przezna-
czeniem do obliczeń matematycznych
1
. I tak w listopadzie 1954 roku została
ogłoszona pierwsza specyfikacja języka FORTRAN, nazwa jest akronimem
słów the IBM Mathematical FORmula TRANslating system. Spójrzmy na
przykładowy program 6.2 zapisany w tym języku, a dokładnie w jego pierw-
szej wersji.
1
W tamtych czasach właściwie można było mówić o dwu typowych wykorzystaniach
komputerów: obliczeniach i przetwarzaniu danych. Gry i rozrywka musiały poczekać
jeszcze wiele lat na swoją kolej.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
161
Przykład 6.2. Program w języku FORTRAN I.
DIMENSION DTA(900)
SUM = 0.0
READ 10, N
10
FORMAT(I3)
DO 20 I = 1, N
READ 30, DTA(I)
30
FORMAT(F10.6)
IF (DTA(I)) 25, 20, 20
25
DTA(I) = -DTA(I)
20
CONTINUE
DO 40 I = 1, N
SUM = SUM + DTA(I)
40
CONTINUE
AVG = SUM/FLOAT(N)
PRINT 50, AVG
50
FORMAT(1H, F10.6)
STOP
Bez zbędnego wgłębiania się w znaczenie kolejnych linii a posiadając
choć minimalne doświadczenie w jakimkolwiek języku programowania, można
zauważyć, że program ten jest dużo czytelniejszy od poprzedniego. Język
ten okazał się na tyle dobry, że przechodził kolejne udoskonalenia. W 1962
komitet ANSI zaczął pracę nad jego standaryzacją i w 1966 roku gotowa
jest specyfikacja języka FORTRAN IV. Popularność tego języka wciąż ro-
śnie, coraz więcej firm tworzy własne implementacje. I tak w 1977 roku
pojawia się kolejny chyba najpopularniejszy standard nazwany FORTRAN
77. Faktycznie język ten jest rozwijany do dziś i istnieje obecnie standard
FORTRAN 90, ale nie tak popularny jak jego poprzednik.
Szybko się przekonano, że i ten język nie był wystarczający, głównie
dlatego, że był to język przeznaczony praktycznie wyłącznie do obliczeń
numerycznych i tylko w takich zastosowaniach się sprawdzał. Co więcej,
czytelność zapisanych w nim programów wciąż pozostawiała wiele do życze-
nia. W latach sześćdziesiątych pewnym antidotum na brak czytelności stał
się język Algol-60. Wprowadzono w nim pętlę for oraz możliwość dzielenia
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
162
Języki programowania
programu na podprocedury, które można było nazwać i odwoływać się do
nich przez tę nazwę. Co prawda FORTRAN również zawierał podprogramy
(procedury), ale wtedy w Algolu-60 było to znacznie bardziej uporządko-
wane. Przykładowy program w języku Algol-60 prezentuje listing 6.3.
Przykład 6.3. Program w języku Algol-60
begin
real x, y;
integer N, i;
real procedure cosh(x); real x;
begin
cosh := (exp(x)+exp(-x))/2;
end
begin
Read Int (N);
for i := 1 step 1 until N do
begin
x := i/N;
y := cosh(x);
Print Real (y);
end;
end
end
Ale i ten język nie przyjął się na długo na rynku programistycznym,
można jedynie odnotować fakt, że powstał jeszcze jeden jego standard Algol-
68. Niemniej jednak jest to bardzo ważny język, gdyż był on wzorem dla
wielu innych takich jak PL/I, Pascal, CPL czy Simula 67.
W 1968 roku Niklaus Wirth rozpoczął pracę nad nowym językiem pod
nazwą Pascal. Ponieważ wcześniej Wirth uczestniczył w pracach nad Algo-
lem, więc świetnie znał zalety i wady tegoż języka. W opracowaniu Pascala
skorzystał z przejrzystej i czytelnej składni Algolu, jednak zwrócił uwagę, że
struktury danych w tym języku wystarczały wyłącznie do działań arytme-
tycznych zatem postanowił obejść tę niedogodność wprowadzając bardziej
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
163
elastyczne typy. Dodał do języka typy wyliczeniowe, dzięki czemu były
możliwe deklaracje zmiennych jak poniżej
type
dzien_tyg = (pon, wt, sro, czw, pia, sob, nie );
Zapis powyższy oznacza definicję typu wyliczeniowego o nazwie dzien tyg,
który to typ może przyjąć wartości jedynie spośród zadeklarowanych nazw
po prawej stronie. Wprowadzenie typów wyliczeniowych wpłynęło na ogra-
niczeni pewnej klasy błędów popełnianych przez programistów. Zauważmy,
że gdyby typ dzien tyg był np. liczbą całkowitą to można zmiennej tego
typu przypisać by wartość 10, która nie odpowiadałaby żadnemu z dni.
Następnie Wirth wzbogacił język o możliwość wprowadzenie ograniczeń
na typy wbudowane, czyli konstruowania tzw. podtypów, poniższy przykład
ilustruje takie ograniczenie
var
dzien_miesiaca: 1 .. 31;
I znów mamy ilustrację pewnego wsparcia dla porządnego pisania pro-
gramów i zapobiegania podobnym błędom jak poprzednio. Do zmiennej
dzien miesiaca
nie przypiszemy wartości mniejszych od 1 i większych od
31. Dalej język Pascal zawierał możliwość definiowania typu zbiorowego
i , co więcej, sprawdzania czy coś należy do pewnego zbioru czy nie. Wszyst-
kie te cechy spowodowały, że Pascal stał się językiem niezwykle przejrzystym
i czytelnym co spowodowało, że szybko przyjął się jako język dydaktyczny.
Z resztą sam Wirth pisząc go robił to z myślą właśnie o aspekcie dydaktycz-
nym. Ze względu na swoje cechy w tym na łatwość jego nauki stał on się
również bardzo chętnie wykorzystywanym językiem przez świerzo upieczo-
nych programistów. Firma Borland widząc duże zainteresowanie wypuściła
na rynek bardzo dobre środowiska programistyczne w oparciu o Pascala,
wpierw Turbo Pascal (zawierał wiele rozszerzeń w stosunku do oryginału),
a potem nawet środowiska typu RAD (ang. Rapid Application Develop-
ment) pod nazwą Delphi
2
. Przykładowy program w języku Pascal ilustruje
wydruk 6.4.
Przykład 6.4. Program w języku Pascal
2
Ale to już były lata dziewięćdziesiąte ubiegłego wieku.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
164
Języki programowania
program prg1 (input, output);
var
x, y: real;
N, i: integer;
function cosh( x: real): real;
begin
cosh := (exp(x)+exp(-x))/2;
end;
begin
readln(N);
for i := 1 to N do
begin
x := i/N;
y := cosh(x);
writeln(y);
end;
end.
Wróćmy do lat siedemdziesiątych ubiegłego wieku. W informatyce na-
stąpił kilka lat wcześniej „kryzys oprogramowania”. W największym skrócie
można ten okres określić jako moment w którym zrozumiano, że ówczesne
techniki programistyczne i metodologie tworzenia programów nie wystar-
czają do tworzenia dużych i złożonych systemów przy jednoczesnym za-
chowaniu niezawodności, jakości oraz akceptowalnego czasu realizacji tych
projektów. Z jednej strony spowodowało to narodziny nowej dziedziny in-
formatyki — inżynierii oprogramowania, której celem było badanie pro-
blematyki tworzenia oprogramowani i konstruowanie nowych metod postę-
powania. A z drugiej strony zrodziły się pomysły na ulepszenie języków
programowania. Kolejną ewolucję języków prześledzimy na przykładzie po-
wstania języka ADA.
W 1971 i 1972 roku D. L. Parnas zaproponował kilka reguł określają-
cych w jaki sposób dzielić program na kilka mniejszych modułów. Jedną
z tych reguł było umieszczanie w jednym module informacji i funkcji, które
służą pewnej określonej i zamkniętej pojęciowo cesze. Dzięki temu, jeśli
w przyszłości trzeba było poprawić coś w działaniu tego modułu, czy nawet
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
165
w całości go przebudować nie wpływało to (a raczej wpływać nie powinno)
na resztę systemu. Cecha ta nosi miano ukrywania informacji i jest do-
skonale znana dzisiejszym programistom piszącym w językach obiektowych.
W tym samym okresie, dokładniej w połowie 1970 roku Departament
Obrony USA określa potrzebę stworzenia (bądź wybrania istniejącego) ję-
zyka programowania dla systemów osadzonych (ang. embedded systems),
oraz krytycznych aplikacji do celów wojskowych. Chodziło o wybranie ta-
kiego języka, który umożliwiał by pisanie oprogramowania dla systemów
obronnych, czy systemów sterowania bronią. Oczywistą sprawą jest, że ta-
kie systemy powinny być niezawodne, a co za tym idzie narzędzia w których
będzie pisane oprogramowanie muszą wspierać tę niezawodność. Kolejnym
czynnikiem skłaniającym do wyboru jednego języka był fakt, że w tam-
tych czasach istniało około 400 różnych języków i ich dialektów służących.
Zatem koszty przenoszenia i wspierania takiej różnorodności narzędzi były
ogromne. W 1975 roku powołano grupę Higher-Order Language Working
Group (HOLWG), której zadaniem było stworzenie jednego języka do oma-
wianych celów. Co więcej w 1976 roku oszacowano, że stworzenie takiego
języka pozwoli zaoszczędzić 12-17 miliardów dolarów w przeciągu następ-
nych 17 lat.
Język o którym mowa powinien posiadać kilka kluczowych cech, głów-
nymi z nich była prostota (ang. simplicity) oraz czytelność (ang. re-
adability). Poza tymi ogólnikami zakładono, że język ten będzie wspierał
ukrywanie informacji, programowanie współbieżne, oraz posiadał wsparcie
do weryfikacji pisanych w nim programów.
W 1977 roku HOLWG przeanalizowała 26 języków programowania i sfor-
mułowała wnioski, że żaden z nich nie odpowiada postawionym wymaga-
niom. Następnie spośród tych języków metodą eliminacji starano wybrać
się język najbardziej zbliżony do ideału. Zwycięzcą okazał się język opraco-
wany przez grupę CII-Honeywell-Bull, której przewodniczył Jean Ichbiah.
W 1979 roku HOLWG nadała temu językowi nazwę ADA. Język ten stał się
standardem do celów wojskowych w styczniu 1983 roku, zaś w czerwcu 1984
został wybrany jako obowiązkowy i jedyny do wszystkich krytycznych zasto-
sowań
3
. Celem tego języka, poza samymi mechanizmami dla programistów,
było obniżenie kosztów tworzenie aplikacji poprzez zwiększenie przenoszal-
ności oraz wsparcia dla powtórnego użycia komponentów (ang. reuse). Stąd
też zabroniono budowania wszelkich pod lub nadzbiorów języka, czy wła-
snych klonów, miał być jeden standard bez odstępstw. Niewątpliwie ten
krok, choć może wydawać się bardzo drastyczny spowodował dużą stabilność
3
Jako standard ISO został zatwierdzony w 1987 roku.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
166
Języki programowania
środowiska pracy. Zauważmy, że przy omawianu Pascala nadmieniliśmy, że
firma Borland stworzyła własny dialekt, który był nieprzenośny.
W języku ADA można wyróżnić cztery podstawowe konstrukcje języ-
kowe: deklaracje, wyrażenia, instrukcje i typy. Wyrażenia i instrukcje
są praktycznie odpowiednikami tego co było znane wcześniej np. w Pascalu.
Typy również są podobne do znanych wcześniej, z tą różnicą, że programista
ma większą swobodę w definicji własnych typów. Największa zmiana jaką
wprowadzono w ADA znajduje się w deklaracjach, i tu wyróżnia się pięć ich
typów: obiekty, typy, podprogramy, pakiety, oraz zadania. Deklara-
cje obiektów pozwalały na określanie funkcji i zmiennych
4
. Podprogramy
przypominały deklarację funkcji i procedur, jednak dodatkowo można było
deklarować operatory np. + czy -.
Największą innowacją było prowadzenie pakietów i zadań. Obie te
konstrukcje pozwalały na definicję modułów, czyli zamkniętych funkcjonal-
nie zbiorów. Zadanie posiadało jednak dodatkową własność, a mianowicie
można je było wykonywać w sposób równoległy bądź rozproszony i istniały
w języku jako takim mechanizmy wspierające takie programowanie
5
. Na
sam koniec poniższy przykład prezentuje pakiet napisany w języku ADA,
zawierający procedurę wyszukiwania binarnego w tablicy liczb zmiennoprze-
cinkowych.
Przykład 6.5. Fragment programu (pakiet) w języku Ada
package Table is
type Table is array (Integer range < >) of Float;
procedure BinarySearch(T: Table, X: Float,
Position: out Integer, Found: out Boolean) is
subtype Index is Integer range T’First..T’Last;
Lower : Index := T’First;
Upper : Index := T’Last;
Middle : Index := (Lower + Upper) / 2;
begin
4
Zwróćmy uwagę, że nie ma to nic wspólnego z obiektowością
5
Warto zwrócić uwagę, że to język dostarczał takie mechanizmy, np. w C czy C++
można pisać i w sposób współbieżny i rozproszony, jednak w przypadku tych języków
programista musi sam zadbać o wiele rzeczy (ADA dbała o nie niejako za programistę).
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
167
loop
if T(Middle) = X then
Location := Middle;
Found := True;
return;
elsif Upper < Lower then
Found := False;
return;
elsif T(Middle) > X then
Upper := Middle - 1;
else
Lower := Middle + 1;
end if;
Middle := (Lower + Upper) / 2;
end loop;
end BinarySearch;
end Tables;
Jednak nie tylko ADA powstała jako język wspierający pracę nad złożo-
nymi projektami — inną grupą języków były języki zorientowane obiektowo
(ang. Object-Oriented Language (OOL)). Jako przyczynę do ich powstania
można wskazać, podobnie jak przy programowaniu strukturalnym, kolejny
wzrost wielkości tworzonych programów. Przede wszystkim skończyła się
era dużych programów pisanych przez jedną osobę. Skoro nad programem
pracowało kilka a nawet kilkanaście osób należało dostarczyć im narzędzi
wspierających pracę grupową i języków wspomagających pisanie złożonych
systemów. Z drugiej strony, coraz więcej powstających systemów, odzwier-
ciedlało bardzo złożone procesy bądź zjawiska ze świata rzeczywistego. Za-
istniała potrzeba odzwierciedlanie rzeczywistych obiektów jak statki czy
samoloty w modelu języka programowania.
Języki zorientowane obiektowo — czyli wspierające pisanie w zgodzie
z metodologią obiektową — musiały posiadać kilka cech, które teraz omó-
wimy. Powinny umożliwiać definicję nowych typów. Ten nowym typ definio-
wano za pomocą klasy, której konkretne instancje nazywano obiektami —
stąd nazwa języki obiektowe. Co więcej należało zapewnić by te nowe typy
(klasy) były traktowane jak typy wbudowane. Dzięki temu programista defi-
niując typ (klasę) reprezentujący macierz mógł dla niej zdefiniować operację
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
168
Języki programowania
np. dodawania i operacja ta w sensie zapisu wyglądała jak dodawanie dwu
zmiennych całkowitych. W rzeczywistości typ w językach obiektowych był
czymś więcej niż typem w językach strukturalnych
6
. W nowym znaczeniu
typ był zbiorem obiektów i operacji, których wykonanie na nim było zawsze
poprawne. Dla podkreślenie pewnej odmienności pojęcia typu w językach
obiektowych wprowadzona pojęcie klasy i tak zaczęto nazywać te nowe typy.
Spójrzmy na poniższy fragment programu (zapisany w języku C++):
// definicja dwu zmiennych typu całkowitego
// jest to typ wbudowany w język
int x = 1, y = 3;
// zsumowanie dwu zmiennych i zapisanie wyniku w trzeciej
int z = x + y;
// Definicja zmiennych reprezentujacych macierze
// a następnie ich zsumowanie
Matrix a, b;
c = a + b;
Dzięki definicji typów była możliwą ścisła kontrola typów, to znaczy,
że do zmiennej reprezentującej liczbę całkowitą nie można było przypisać
samochodu. Jednak nie wszystkie języki wspierają ten mechanizm, mimo
jego niepodważalnej siły. Przykładem języków o ścisłej typizacji — ścisłym
sprawdzaniu poprawności typów — jest C++.
Klasy miały przede wszystkim umożliwiać oddzielania interfejsu od im-
plementacji. Interfejsem nazwiemy wszystko to co jest publiczne, czyli da-
jące się wykorzystać przez użytkowników klasy. Implementacja jest spo-
sobem realizacji funkcji klasy, jej jakby wnętrzem, które nie jest widzialne
spoza niej samej a przez to nie jest narażone na przypadkową zmianę. Jako
przykład rozważmy samochów, pojazd ten posiada kierownicę, pedały i drą-
żek zmiany biegów
7
. Wszystkie te elementy są składnikami jego interfejsu
przez który kierujący jest w stanie sterować pojazdem. Jednak samochód
posiada również silnik, skrzynie biegów i wiele innych, jednak większość
użytkowników nie musi do nich zaglądać, a już z pewnością nie jest to zale-
cane w czasie jazdy.
6
W Pascalu również programista mógł zdefiniować własny typ danych.
7
Oczywiście posiada znacznie więcej elementów, ale tyle wystarcza do tego przykładu.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
169
Następnie języki obiektowe powinny wspierać mechanizm dziedzicze-
nia. Mechanizm ten zapewnia możliwość definiowania nowej klasy na pod-
stawie istniejącej. W takiej sytuacji nowa klasa dziedziczy wszystko ze swo-
jego przodka
8
. Jest to bardzo silna cecha, która daje wsparcie do pisania
programów „przez powtórne użycie” (ang. software reuse). Zatem mając
wcześniej napisany program, możemy wykorzystać część jego klas, ewentu-
alnie rozszerzając ich funkcjonalność poprzez dziedziczenie. Takie postępo-
wanie oszczędza czas piszącego, ale co ważniejsze korzystamy z fragmentów
kodu, który jest przetestowany, a zatem mamy mniej miejsc do popełnienia
błędów.
W chwili obecnej najczęściej kojarzonymi językami wspierającymi taki
sposób programowania są C++ czy Java, jednak nie one były pierwsze.
W 1971 roku w firmie Xerox rozpoczęto prace nad stworzeniem graficznego
środowiska pracy o nazwie Dynabook. Do programowania tego środowi-
ska wybrano język Smalltalk-72. Język ten został stworzony przez Alana
Key-a we współpracy z wieloma osobami w tym, co ciekawe, psychologami.
W tamtych czasach jeszcze nie dostrzegano wielu problemów, które znamy
obecnie, jednak zdawano sobie sprawę, że wkrótce projekty informatyczne
będą coraz większe, programów zaś mają używać zwykli użytkownicy nie
zaś informatyczni guru. Stąd zaistniała potrzeba tworzenia graficznych in-
terfejsów użytkownika i do takiego celu był projektowany Smalltalk. Został
on oparty o różne wcześniejsze idee w tym o LOGO. Autorom Smalltalk-a
zależało by był on jak najprostszy i intuicyjny w tworzeniu interfejsu.
Zupełnie inny kierunek rozwoju został wyznaczony przez programo-
wanie funkcjonalne (ang. functional programming) oraz programowa-
nie w logice (ang. logic programming). Obie te metodologie powstały
do wsparcia programowania sztucznej inteligencji (ang. artificial intelli-
gence). Można najogólniej powiedzieć, że miały stanowić wsparcie do prze-
twarzania związków pomiędzy bardzo dużą ilością danych (patrz 1.4.8).
Jako przykład rozwoju języka funkcjonalnego podamy krótką historię
języka LISP (ang. List-Processing Language). Został on stworzony w końcu
lat pięćdziesiątych ubiegłego wieku w głównej mierze przez John’a McCar-
thy’ego. Pierwsza implementacja tego języka pojawiła się na komputerze
IBM 704, na nim to właśnie odbyła się demonstracja prototypu w 1960 roku.
Język ten zdobył szerokie uznanie i stał się szybko najpowszechniej używa-
8
Choć słowo dziedziczenie kojarzy się w naturalny sposób z relacją rodzic-dziecko, to
jednak tej analogii nie wolno posuwać aż tak daleko. Dziedzicząc pewne cechy od obojga
rodziców jesteśmy niejako konglomeratem różnych cech i to nie wszystkich. Podczas gdy
przy operacji tej w sensie języków obiektowych dziedziczone jest wszystko.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
170
Języki programowania
nem językiem do programowanie sztucznej inteligencji posiadającym swoje
implementacje również na mikrokomputery. Co więcej, zdarzały się imple-
mentacje nie związane ze sztuczną inteligencją, czego przykładem może być
wykorzystanie LISP-u do programowanie komend użytkownika w programie
AutoCAD.
Rdzeniem języków tego typu jest funkcja. Co ciekawe wynikiem działa-
nia konkretnej funkcji jest inna funkcja. Nazwa tych języków wynika właśnie
z faktu, że zajmują się one przetwarzaniem funkcji. Jest to zupełnie inne
jakościowo podejście niż w przypadku wcześniej omawianych języków. W
języku LISP, który omawiamy cecha ta jest wyraźnie widoczna podobnie
jak to, że operuje on na listach. Dla przykładu funkcja posiada listę argu-
mentów oraz w wyniku działania zwraca listę wartości. Można zapytać a
co z funkcją, która wyświetla komunikat na ekranie? Przecież nie musi ona
niczego zwracać. Nie szkodzi, zwróci ona listę wyników, która będzie pu-
sta. Podobnie z funkcją, która nie potrzebuje argumentów, lista ich będzie
również pusta.
Zanim pokażemy przykład fragmentów programów w języku LISP mu-
simy wyjaśnić pojęcie polskiej notacji. Notacja ta została zaproponowana
przez polskiego logika Jana Łukasiewicza. Cechą charakterystyczną tej no-
tacji jest umieszczanie operatora przed operandami, stąd też czasami jest
ona zwana notacją prefiksową. Rozważmy prosty przykład, w matematyce
działanie sumowanie dwu argumentów zapisujemy
2 + 3
podczas, gdy w polskiej notacji, to samo wyrażenie będzie miało postać
(+ 2 3)
Zatem co oznacza zapis
(* (+ 2 3) 7)
oczywiście (2 + 3) ∗ 7. I trochę bardziej skomplikowany przykład, znany jest
nam wszystkim następujący wzór
−b +
√
b
2
− 4ac
2a
Jego zapis w notacji polskiej będzie miał postać
(/ (+ (-b) (sqrt (- (exp b 2) (* 4 a c)))) (* 2 a ))
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.2 Ewolucja języków programowania
171
Być może na początku ta notacja wydaje się dziwna i nienaturalna jednak
w wielu przypadkach jest znacznie wygodniejsza dla maszyny. Ponieważ
naczelną własnością języka LISP jest przetwarzanie list za pomocą funk-
cji, stąd właśnie polska notacja wydaje się być naturalna do zapisywania
jego poleceń. Rozważmy prosty warunek zapisany w poznanym dotychczas
strukturalnym języku programowania
9
if x = y then f(x)
else g(x)
endif
A teraz spróbujmy go zapisać w LISP-ie
(cond
((eq x y) (f x))
(t (g x))
)
Jak widać już sam „wygląd” takiego programu jest zupełnie inny, być może
mniej czytelny dla osób przyzwyczajonych do zapisu „klasycznego”
10
.
W chwili obecnej LISP doczekał się wielu implementacji i tak np. w Unix-
owym edytorze Emacs LISP służy do definicji poleceń, a nawet istnieje mo-
duł do popularnego serwera WWW jakim jest Apache, który pozwala na
pisanie aplikacji Internetowych w tym właśnie języku.
Przejdźmy teraz do programowania w logice. Jak to było powiedziane
wcześniej motywacją do powstania tego typu języków były również bada-
nia nad sztuczna inteligencja. Jednak ten sposób programowania jest czymś
więcej niż suchym narzędziem, jest wyznacznikiem pewnego nowego sposobu
myślenia a mianowicie programowanie bezproceduralnego. Zauważmy,
że programowanie proceduralne, czy to strukturalne czy funkcjonalne, sku-
piało się na tym jak daną rzecz należy wykonać. W programowaniu w
logice skupiamy się na tym co należy zrobić. Być może jeszcze wydaje się
to niejasne, wszak można powiedzieć: przecież zanim będę wiedział „jak”
muszę wpierw odpowiedzieć „co” będę robił. To prawda, ale w progra-
mowaniu w logice wystarczy odpowiedź na pierwsze pytanie. Spróbujemy
to wytłumaczyć na przykładzie 6.6, który jest napisany w języku Prolog
najpopularniejszym z tego typu języków.
9
Jest to przykład w pewnym „wymyślonym” języku.
10
Słowo „klasyczny” zostało tu użyte wyłącznie jako przenośnia. Nie można mówić
o językach strukturalnych jako klasycznych, gdyż jak to wynika z dat wcale nie były
wcześniejsze od funkcjonalnych. Mamy w tym miejscu na myśli tylko fakt, że z reguły
strukturalne języki są powszechniej znane.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
172
Języki programowania
Przykład 6.6. Prosty program napisany w Prologu
rodzic(X, Y) :- ojciec(X, Y).
rodzic(X, Y) :- matka(X, Y).
malzenstwo(X, Y) :- ojciec(X, Z), matka(Y, T), Z = T.
malzenstwo(X, Y) :- matka(X, Z), ojciec(Y, T), Z = T.
przodek(X, Y) :- rodzic(X ,Y).
rodzenstwo(X, Y) :- matka(M, X), matka(M, Y),
ojciec(O, X), ojciec(O, Y), X \= Y.
ojciec(marek, jurek).
ojciec(marek, zosia).
matka(jola, jurek).
matka(jola, zosia).
W językach tych definiuje się relacje wiążące elementy, oraz określa pe-
wien zasób wiedzy początkowej. Nie inaczej jest w powyższym przykładzie,
określamy relację rodzic, mówiącą o tym, że X jest rodzicem Y, jeśli X jest
ojcem Y (pierwsza linijka) lub X jest matką Y (druga linijka). W efek-
cie mamy powiedziane co to znaczy „być czyimś rodzicem”. Następnie
w podobny sposób mamy powiedziane, co to jest relacja małżeństwa, by-
cia przodkiem, czy też rodzeństwa. Na koniec musimy wprowadzić pewien
zbiór wiedzy, są to linie zaczynające się od słów matka i ojciec. Ostatecznie
otrzymujemy pewną bazę wiedzy o niewielkiej rodzinie, teraz jeśli zapy-
tamy system czy np. jola i marek są małżeństwem otrzymamy odpowiedź
twierdzącą, mimo iż nie podaliśmy tego w sposób efektywny a jedynie na
podstawie relacji z innymi elementami. Dzięki takiemu podejściu widać,
że języki te nadają się do pisania systemów wspomagających wnioskowanie
i w konsekwencji do tzw. baz wiedzy.
Sam język Prolog, użyty w powyższym przykładzie został wymyślony
w 1970 roku przez Alain-a Colmerauer-a oraz Philippe-a Roussel-a. Oni
to wraz ze swoją grupą prowadzili badania na Uniwersytecie w Marsylii
dotyczące sztucznej inteligencji. Stworzyli tam pierwszą specyfikację tego
języka i rozwijali go dalej.
Jak widać historia języków programowanie jest bardzo bogata nie tylko
w różnego rodzaju dialekty tego samego języka, lecz przede wszystkim w
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.3 Klasyfikacja języków programowania
173
różne koncepcje, które miały służyć rozwiązywaniu konkretnych problemów
zaczerpniętych z życia.
6.3
Klasyfikacja języków programowania
Klasyfikacji języków programowania można dokonać na różne sposoby, lub
mówiąc inaczej patrząc z różnych poziomów, lub przez inne pryzmaty. Z jed-
nej strony można dzielić języki ze względu na metodologię programowania
jaką wspierają i wtedy wyróżnia się zasadniczo: programowanie sekwen-
cyjne, programowanie strukturalne, programowanie obiektowe, programo-
wanie funkcjonalne, programowanie w logice. Z drugiej strony można mówić
o kolejnych generacjach języków programowania, i wtedy wyróżnia się pięć
generacji, które omówione są w dalszej części punktu (zob. 6.3.2).
6.3.1
Podział według metodologii programowania
Szczegółowe omówienie języków pod tym kątem, na tle rozwoju myśli pro-
gramistycznej, można znaleźć w punkcie (6.2), teraz dokonamy jedynie pod-
sumowania wcześniejszych informacji.
Programowanie sekwencyjne
Konstrukcja tego typu języków odzwierciedlała prawie dokładnie język ma-
szyny na jakiej one działały. Były to często programy zapisane w asem-
blerze danego procesora. Nawet jeśli były to języki wyższego poziomu, jak
np. FORTRAN IV, to typy danych jakie w nim występowały również sta-
nowiły odzwierciedlenie tego co mógł reprezentować procesor. Zatem języki
te posiadały wyłącznie typy liczbowe ewentualnie znakowe, jednak nie było
możliwości definicji własnych typów danych. Taka cecha została wprowa-
dzona dopiero w poźniejszych językach np. Pascalu.
Programowanie strukturalne
W latach sześćdziesiątych ubiegłego wieku zaczęto zwracać większą uwagę
na sposób pisania, czyli metodologię. Zauważono, że nie wystarczy jeden czy
dwu zręcznych programistów. Coraz częściej programy były większe zatem
trudniejsze do opanowania i w konsekwencji człowiek popełniał więcej błę-
dów. Zaistniała potrzeba zaprojektowania takich języków programowania,
który wprowadzałyby pewien porządek w programie, były wsparciem dla
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
174
Języki programowania
programisty a nie balastem. Konsekwencją tych spostrzeżeń było pojawie-
nie się prac omawiających programowanie strukturalne (ang. structured
programming). Sam termin programowanie strukturalne jest niejako wypa-
czony w odniesieniu do jego pierwotnego znaczenia, w oryginale autorom
chodziło o podkreślenie, że programowanie to niejako wymusza prawidłową
strukturę programu. Jednak z nazwy można by sądzić, że odnosi się to
do pisania wyłącznie struktur. Należy podkreślić, że nazwa ta miała wy-
łącznie wskazywać na dobry styl pisania, co często prowadziło nawet do
skrajności mówiącej o zakazie używania w takim programowania instrukcji
skoku GOTO
11
. Rzeczywiście przesadna ilość instrukcji GOTO w progra-
mie zaciemnia a często wręcz uniemożliwia analizę kodu, jednak są miejsca
w których zastosowanie tej instrukcji jest czytelne i upraszające program.
W związku z pojawieniem się nowej tendencji w programowaniu musiały
pojawić się języki wspierające tan paradygmat postępowania. Do pierw-
szych języków strukturalnych należy zaliczyć Pascal, zaprojektowany przez
Niklausa Wirtha [Wir71b]. Język Pascal był zaprojektowany by wspoma-
gać dydaktyków programowania, tak by mogli nauczać dobrych nawyków
przyszłych programistów. Zatem musiał spełniać następujące założenia:
• struktura języka i jego konstrukcje powinny być przejrzyste i skłania-
jące do porządnego pisania,
• powinien być językiem na tyle obszernym (uniwersalnym) by można
w nim opisać szeroką klasę algorytmów,
• opis języka powinien być ścisły, czytelny i prosty,
• język ten powinien być łatwy do zaimplementowania, czyli stworzenia
kompilatora dla niego.
Język Pascal wspierał metodologię tworzenia programów zaproponowaną
również przez Wirtha, znaną pod nazwą metody zstępującej (ang. step-
wise refinement) [Wir71a]. W metodzie tej pracę rozpoczyna się od naszki-
cowania szkieletu całego programu, a następnie właśnie w sposób zstępu-
jący rozpisuje się coraz to drobniejsze fragmenty, aż na końcu dochodzi się
do funkcji i struktur danych. Oba te elementy implementuje się w języku
strukturalnym, który właśnie wspierał zarówno tworzenie struktur danych
definiowanych przez programistę, jak i definiowanie funkcji czy też proce-
dur. Bardzo przystępny i zwięzły opis pierwszej wersji języka Pascal można
znaleźć w [MI86].
11
Nawet utarło się swego czasu powiedzenie, że „umiejętności programisty są odwrotnie
proporcjonalne do ilości użytych przez niego instrukcji GOTO w programie”.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.3 Klasyfikacja języków programowania
175
Programowanie obiektowe
Programowanie obiektowe zaczęto rozwijać, na dużą skalę, w latach
osiemdziesiątych XX wieku. Języki zorientowane obiektowo — czyli wspie-
rające pisanie w zgodzie z metodologią obiektową, musiały posiadać nastę-
pujące cechy: definicję własnych typów, tworzenie klas, ukrywanie infor-
macji, dziedziczenie. Szczególnie dziedziczenie było silnym mechanizmem,
dzięki któremu można było wykorzystywać kod napisany wcześniej, ewentu-
alnie rozbudowując go tylko o nowe cechy. W chwili obecnej istnieje bardzo
dużo języków zorientowanych obiektowo, można tu wymienić: C++, Java,
Python, PHP. Co ciekawe C++ jest językiem w którym można pisać za-
równo strukturalnie jak i obiektowo, to znaczy nie ma konieczności używa-
nia klas. Dla kontrastu w Javie nie ma takiej możliwości i nawet najkrótszy
program musi mieć co najmniej jeden obiekt.
Programowanie funkcjonalne
Jest to rodzaj programowania, które jest skoncentrowane wokół funkcji.
W większości tego typu języków programowania wszystko jest funkcją, wręcz
cały program jest to prostu wywołanie funkcji i jej wykonanie. Zastosowanie
tych języków to głównie sztuczna inteligencja, ale jak to było opisane wcze-
śniej bynajmniej nie do tego zostały ograniczone. Okazuje się, że świetnie
się sprawdzają do programowania komend użytkownika w złożonych pro-
gramach. Innym zastosowaniem jest wspomaganie dowodzenia twierdzeń
matematycznych i systemy wnioskujące. Z takiech źródeł wyrósł nie oma-
wiany wcześniej język Standard ML, który również jest obecnie szeroko wy-
korzystywany.
Programowanie w logice
Podobnie jak programowanie funkcjonalne tak i programowanie w logice
zostało stworzone do wspomagania procesów wnioskowania i baz wiedzy.
Paradygmat tego programowania różni się od poprzednich, gdyż koncentruje
się na problemie jako taki — czyli pyta „co” jest do zrobienia, nie zaś na
samym sposobie realizacji. Niewątpliwie najpopularniejszym środowiskiem
do programowania w taki sposób jest Prolog, choć spotyka się też inne
systemy, w tym systemy specjalistyczne czy też przemysłowe, pisane do
realizacji specjalistycznych zastosowań.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
176
Języki programowania
6.3.2
Generacje języków programowania
W literaturze ([Mac99]) można spotkać podział języków programowania na
pięć generacji.
Języki pierwszej generacji
Struktura takich języków odpowiadała budowie komputerów lat 60-tych, co
jest zrozumiałe o tyle, że w tamtych czasach istniały wyłącznie duże ma-
szyny i było zalewie kilka firm je produkujących. Wszelkie instrukcje ste-
rujące programem były ściśle związane z odpowiadającymi im instrukcjami
w maszynie. Dla przykładu instrukcje warunkowe nie mogły być zagnież-
dżone. Struktura języka była sekwencyjna, oparta wyłącznie na instrukcji
skoku GOTO, przy pomocy której sterowano przebiegiem programu. Na-
wet w językach w których pojawiały się podprocedury (podprogramy), nie
można było stosować rekurencyjnych ich wywołań. Podobnie typy danych
były ściśle związane z maszyną, występowały w danym języku tylko takie,
które miały odzwierciedlenie w implementacji w maszynie. Struktury da-
nych nie mogły być zagnieżdżane. Nie przywiązywano uwagi do kwestii
przenośności kodu na inne maszyny. Nie występowało dynamiczne zarzą-
dzanie pamięcią. Program zapisywany w tych językach do tego stopnia był
silnie związany z maszyną, że często etykiety kolejnych linii były numerami
komórek pamięci w których te rozkazy się znajdowały (patrz przykład 6.1).
Przykładem języka programowanie pierwszej generacji jest FORTRAN
IV.
Języki drugiej generacji
Pojawiają się w tych językach pewne uogólnienia typów danych, między in-
nymi możliwość definiowania tablic z dolnym indeksem innym niż 1, oraz
tablic dynamicznych. Zwykle w tych językach pojawia się ścisła kontrola
typów oraz typy wbudowane, wciąż nie ma typów definiowanych przez użyt-
kownika. Struktura programu przypomina strukturę hierarchiczną i blo-
kową, co powoduje mniejszą potrzebę użycia instrukcji GOTO. Pojawia się
możliwość dynamicznego zarządzania pamięcią. Wiele z języków posiada
słowa kluczowe i słowa zastrzeżone.
Przykładem języka programowania drugiej generacji jest Algol-60.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.4 Kompilacja vs. interpretacja
177
Języki trzeciej generacji
Struktura języka trzeciej generacji stała się bardziej elastyczna i wygod-
niejsza do korzystania, przykładem może być pętla for. Dodano również
konstrukcje, które są wygodniejsze z punktu widzenia programisty, przykła-
dem może być instrukcja wielokrotnego wyboru case. Pojawia się możli-
wość definiowania własnych struktur danych przez programistę. Wszystko
to powoduje ogólną orientację języka w kierunku aplikacji a nie maszyny na
której jest implementowany.
Przykładem języka programowania trzeciej generacji jest Pascal.
Języki czwartej generacji
Jedną z głównych cech tych języków jest abstrakcja danych, wsparcie dla
oddzielania informacji publicznej (interfejsu) od prywatnej (jej realizacji,
implementacji). Języki te pozwalają często na tworzenie uogólnionych mo-
dułów (np. język ADA). Próbuje się pogodzić elastyczność z prostotą zapisu
informacji. Drugą ważną cechą jest wsparcie dla programowania współbież-
nego, zatem języki te posiadają mechanizmy synchronizacji procesów czy
komunikacji pomiędzy nimi. Wprowadza się mechanizmy ochrony danych,
oraz dodawany jest mechanizm obsługi wyjątków.
Przykładami takich języków mogą być: C++, ADA, Java.
Języki piątej generacji
Nikt jeszcze nie wie dokładnie jak te języki będą wyglądały, ani jaka na-
czelna idea będzie im przyświecała. Wiele doświadczeń już zdobyto, ale
wiele kierunków jeszcze nie jest rozpoznanych. Można powiedzieć tylko
o pewnych kierunkach i trendach. Są nimi języki zorientowane obiektowo,
języki zorientowane funkcyjnie, języki zorientowane logicznie. Słowo zo-
rientowane mówi tylko o pewnym paradygmacie, wokół którego następuje
rozbudowa języka.
6.4
Kompilacja vs. interpretacja
Program zapisany w języku programowania ma postać pliku tekstowego i w
tej formie nazywany jest kodem źródłowym. Aby kod źródłowy mógł
być wykonany musi zostać przetłumaczony na program wykonywalny,
zapisany w języku maszynowym (jedyny język zrozumiały przez procesor
zob. 3.4.5). Istnieją programy tłumaczące programy przez nas napisane
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
178
Języki programowania
na język danej maszyny. Ze względu na sposób i charakter pracy mówimy
głównie o kompilatorach i interpreterach.
Proces, który przetwarza program zapisany w języku programowania,
zwany również programem źródłowym lub kodem źródłowym, na ję-
zyk maszynowy nazywamy kompilacją. Niestety kompilacją nazywany jest
również jest proces tłumaczenia na język adresów symbolicznych lub
inaczej asembler. Z kolei dla odróżnienia proces tłumaczenia programu
zapisanego w asemblerze na kod maszynowy nazywany jest często dla wy-
różnienia asemblacją. Otrzymany w wyniku kompilacji program w kodzie
maszynowym nazywamy programem wykonywalnym. W przypadku
kompilacji musimy posiadać program, który będzie tłumaczył nasz kod źró-
dłowy na kod maszynowy, czy też na asembler. Program ten — kompilator
— charakteryzuje się tym, że z reguły umie przetłumaczyć tylko jeden ję-
zyk programowania, oraz tylko na jedną platformę sprzętową i w ramach
jednego systemu operacyjnego. Zatem jeśli posiadamy kompilator języka C
na platformę Intel, pod kontrolą systemu Linux, to nie będziemy mogli przy
jego pomocy skompilować programu napisanego w języku ADA. Co więcej
program napisany w języku C i przetłumaczony na kod maszynowy za po-
mocą tego kompilatora nie będzie mógł być wykonany w systemie Windows,
nawet jeśli będzie to ten sam komputer
12
.
Co prawda cały proces tłumaczenia programu nazywamy kompilacją,
jednak faktycznie składa się on z dwu czynności: kompilacji i łączenia.
Kompilacja jest procesem zamiany programu źródłowego na plik binarny,
który zawiera program w kodzie maszynowym — plik ten zwany jest plikiem
obiektu
13
(ang. object file). Jednak plik taki bardzo rzadko jest finalnym
programem, wynika to z faktu, że często pisząc programy używa się odwołań
do funkcji, które zawarte są w bibliotekach. Biblioteki są zbiorami skom-
pilowanych funkcji, które mogą być używane wielokrotne. Zauważmy, że
pisząc jakikolwiek program będziemy odwoływali się do funkcji (procedury)
wypisującej komunikaty na ekranie. Zatem warto taką funkcje napisać raz,
a potem wielokrotnie ją tylko wywoływać a nie pisać za każdym razem od
nowa. Ponieważ nie jesteśmy jedynymi programistani na świecie, często
to producent kompilatora dostarcza takich popularnych funkcji w postaci
bibliotek — zwanych również bibliotekami systemowymi. Cały proces
kompilacji jest zilustrowany na rysunku 6.4.
Po zakończonym procesie kompilacji mamy zbiór plików obiektów oraz
biblioteki. W tym momencie należy posklejać to wszystko w jeden wykony-
12
Oczywiście jest możliwość emulacji jednego systemu operacyjnego w ramach innego.
13
Nie ma to nic wspólnego z programowaniem obiektowym!
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.4 Kompilacja vs. interpretacja
179
walny program. Proces wykonujący tę czynność nazywany jest łączeniem
lub konsolidacją
14
, zaś program wykonujący go zwany jest konsolida-
torem. Wynikiem łączenia jest kompletny program zawierający wszystko
to co jest niezbędne do jego wykonania w ramach konkretnej platformy
sprzętowo-systemowej. Opisany proces łączenia zwany jest również łą-
czeniem statycznym. Drugą możliwością łączenie jest łączenie dyna-
miczne. W tym wypadku, program końcowy jest wyłącznie informowany
o obecności pewnych funkcji w bibliotekach, zaś wywoływanie tych funk-
cji spoczywa na systemie operacyjnym. Funkcje systemowe umieszczane są
wtedy w bibliotekach dzielonych
15
.
plik obiektowy 1
plik obiektowy 2
Edycja
(dowolny edytor tekstowy)
{plik na dysku}
{plik na dysku}
Kompilacja
plik obiektowy 1
plik wynikowy (program)
plik obiektowy 2
!"#$&% '$)(+*&,% -./". 0
{plik na dysku}
{plik na dysku}
pliki biblioteczne
plik biblioteczny
plik biblioteczny
Pliki tekstowe
1
32456 57867 649:;7< >=6?85
1
@2456 @A 87B=6?85=C@D =6;7@ 7E57F<GH
Pliki binarne
867 649:;7
kod maszynowy
Rysunek 6.1: Ilustracja procesu kompilacji.
Drugim sposobem uruchamiania programów zapisanych w pewnym ję-
14
Czasami określa się go spolszczając angielskie słowo linking i nazywa się go linkowa-
niem, zaś program go wykonujący linkerem.
15
Są one znane doskonale użytkownikom systemów Windows pod nazwą bibliotek DLL
(ang. Dynamic Linking Library).
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
180
Języki programowania
zyku programowania, jest ich interpretacja. W celu uruchomienia pro-
gramu interpretowanego, musimy posiadać dla niego środowisko urucho-
mieniowe zwane interpreterem. Interpreter jest podobnie jak kompilator
programem, który umożliwia nam uruchomienie naszego programu. Różnicą
jest to, że interpreter nie produkuje programu wykonywalnego w postaci
pliku wykonywalnego, a tłumaczy nasz program „w locie” na program ma-
szynowy i wykonuje go na bieżąco. Przypomina to wykonywanie skryptów
powłoki (lub plików wsadowych w przypadku systemu MS-DOS), stąd też
inna nazwa tego typu języków — języki skryptowe. Charakterystyką tych
języków jest to, że posiadają środowisko do interpretacji na wiele platform
sprzętowych i systemowych, a co za tym idzie przenośność programów w
nich napisanych jest ogromna. Środowiska uruchomieniowe (interpretery)
posiadają również zbiory bibliotek systemowych, które zawierają funkcje
najczęściej stosowane lub napisane przez kogoś innego. W przypadku tych
języków nie występuje proces łączenia w takiej formie jak przy kompila-
cji, funkcje biblioteczne są na bieżąco wyciągane z bibliotek i wywoływane.
Ilustracja procesu interpretacji znajduje się na rysunku 6.4.
Przykładem języka skryptowego jest PERL, który posiada swoje środo-
wisko do interpretacji na ponad dwadzieścia platform.
Zasadnicza różnica pomiędzy językami interpretowanymi a kompilowa-
nymi polega na tym, że w jednym przypadku użytkownik końcowy otrzy-
muje program w postaci kodu źródłowego (języki interpretowane), a w dru-
gim otrzymuje program w kodzie maszynowym (języki kompilowane). Po-
nieważ kod źródłowy należy interpretować w czasie wykonania zatem są
one wolniejsze od programów skompilowanych. Również niekorzystny jest
fakt, że przypadkowy użytkownik, często laik, otrzymuje postać źródłową
naszego programu. Istnieje teoretyczna możliwość, że przez przypadek ją
uszkodzi zaglądając do środka programu jakimkolwiek edytorem tekstowym
i przez ciekawość zmieniając np. plus na minus
16
. Niepodważalną zaś zaletą
języków interpretowanych jest ogromna przenośność kodu, co w przypadku
programu wykonywalnego prawie nie występuje, za wyjątkiem sytuacji wy-
korzystywania emulatorów
17
.
Z uwagi na przenośność i uniwersalność języki skryptowe wykorzystuje
się do pisane różnego rodzaju programów instalacyjnych, bądź skryptów
administracyjnych. Cieszą się one dużym zainteresowaniem przy automa-
tyzacji stron WWW i tu jako przykład można podać język PHP. Z kolei
16
Podkreślamy czysto teoretyczną możliwość, gdyż w praktyce użytkownik nie ma po-
wodu tam zaglądać.
17
Programy „udające” inny procesor, bądź inny system operacyjny, bądź jedno i drugie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.4 Kompilacja vs. interpretacja
181
języki kompilowane stosuje się tam gdzie najważniejsza jest wydajność
18
.
Rysunek 6.2: Ilustracja procesu interpretacji.
4
Edycja
(dowolny edytor tekstowy)
{plik na dysku}
{plik na dysku}
wykonanie programu
Interpretacja
pliki biblioteczne
plik biblioteczny
plik biblioteczny
plik biblioteczny
Próbą pogodzenie obu powyższych rozwiązań było wprowadzenie ję-
zyków prekompilowanych. W takiej sytuacji programista po napisaniu
programu dokonuje procesu wstępnej kompilacji — prekompilacji swojego
programu, efektem tej czynności jest plik w postaci kodu pośredniego, czę-
sto zwanego Byte-code lub krócej B-Code. W efekcie użytkownik otrzymuje
tę właśnie postać wstępnie skompilowaną, a następnie uruchamia program
na pewnej maszynie wirtualnej (ang. virtual machine) lub krótko VM.
Maszyna ta w dalszym ciągu interpretuje program i wykonuje go na konkret-
nej platformie sprzętowo-systemowej. Jak widać jest to połączenie procesów
kompilacji i interpretacji, dzięki czemu oddajemy w ręce użytkownika nie-
jako finalny program, a jednocześnie jest on przenośny wszędzie i będzie
funkcjonował tam gdzie posiadamy VM dla tego języka. Wstępna kompi-
lacja, przyśpiesza późniejszą interpretację, zatem języki te są szybsze od
interpretowanych, oczywiście wolniejsze od kompilowanych. Funkcje z bi-
bliotek podobnie jak w przypadku języków interpretowanych są dołączone
18
Faktem jest, że często komercyjne firmy programistyczne, mówią o zagrożeniu kra-
dzieży kodu źródłowego, jeśli jest on dostępny. Jednak doświadczony programista do
takiej argumentacji będzie podchodził ostrożnie. Ma on świadomość, że prześledzenie,
zrozumienie a następnie przepisania na własne potrzeby dużego programu, który ma parę
milonów linii kodu źródłowego jest bardzo trudne i czasochłonne. Osoba która to zrobi,
zrozumie ideę tego programu, zatem może go napisać sama od nowa, i wcale nie musi go
kraść.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
182
Języki programowania
w trakcie wykonywania. Jednak w przypadku tych języków, dość często
producent maszyny wirtualnej dostarcza te biblioteki nie w postaci kodu
pośredniego, a w postaci skompilowanej na konkretną platformę. W takiej
sytuacji funkcje te działają szybciej niż te napisane przez programistę. Przy-
kładem takiego języka programowania jest JAVA. Co ciekawe w przypadku
tego języka, firmy które tworzą maszynę wirtualną, wzbogacają ją coraz
częściej w technologię JIT (ang. Just In Time compilation). Technologia
ta zapewnia kompilację z kodu pośredniego do kodu wykonywalnego, dla
danej platformy sprzętowo-systemowej, w trakcie pierwszego uruchomienia
programu. Dzięki czemu każde następne wywołanie programu pobiera już tę
skompilowaną, a zatem szybszą, wersję. Proces prekompilacji i wykonania
na maszynie wirtualnej ilustruje rysunek 6.4.
Rysunek 6.3: Ilustracja procesu prekompilacji i wykonania na maszynie
wirtualnej.
plik obiektowy 1
plik obiektowy 2
Edycja
(dowolny edytor tekstowy)
{plik na dysku}
{plik na dysku}
Pre−kompilacja
plik obiektowy 1
plik obiektowy 2
Wykonanie na maszynie wirtualnej
{plik na dysku}
{plik na dysku}
pliki biblioteczne
plik biblioteczny
plik biblioteczny
Pliki tekstowe
! "#$ %
Pliki binarne,
zwykle kod maszynowy,
&'
( ) *$
Maszyna wirtualna (VM)
+
(, )
&
- !!, )!).
&
/102
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.5 Elementy teorii języków formalnych
183
6.5
Elementy teorii języków formalnych
W tym punkcie podamy podstawowe pojęcie, którymi posługują się twórcy
języków do ich opisu. Jednak spróbujemy przede wszystkim podać pewne
intuicje związane z tymi pojęciami, celem lepszego zrozumienia złożoności
zagadnienia. Szersze omówienie tych zagadnień wprowadzana jest z reguły
na przedmiotach związanych z teorią automatów i języków formalnych.
6.5.1
Gramatyka
W celu formalnego zdefiniowania języka wprowadza się następujące pojęcia
alfabetu — pewien zbiór symboli, musi być on skończony i niepusty, zwy-
kle oznaczany przez symbol Σ;
litery — dowolny element alfabetu;
słowa — skończony ciąg liter alfabetu, spotyka się również nazwę słowo
nad alfabetem;
słownika — zbiór wszystkich słów utworzonych nad alfabetem, zwykle
oznaczany poprzez dodanie symbolu gwiazdki do symbolu alfabetu,
np. Σ
∗
;
języka — dowolny podzbiór słownika.
Zauważmy, że jeśli posługujemy się językiem naturalnym np. polskim,
to słowa tego języka składają się z liter oraz pewnych dodatkowych znaków,
zatem mamy alfabet. Na bazie tego alfabetu budowane są słowa danego ję-
zyka. Jeśli na bazie danego alfabetu zbudujemy zbiór wszystkich możliwych
słów to otrzymamy słownik. Zauważmy jednak, ze jest to zbiór wszystkich
słów, czyli np. słowa „aalgifk”, które nie ma określonego znaczenia w języku
polskim. Następnie językiem nazwiemy pewien podzbiór słów ze słownika,
czyli odrzucimy te słowa, które nie posiadają znaczenia.
W końcu lat pięćdziesiątych Noam Chomsky i John Backus wprowadzili
pojęcie gramatyki formalnej. Co więcej, wprowadzili pojęcie gramatyki
kontekstowej i gramatyki bezkontekstowej. Przekłada się to bezpo-
średnio na języki. Otóż jeśli dla danego języka istnieje gramatyka kon-
tekstowa, która go generuje to nazwiemy go językiem kontekstowym,
podobnie rzecz się ma dla języka bezkontekstowego. Znów odwołując
się do pewnej intuicji można powiedzieć, że jeśli w danym języku mamy
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
184
Języki programowania
dowolne zdanie i znaczenie jego słów jest jasne w oderwaniu od reszty zda-
nia, czyli od kontekstu, to taki język będzie bezkontekstowy. Analogicznie
dla języka kontekstowego. Niestety trudno na pierwszy rzut oka wyobrazić
sobie język naturalny
19
bezkontekstowy i faktycznie nie ma takich języków.
6.5.2
Notacja BNF
Gramatyki formalne, zasygnalizowane powyżej, nie stanowią jedynej możli-
wej formy opisu składni, lecz również stanowią podstawę dla innych koncep-
cji. Do innych metod zliczamy specjalne języki opisu składni. Języki służące
do opisu składni języków formalnych nazywamy metajęzykami. Najbardziej
rozpowszechnionym metajęzykiem jest notacja BNF (Bachus-Naur-Form).
W notacji BNF wprowadza się pewne oznaczenia i skróty do opisu
składni. Przy użyciu tego metajęzyka, opis składni przedstawiony jest w po-
staci definicji, nazywanych formułami metajęzykowymi, postaci L ::= R,
gdzie L — nazwa zmiennej metajęzykowej, R — zbiór wartości, które może
przyjmować zmienna L, symbol ::= oznacza „równe z definicji”. Nazwa
zmiennej metajęzykowej, symbol nieterminalny, składa się z pary nawiasów
hi, między którymi występuje dowolny ciąg znaków. Ciąg R jest wylicze-
niem jednej lub więcej wartości zwykle oddzielanych znakiem ”. Dodatkowo
wprowadza się symbole {} oraz [], służą one do określenia odpowiednio po-
wtórzenia oraz elementu opcjonalnego . . . i tu zwykle następuje drobna kon-
sternacja. Przed czytaniem czegokolwiek w notacji BNF należy się upewnić
co autor rozumie pod tymi pojęciami. Możliwe wartości to odpowiednio po-
wtórzenie zero lub więcej razy, powtórzenie raz i więcej, ale może zdarzyć się
coś innego. Dlatego zawsze na początku warto dobrze zinterpretować zna-
czenie tych symboli. Na przykład w [Fe98] w dodatku opisującym składnię
jest napisane:
{} -- dowolny ciąg powtórzeń
[] -- element opcjonalny
\\ -- wybór jednego z elementów składowych
|
-- alternatywa
::= -- reguła produkcji
... -- składnik identyczny
Przykład 6.7. Fragment składni Pascala zapisany przy pomocy
notacji BNF.
19
Mamy tu na myśli polski, angielski ...
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
6.5 Elementy teorii języków formalnych
185
<litera>::=A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<cyfra>::=0|1|2|3|4|5|6|7|8|9
<znak_liczby>::=+|-
<litera_lub_cyfra>::=<litera>|<cyfra>
<identyfikator>::=<litera>{<litera_lub_cyfra>}
<ciag_cyfr>::=<cyfra>{<cyfra>}
<liczba_całkowita_bez_znaku>::=<ciąg_cyfr>
6.5.3
Notacja przy użyciu diagramów składni
Inną formą prezentacji gramatyki języka są diagramy składni. Notacja
ta, zaproponowana przez Niklausa Wirtha, nosi także nazwę notacji skrzyn-
kowej. W notacji tej każdy element składni jest prezentowany za pomocą
pewnego symbolu graficznego, zaś połączenie pomiędzy nimi za pomocą
strzałek. Rysunek 6.5.3 ilustruje fragment składni języka Pascal, podany w
poprzednim punkcie za pomocą notacji BNF, zapisany w notacji skrzynko-
wej.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
186
Języki programowania
Rysunek 6.4: Fragment składni Pascala zapisany przy pomocy diagramów
składni.
litera
z
b
a
A
Y
Z
cyfra
0
9
znak_liczby
+
−
litera_lub_cyfra
litera
cyfra
cyfra
liczba_calkowita_bez_znaku
identyfikator
litera
litera_lub_cyfra
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 7
System operacyjny
Prawie każdy
1
komputer posiada system operacyjny, jednak zwyczajny użyt-
kownik często wcale nie zdaje sobie sprawy z jego funkcjonowania. Niewi-
doczny dla nie wtajemniczonych, nie zawsze doceniany przez tych, którzy
coś o nim wiedzą, sprawia, że komputer staje się użytecznym i przyjaznym
narzędziem pracy. Komputer jaki jest dziś znany, to „uniwersalna ma-
szynka” do wszystkiego. Urządzenie, któremu przypisuje się wręcz jakąś
magiczną moc. Można zauważyć tendencję dodawania wyrazu „kompu-
terowy” w celu podnoszenia rangi danego przedmiotu; chyba tylko w ten
sposób uzasadnić można hasła reklamowe typu „Komputerowe haftowanie”.
Bezspornym faktem pozostaje jednak, iż komputery są obecne we wszyst-
kich dziedzinach ludzkiej działalności. Stało się to głównie dzięki uczynieniu
ich bardzo przyjaznymi dla zwykłego użytkownika i zapewnieniu zdolności
do spełniania powierzanych im zadań w sposób efektywny (i nierzadko efek-
towny). Zwykle ta efektywność jest zapewniania przez dobry i sprawny
system operacyjny.
System operacyjny, to pierwszy program z jakim stykamy się zwykle
zaraz po włączeniu komputera. Można usłyszeć nieraz: „Czekam, aż za-
ładują się Windowsy”, ale czym są te „Windowsy”. „No jak to, czym?
— pada odpowiedź — Windowsy to te ikonki, ta tapeta i kursor myszki.
Jak klikniesz tu, to się uruchomi edytor tekstu, jak tu, to gra a jak tu,
to . . . ”. Jest to wypowiedź użytkownika, który nie zamierza zagłębiać się
w tajniki informatyki. Dla informatyka jest to oczywiście niedopuszczalne
uproszczenie.
1
Patrz punkt 7.9
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
188
System operacyjny
7.1
Zadania realizowane przez system operacyjny
Zasadniczym celem systemów komputerowych jest wykonywanie programów
użytkownika mających za zadanie ułatwić rozwiązanie pewnych zagadnień i
problemów. Wraz z konstruowaniem odpowiedniego sprzętu, powstaje także
oprogramowanie, które ma być na nim uruchamiane. Wiele z tworzonych
programów wymagać będzie pewnych wspólnych operacji, jak na przykład
dostęp do urządzeń wejścia/wyjścia, takich jak drukarka czy monitor. Jeśli
komputer będzie docelowo posiadał wiele programów komunikujących się
ze światem zewnętrznym przez wejścia/wyjścia (a tak jest w dzisiejszych
komputerach), to ekonomicznie jest wyodrębnić funkcje realizujące komu-
nikację w postaci pewnej wspólnej, dla nich wszystkich, „biblioteki” (jak
się przekonamy dalej — zwykle jest to składnik systemu operacyjnego).
Wspólne funkcje odpowiedzialne za sterowanie i przydzielanie zasobów, to
oszczędność nie tylko miejsca w pamięci (wszak każdy program je zajmuje),
ale również oszczędność czasu, gdyż nie trzeba dwa razy pisać tych samych
operacji.
Poniżej podano krótką charakteryzację głównych zadań stawianych sys-
temom operacyjnym:
Podsystem zarządzania procesami:
• tworzenie i usuwanie procesów;
• wstrzymywanie i wznawianie procesów;
• dostarczanie mechanizmów synchronizacji i komunikacji proce-
sów;
Podsystem zarządzania pamięcią operacyjną:
• przydzielanie i zwalnianie obszarów pamięci w zależności od za-
potrzebowania zgłaszanego przez procesy;
• przechowywanie informacji o aktualnie zajętych częściach pa-
mięci (ich rozmiar, położenie, proces, któremu są przypisane);
• decydowanie o tym, który proces ma być załadowany do obszarów
zwolnionych;
Podsystem zarządzania pamięcią masową:
• planowanie przydziałów obszarów pamięci dyskowej;
• zarządzanie obszarami wolnymi;
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.2 System operacyjny a architektura komputera
189
• dostarczanie logicznych jednostek składowania danych — plików
i katalogów, oraz zarządzanie nimi;
Podsystem wejścia/wyjścia:
• dostarczenie programów obsługi poszczególnych urządzeń;
• izolowanie użytkownika od specyfiki urządzeń — dostęp do urzą-
dzenia odbywa się nie bezpośrednio, ale za pomocą dobrze zdefi-
niowanego interfejsu;
Podsystem ochrony:
• identyfikacja użytkownika;
• ochrona zasobów systemowych przed nieautoryzowanym dostę-
pem;
• ustanowienie i kontrolowanie wzajemnych relacji pomiędzy użyt-
kownikiem, czynnościami jakie wykonuje i programami jakie uru-
chamia a przyznanymi prawami dostępu;
• zarządzanie rozliczeniem — sprawowanie kontroli nad stopniem
wykorzystania systemu przez poszczególnych użytkowników;
Podsystem interpretacji poleceń:
• dostarczenie mechanizmów interaktywnego dostępu do funkcji
systemu operacyjnego dotyczącego między innymi nadzorowania
wykonywania procesów, obsługi wejścia/wyjścia czy ochrony za-
sobów.
Istnienie i działanie wszystkich tych podsystemów, to odpowiedź na
główne zadanie stawiane przed systemem operacyjnym: umożliwić efek-
tywną pracę pozwalającą w maksymalnym stopniu wykorzystać zasoby
2
ja-
kimi dysponuje system komputerowy.
7.2
System operacyjny a architektura komputera
Własności systemu operacyjnego wpływają na obraz i możliwości komputera
w podobnym, jeśli nie większym stopniu, co jego fizyczna architektura (pro-
cesor, pamięć, ...). Tym drugim czynnikiem świadczącym o możliwościach
2
Przez zasoby rozumiemy tutaj wszystkie urządzenia i podzespoły wchodzące w skład
systemu komputerowego a więc procesor, pamięci, ale także drukarki, skanery, itp.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
190
System operacyjny
komputera jest oczywiście architektura fizyczna komputera (procesor, pa-
mięć, układy towarzyszące — patrz 3.3). Jednym z zadań stawianym dzisiej-
szym systemom operacyjnym jest zapewnienie w jak największym stopniu
izolacji od fizycznych urządzeń przy jednoczesnym zachowaniu łatwości i in-
tuicyjności ich obsługi — np. proces nagrywania danych na dysk, dyskietkę,
dysk magnetooptyczny, czy CD powinien być maksymalnie ujednolicony, o
prostocie nie wspominając.
Dobry przykład ilustrujący poprzednie zdanie stanowi system opera-
cyjny o nazwie Linux. Dostępny jest on na wiele różnych platform sprzę-
towych różniących się często istotnie pod względem ich budowy fizycznej.
Użytkownik wcale jednak nie musi zdawać sobie z tego sprawy, gdyż wszyst-
kie polecenia i czynności bez względu na rzeczywistą konfigurację sprzętową
dają ten sam, lub możliwie najbardziej zbliżony, efekt. Dlatego też myśląc
o systemie komputerowym z punktu widzenia zwykłego użytkownika wyod-
rębnia się zwykle trzy warstwy pojęciowe (rysunek 7.1):
• Programy użytkowe i udostępniane przez nie możliwości manipulacji
i przetwarzania danych.
• System operacyjny, który pośredniczy pomiędzy elementami z war-
stwy poprzedniej i następnej.
• Sprzęt komputerowy, który dzięki systemowi operacyjnemu wystarczy,
jeśli użytkownik wie jakiego typu są zainstalowane urządzenia. Nie
musimy nic wiedzieć na temat ich faktycznego sposobu pracy.
Znajomość architektury komputera zaczyna być istotna dopiero, gdy
ktoś samodzielnie zamierza napisać system operacyjny. Może się wówczas
okazać, że w niektórych przypadkach realizacja pewnych postulatów sta-
wianych przed systemami operacyjnymi jest szczególnie łatwa (lub trudna)
właśnie ze względu na konkretną konstrukcję fizyczną danego komputera.
7.3
Klasyfikacja systemów operacyjnych
Systemy operacyjne można sklasyfikować ze względu na pewne cechy ich
budowy, lub też ze względu na ich przeznaczenie. Poniżej przedstawiono
podział ze względu na ich budowę:
Jednoużytkownikowe, jednozadaniowe — Tego typu systemy umożli-
wiają efektywne wykonywanie tylko jednego programu przez jednego
użytkownika. Przykładem systemu tej klasy jest DOS.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.3 Klasyfikacja systemów operacyjnych
191
SYSTEM OPERACYJNY
U¯YTKOWNICY
SPRZÊT
Arkusz kalkulacyjny
Baza danych
Edytor tekstu
OPROGRAMOWANIE
Rysunek 7.1: Umiejscowienie Systemu Operacyjnego w systemie kompute-
rowym.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
192
System operacyjny
Jednoużytkownikowe, wielozadaniowe — Systemy operacyjne należące
do tej grupy umożliwiają pojedyńczemu użytkownikowi wykonywanie
równocześnie kilku programów. Na przykład pracując na kompute-
rze z systemem Windows 95 mamy możliwość jednoczesnego pisania
tekstu w edytorze, słuchania plików muzycznych oraz drukowania ob-
razka z programu graficznego.
Wieloużytkownikowe — Systemy te pozwalają na równoczesną pracę
wielu różnych użytkowników. Z punktu widzenia pojedynczej osoby,
zachowują się jak wielozadaniowe systemy jednoużytkownikowe. Do
tej grupy należą np. systemy wywodzące się z rodziny Unixa.
Wśród systemów operacyjnych należy wyróżnić jeszcze dwie grupy, które
ze względu na specyficzny charakter pracy trudno zakwalifikować do jednej z
wyżej wymienionych grup, są to systemy czasu rzeczywistego i systemy
rozproszone.
Systemy czasu rzeczywistego są systemami o ściśle zdefiniowanych
i określonych czasach realizacji konkretnych operacji. System gwarantuje,
że zrealizuje pewną operację w założonym przedziale czasu w całości albo
wcale. Jeśli z jakiś powodów nie uda się jej wykonać w tym terminie, zo-
stanie wysłana wiadomość o tym fakcie, co daje szansę na podjęcie innych
procedur postępowania. Można powiedzieć, że w tych systemach popraw-
ność działań nie zależy tylko od ich poprawności w sensie prawidłowych wy-
ników, ale także od czasu, w którym udało się je przeprowadzić (bądź nie).
Przykładem z życia codziennego może być spóźnione przybycie na dworzec
kolejowy — co prawda przybyliśmy, zatem zadanie zostało wykonane, ale
niestety pociąg odjechał. Osiągnięcie terminowości realizacji zadań wymaga
maksymalnego ograniczenia wszelkich możliwych opóźnień jakie powstają w
systemie w związku z realizacją programów. Dlatego też systemy czasu rze-
czywistego pozbawione są wielu rozwiązań spotykanych w innych nowocze-
snych systemach operacyjnych. W szczególności, systemy rygorystycznego
czasu rzeczywistego
3
(ang. hard real-time system) pozostają w sprzeczno-
ści z koncepcją systemów wielozadaniowych. Jako przykład systemu czasu
rzeczywistego posłużyć może QNX.
Systemy rozproszone nadzorują pracę wielu różnych systemów kom-
puterowych traktując je jak jeden duży komputer. Do najważniejszych po-
wodów tworzenia takich systemów należą:
3
Inną odmianą systemów czasu rzeczywistego są systemy łagodne (ang. soft real-time
system), w których to zakłada się jedynie, że zadanie mające priorytet zadania czasu
rzeczywistego zostanie obsłużone przed innymi zadaniami.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.4 Realizacja zadań
193
Podział zasobów — Daje możliwość wspólnego użytkowania pewnych za-
sobów w taki sposób jak byśmy byli w ich fizycznym posiadaniu.
Dzięki temu możemy na przykład wydrukować pewne dane mimo, że
drukarka stoi w innym pomieszczeniu. (Oczywiście można to również
osiągnąć przy udziale klasycznej sieci komputerowej)
Podział obciążenia — W sytuacji, gdy pewien system komputerowy w
danej chwili jest mocno obciążony pracą, część zadań, bez ingeren-
cji użytkownika, przenoszona jest na inny, gdzie wykonuje się jak w
systemie pierwotnym.
Zapewnienie niezawodności — W przypadku wystąpienia awarii, pew-
nego stanowiska zadania realizowane przez nie przejmują pozostałe.
Dzieje się to w sposób niezauważalny dla użytkownika.
Zapewnienie komunikacji — Wymiana informacji stanowi jedno z naj-
istotniejszych zagadnień naszych czasów. Jednolity system daje użyt-
kownikom dużą możliwość przesyłania plików, wiadomości czy prowa-
dzenia videokonferencji.
System Amoeba (zob. 7.10.1 opracowany przez Andrew Tanenbaum’a,
to jeden z najczęściej podawanych, jako wzorzec, przykładów systemów tej
rodziny.
7.4
Realizacja zadań
Przypomnijmy, że działanie komputera to nieprzerwane wykonywanie róż-
nych instrukcji. Instrukcje te stanowią przetłumaczony na język maszyny
sposób rozwiązania jakiegoś zagadnienia. Ciąg tych instrukcji realizujący
zadanie nazywany jest programem. Gdy procesor rozpocznie wykonywa-
nie instrukcji składających się na program, mówi się o procesie. Z każdym
procesem wiążą się pewne dodatkowe informacje, które niezbędne są dla
prawidłowego przebiegu wykonania programu. Między innymi są to:
1. Informacja o następnej instrukcji, która zostanie pobrana do wyko-
nania przez procesor po obecnie przetwarzanej. Wskazuje ją licznik
rozkazów będący komórką pamięci przechowującą adres następnej
instrukcji.
2. Stan rejestrów procesora, zawierających najistotniejsze informacje
dotyczące aktualnego przebiegu wykonywania instrukcji.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
194
System operacyjny
Tworzenie
procesu
GOTOWY
Zaszeregowanie
Wywłaszczenie
AKTYWNY
procesu
WSTRZYMANY
Wywołanie funkcji O.S.
Zamówienie zasobu
Rysunek 7.2: Stany procesu i przejścia pomiędzy nimi.
3. Stan pamięci i urządzeń wejścia/wyjścia. Przechowywane będą infor-
macje o obszarach pamięci zajętych przez proces, a także realizowa-
nych operacjach wejścia/wyjścia, przydzielonych urządzeń itp.
4. Stan procesu; każdy proces znajduje się w jednym z trzech stanów
(rysunek 7.2)
4
.
• aktywny — są wykonywane instrukcje;
• gotowy — proces czeka na rozpoczęcie wykonania; ma przydzie-
lone wszystkie zasoby oprócz procesora;
• wstrzymany — proces czeka na wystąpienie jakiegoś zdarzenia,
na przykład zakończenia operacji wejścia/wyjścia.
Należy zwrócić uwagę na fakt, że w stanie aktywnym w każdej chwili
może znajdować się co najwyżej tyle procesów ile procesorów jest w da-
nym systemie. Nic jednak nie stoi na przeszkodzie, aby liczba procesów
gotowych była większa. Również liczba procesów wstrzymanych nie jest
(przynajmniej teoretycznie) ograniczona. Wymienione powyżej elementy
jednoznacznie określają proces oraz stan w jakim się on w danym momen-
cie znajduje i są niezbędne do jego prawidłowego wykonania. Dopóki system
komputerowy realizuje tylko jeden konkretny program (przyjmijmy, że tylko
jeden proces — ale pamiętajmy, że tak być nie musi!), dane te pozostają cały
czas aktualne, bo tylko jeden proces jest aktywny. Jednakże w przypadku
wielozadaniowych systemów wykonywanie tylko jednego jest sprzeczne z ich
ideą. Co więcej założenie, że następny program możemy zacząć wykonywać
dopiero z chwilą zakończenia poprzedniego to źródło potencjalnych prze-
stojów i również w większości sytuacji przeczy to idei wielozadaniowości
4
W bardziej złożonych systemach może być więcej stanów, a także ich definicja może
być inna.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.4 Realizacja zadań
195
a)
CPU
I/O
P1
P1
P1
b)
CPU
I/O
P2
P2
P2
P2
c)
CPU
I/O
P1
P1
P1
P2
P2
P2
P2
d)
CPU
I/O
P1
P1
P1
P2
P2
P2
P2
Rysunek 7.3: Wykorzystanie procesora przez dwa procesy.
Wykorzystanie procesora przez dwa procesy a) i b) w środowisku
jednozadaniowym c) i wielozadaniowym d).
(mogłoby to sprawdzić się jedynie wtedy, kiedy działanie programu byłoby
bardzo krótkie, co oczywiście jest nie realne). Ponadto prawie zawsze za-
chodzi konieczność odwołania się procesu do urządzeń wejścia/wyjścia w
celu pobrania lub zapisania danych, i zwykle do zakończenia takiej operacji
proces pozostaje wstrzymany; procesor w tym czasie nie robi nic. Rysunek
7.3 jest bardzo uproszczoną ilustracją sytuacji, gdy mamy dwa procesy A
(rysunek 7.3 a) i B (rysunek 7.3 b) działające w środowisku systemu opera-
cyjnego, gdzie mogą być one wykonywane jeden po drugim i tylko tak. Na
proces A składają się następujące części:
• obliczenia — trwające 3 jednostki czasu (TU, ang. Time Unit),
• operacje we/wy — 6 TU,
• ponownie obliczeń — 2 TU.
Proces B składa się z:
• obliczenia — 5 TU,
• operacje we/wy — 2 TU,
• obliczenia — 2 TU,
• operacje we/wy — 2 TU.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
196
System operacyjny
Łączny czas wykonania obu procesów to 22 TU (rysunek 7.3 c)) co daje
wykorzystanie procesora w 54%.
Jeśli procesy te będą wykonywane w środowisku wielozadaniowym to
w takiej sytuacji procesor nie będzie bezczynny w czasie realizacji zadań
we/wy. Daje to dobre efekty — schematycznie przedstawiono to na rysunku
7.3 d (łączny czas wykonania 15 TU, wykorzystanie procesora 80%).
Oczywiście należy pamiętać, że powyższa sytuacja jest wielkim uprosz-
czeniem rzeczywistości, a pominięto w niej między innymi:
• czas potrzebny na przełączanie się pomiędzy jednym a drugim proce-
sem,
• czas potrzebny dla systemu operacyjnego na nadzorowanie procesów,
• założono, że operacje wejścia/wyjścia nie potrzebują w ogóle udziału
procesora, co nigdy nie jest prawdą.
W omawianej sytuacji rodzi się potrzeba funkcjonowania mechanizmów,
które umożliwiałyby przełączanie miedzy procesami. Przełączanie, rozu-
miane tutaj jako ustawienie wszystkich niezbędnych struktur danych zwią-
zanych z procesem na odpowiednie wartości i spowodowanie, że procesor
rozpocznie realizację instrukcji związanych z innym programem, wybranym
na podstawie pewnych założeń spośród oczekujących na wykonanie. Gdy
tylko stanie się to możliwe, procesor powróci do poprzedniego programu.
Zadanie to realizuje się właśnie poprzez system operacyjny. W swej naj-
prostszej postaci odpowiada on za umieszczanie innych programów w pa-
mięci, rozpoczęcie i nadzorowanie ich wykonania, przesyłanie i odbieranie
danych.
7.5
W kierunku systemów wielozadaniowych
Przedstawiony na końcu poprzedniego punktu model pracy systemu ope-
racyjnego, czyli „zdolność” przełączania się między programami nazywamy
wieloprogramowością lub wielozadaniowością. Omawiając wielozada-
niowość należy wspomnieć, że może ona być zrealizowana na dwa sposoby:
bez wywłaszczania i z wywłaszczaniem.
W obu przypadkach w rzeczywistości mamy do czynienia ze złudzeniem
jednoczesności — ze złudzeniem, gdyż procesor nie może w tym samym
momencie wykonywać kilku rozkazów realizujących różne programy. Jed-
noczesność polega na dzieleniu czasu pracy procesora pomiędzy wszystkie
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.6 Procesy, wątki, . . .
197
zadania (chwilowo zadanie utożsamiamy z procesem) i przydzielaniu każ-
demu z nich pewnego, bardzo krótkiego, odcinka czasu.
W przypadku działania bez wywłaszczania system operacyjny mówi,
który z procesów ma podjąć działanie, ale to ten proces musi oddać pa-
łeczkę z powrotem do systemu operacyjnego. W tej sytuacji jak łatwo sobie
wyobrazić, jeśli proces „nie odda” procesora to żaden inny proces (rów-
nież system operacyjny) nie może działać. W konsekwencji komputer się
„zawiesi”. Taka sytuacja miała miejsce w „duecie” Windows 3.11–DOS.
Istotne jest to, że wówczas cały ciężar zapewnienia jednoczesności spoczy-
wał na programiście. Każda aplikacja musiała być napisana w ten sposób,
aby samodzielnie przekazać sterowanie do systemu. Innymi słowy, to pro-
gram musiał wyrazić zgodę na wywłaszczenie i oddanie sterowania innemu
programowi. Jeśli tego nie uczynił, system komputerowy cały czas wykony-
wał tylko jego kod, co użytkownik odbierał jako zawieszenie systemu, czyli
utratę kontroli nad jego zachowaniem.
W systemach z wywłaszczaniem, bez względu na to jak napiszemy pro-
gram, czy tego chcemy, czy nie, zawsze po upływie przydzielonego fragmentu
czasu zostanie on wstrzymany a rozpocznie się wykonanie następnego, wy-
typowanego przez system operacyjny. Dzięki temu realizowane są wszystkie
zadania. Każdemu zadaniu przydzielany jest na tyle mały przedział czasu,
że sprawia to wrażenie jednoczesności. W konsekwencji czas realizacji po-
jedyńczego zadania wzrośnie. Spowodowane jest to faktem przydzielenia
tylko części mocy obliczeniowej. Jednakże w rzeczywistych zastosowaniach
nie rzadko zdarza się, iż zadanie częściej oczekuje na wyniki operacji wej-
ścia/wyjścia niż na wykonanie jego kodu (np. edytory tekstu), przez co
w zupełności wystarczą mu te małe chwile czasowe jakie przydzieli system
operacyjny.
7.6
Procesy, wątki, . . .
Na codzień terminy proces, wątek i zadanie używa się zwykle zamiennie,
mając na myśli wykonywany ciąg instrukcji reprezentujący jakiś program.
W pewnych sytuacjach rzeczywiście są to synonimy, jednak należy zdawać
sobie sprawę, iż nie zawsze jest to prawdą.
Co należy rozumieć pod pojęciami program i proces, powiedziane zo-
stało na samym początku. Zdarzają się jednak sytuacje, w których jest
porządane, aby wykonania pewnego programu było realizowane przez kilka
procesów, które współużytkowałyby jakąś część zasobów. Takie procesy
współdzielące kod, przestrzeń adresową i zasoby systemu operacyjnego na-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
198
System operacyjny
zywa się wątkami, natomiast środowisko, w którym wątek działa — zada-
niem. Pojedyńczy wątek, podobnie jak proces, powinien mieć własny stan
rejestrów i stos. Proces równoważny jest zadaniu z jednym wątkiem. Kon-
kretny wątek może być związany z dokładnie jednym zadaniem. Zadanie
nic nie robi jeśli nie ma w nim ani jednego wątku.
7.7
Zarządzanie pamięcią
Podczas wykonywania programu jego kod oraz dane muszą znajdować się,
przynajmniej częściowo, w pamięci głównej. Jeśli system jest jednozada-
niowy, to całą wolną pamięć można przeznaczyć na potrzeby jednego, kon-
kretnego programu (o ile oczywiście rozmiar programu nie przekracza roz-
miaru wolnej pamięci). Sytuacja mocno komplikuje się w systemach wie-
lozadaniowych, kiedy to w pamięci przechowuje się informacje związane z
wieloma procesami. Zwykle wolny obszar pamięci głównej jest mniejszy
niż łączne zapotrzebowanie programów. Wymaga to stworzenia mechani-
zmów zarządzających pamięcią i wbudowanie ich w system operacyjny. Ist-
nieje wiele rozmaitych sposobów zarządzania pamięcią, a wybór konkretnych
rozwiązań podyktowany jest w głównej mierze właściwościami sprzętowymi
determinującymi ich efektywność.
7.8
System plików
Mechanizmy związane z zarządzaniem procesami i pamięcią pozostają zwy-
kle niewidoczne dla użytkownika i raczej mało kto zdaje sobie sprawę z ich
istnienia. Jednym z najlepiej widocznych przejawów działalności systemu
operacyjnego jest system plików, a raczej jego obsługa. System plików
to pewna logiczna hierarchia danych zdefiniowana niezależnie od fizycznych
właściwości urządzenia na którym się znajduje, udostępnia ona logiczne jed-
nostki magazynowania informacji, takie jak katalog czy plik.
Informacje są gromadzone w plikach których zawartość określa ich twórca,
nadając odpowiednie znaczenie ciągowi bajtów, którym faktycznie jest każdy
plik. Pliki, dla łatwiejszego zarządzania nimi, pogrupowane są w katalogi
tworzące hierarchiczną strukturę przypominającą drzewo. System plików
porównać można z biblioteką, w której jest wiele różnych książek (plików).
Oczywiście można je poukładać w kolejności alfabetycznej, łatwo będzie
wówczas znaleźć jedną konkretną książkę. Jeśli jednak chcielibyśmy znaleźć
wszystkie pozycje związane z bajkami, możemy natrafić na problemy. Dla-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.9 Czy każdy komputer musi posiadać system operacyjny?
199
tego w wielu bibliotekach wyodrębnia się działy (odpowiednik katalogów)
grupujące książki o wybranych tematykach (narzuconych przez bibliotekarza
w celu łatwiejszego przeszukiwania zbiorów).
Poniżej przedstawiono typowe informacje związane z każdym plikiem
(pewne systemy operacyjne mogą nie mieć części z tych informacji, inne
mogą dodawać odmienne)
5
:
nazwa pliku — służy do jednoznacznej identyfikacji pliku w danym kata-
logu. Nie mogą zatem w jednym katalogu istnieć dwa pliki o tej samej
nazwie. Możliwe jest natomiast umieszczenie plików o identycznej na-
zwie w różnych katalogach.
typ pliku — informacja dla systemu i/lub człowieka dotycząca sposobu
interpretacji zawartości danego pliku;
lokalizacja — określa urządzenie i umieszczenie pliku na tym urządzeniu;
rozmiar — wyrażony w bajtach rozmiar pliku;
atrybuty — informacje dodatkowe o pliku mówiące na przykład o tym,
kto może go czytać, zmieniać, wykonywać itd.
System plików stanie się faktycznie użyteczny, jeśli zostaną jeszcze zdefi-
niowane pewne, dostarczane przez system operacyjny, elementarne funkcje,
które można na nim wykonać. Do podstawowych zaliczyć należy tworzenie
pliku, zapis do pliku, odczyt z pliku, usuwanie pliku. Ponadto definiuje
się pewną klasę operacji dodatkowych jak czytanie/pisanie od pewnej ściśle
określonej pozycji w pliku czy zmiana jego atrybutów.
W rzeczywistości wszystkie dane zapisane są, w jakiś sposób na fizycz-
nym nośniku danych (użytkownik nie zna fizycznej organizacji tych danych).
Gdyby nie system operacyjny, program musiałby pamiętać o ich położeniu i
wzajemnych powiązaniach. To właśnie do systemu operacyjnego należy od-
wzorowywanie logicznej koncepcji pliku na fizyczne urządzenia pamięciowe.
7.9
Czy każdy komputer musi posiadać system
operacyjny?
Z odpowiedzią na pytaniem postawione w tytule czekaliśmy na sam koniec,
gdyż prowokuje ono do pewnej dyskusji, a ta możliwa jest gdy posiadamy
5
W systemie S/400 w ogóle nie ma hierarchii drzewiastej plików i katalogów, zamiast
tego pliki są pamiętane w bazie danych.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
200
System operacyjny
odpowiednią wiedzę, której zarys został przedstawiony w poprzednich punk-
tach. Postaramy się przedstawić nasz punkt widzenia, mając nadzieję, iż
każdy, opierając się na zdobytej wiedzy, wyrobi sobie swoje własne zdanie.
W głównej mierze zależy to od charakteru pełnionych zadań. System
operacyjny ma ułatwiać kontakty człowiek–maszyna i pozwolić na efektywne
wykorzystanie sprzętu. Istotne jest to szczególnie w systemach wielozada-
niowych, gdzie mamy do czynienia z mnóstwem dość złożonych zależności.
Istnieją jednak systemy komputerowe wykonujące jeden konkretny pro-
gram a interakcje z człowiekiem ogranicza się w ich przypadku do niezbęd-
nego minimum. Taka sytuacja na przykład ma miejsce w przypadku mi-
krokontrolera sterującego pralką. Mikrokontroler, praktycznie rzecz biorąc,
to bardzo mały system komputerowy — ma swoją jednostkę wykonawczą,
różnego rodzaju pamięci, przetworniki i układy sterujące — wszystko to, co
jego większy brat z biurka, tylko w mniejszej skali. Ze względu na sposób
pracy, to znaczy stałe wykonywanie tego samego, pozostającego bez zmian,
programu nie jest wymagana obecność systemu operacyjnego. Oczywiście
w tym momencie, ktoś mógłby powiedzieć, iż program ten gospodarując za-
sobami mikrokontrolera w istocie stanowi sam dla siebie system operacyjny.
Jednak z naszego punktu widzenia system operacyjny, to osobny, nieza-
leżny program (lub ich zbiór) wykonujący prace związane z zarządzaniem
zasobami systemu na rzecz innych programów. Zatem w tym ujęciu pro-
gram sterujący pralką wykonuje się bez udziału systemu operacyjnego. Ten
typ oprogramowania nosi nazwę oprogramowanie wbudowane lub osadzone
(ang. embedded system).
Warto nadmienić, iż w chwili obecnej następuje dość dynamiczny roz-
wój układów mogących znaleźć zastosowanie w sterowaniu różnymi urzą-
dzeniami, jak choćby mikrofalówka czy pralka. Ich obecność w najnowszych
produktach uzasadniana jest poszerzeniem zakresu funkcjonalności. Chodzi
nam tutaj głównie o koncepcję „inteligentnego domu”, w którym to zain-
stalowane wyposażenie stara się dopomóc jego mieszkańcom. Tak więc, gdy
skończy się mleko, lodówka automatycznie wysyła zamówienie do sklepu
spożywczego; martwi się także o to, abyśmy mieli codziennie urozmaiconą
dietę zestawiając różnorodne menu. Takie ”zachowanie” wymagać będzie
rozbudowanego oprogramowania sterującego, a wówczas obecność systemu
operacyjnego stanie się koniecznością. Sytuacja ta jest szczególnie dobrze
widoczna na rynku telefonów komórkowych, które zaczynają pełnić coraz
więcej różnorodnych funkcji, stając się malutkimi komputerami, aparatami
cyfrowymi, organizatorami, salonami gier.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
201
7.10
Przykładowe systemy operacyjne
W punkcie tym pokrótce zostaną wymienione pewne wybrane systemy ope-
racyjne. Nie było naszym celem omówienie wszystkich znanych i mniej
znanych, gdyż wymagałoby to osobnego opracowania. Staraliśmy się jed-
nak wybrać te, które są znane i popularne oraz te, które może mniej znane,
są wyznacznikami pewnego trendu lub typu systemów. Omawiane są one w
kolejności alfabetycznej, by nie wyróżniać czy też sugerować ważności bądź
jakości któregoś z nich.
7.10.1
Amoeba
Amoeba jest systemem znacznie różniącym się od pozostałych zaprezento-
wanych w tym opracowaniu. Koncepcje jakie legły u jego podstaw są jednak
naturalną konsekwencją zmian zachodzących w świecie informatyki. W la-
tach 70-tych i początkach 80-tych, królowały maszyny wieloużytkownikowe
— na jednym komputerze mogło i często pracowało wiele osób. Postęp w
takich gałęziach nauki i przemysłu jak chemia czy fizyka pozwolił na pro-
dukowanie coraz lepszych (bardziej wydajnych) i tańszych układów elek-
tronicznych przy jednoczesnym spadku kosztów wytwarzania. Dzięki temu
praktycznie każdy, kto tylko chciał, mógł posiadać komputer wyłacznie na
swoje potrzeby; tak więc od połowy lat 80-tych do połowy lata 90-tych
mamy do czynienia z sytuacją, gdy na jednym komputerze pracowała jedna
osoba. Większą szybkość pracy komputera można osiągnąć na dwa spo-
soby: produkować wydajniejsze układy elektroniczne (co jest rozwiązaniem
kosztownym i wymagającym czasu) lub łącząc wiele komputerów ze sobą
w taki sposób aby „udawały” jeden. Drugie rozwiązanie jest znacznie tań-
sze a poza tym dostępne od zaraz. W drugim przypadku jest tylko jeden
istotny szczegół — jak sprawić, aby wiele maszyn działało jak jedna? W
poszukiwaniu odpowiedzi na to pytanie już w 1980 roku rozpoczyna pracę
kierowany przez prof. Andrew S. Tanenbaum’a, z uczelni Vrije Universi-
teit (ang. Free University) z Amsterdamu, zespół badający rozproszone
systemy komputerowe (ang. distributed computer system). Badania te, pro-
wadzone także przy udziale Centrum voor Wiskunde en Informatica (ang.
Centre for Mathematics and Computer Science), zaowocowały powstaniem
nowego rozproszonego systemu operacyjnego nazwanego Amoeba (1983, V
1.0)
6
. Z założenia Amoeba jest uniwersalnym (to znaczy nie przeznaczonym
do wykonywania konkretnych zadań) systemem operacyjnym pozwalającym
6
Ostatnie oficjalne wydanie V 5.3 pochodzi z roku 1996.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
202
System operacyjny
traktować zespół komputerów jak jeden dysponujący dużymi możliwościami
przetwarzania
7
. Pozwala to na wykonywanie programu na najlepiej do tego
nadającej się maszynie lub wręcz równoległe wykonanie jego części, jeśli
tylko istnieje taka możliwość
8
. Użytkownik nie powinien (to znaczy nie
musi) interesować się na jakim procesorze wykonywany jest jego program
czy też gdzie faktycznie składowane są jego pliki; logując się do systemu
9
uzyskuje dostęp do wszystkich przydzielonych jemu zasobów
10
. Istotne jest,
że maszyny pracujące pod kontrolą tego systemu nie muszą być oparte na
tej samej architekturze i mogą być łączone za pomocą sieci LAN, a więc
ich rozmieszczenie może być dosyć dowolne. Z punktu widzenia pojedyn-
czej osoby całość zachowuje się jak jeden duży i bardzo wydajny system
komputerowy.
7.10.2
Mac OS
Mac OS firmy Apple nierozłącznie kojarzony jest z graficznym interfejsem
użytkownika — GUI (Graphical User Interface). Inspiracją do jego po-
wstania, podobnie jak dla pozostałych systemów komunikujących się z oto-
czeniem głównie za pomocą obrazu i urządzenia wskazującego, była zbu-
dowana w 1973 w laboratoriach firmy Xerox w Palo Alto maszyna Xerox
Alto, która z czasem wyposażona została w pierwszy kompleksowy inter-
fejs graficzny zrealizowany w komercyjnym produkcie Xerox Star (1981).
Zaprezentowany w 1983 Apple Lisa znacznie rozszerzał powstałe tam kon-
cepcje, czyniąc urządzenie atrakcyjnym dla potencjalanych nabywców. Nie-
stety ze względu na cenę wynoszącą 10.000 USD (Xerox Alto 32.000 USD,
Xerox Star 16.000 USD) oraz niewystarczającą wydajność nie osiągnął on
większego sukcesu. Udało się to jednak jego następcy — Apple Macintosh
(1984). Mac był od Lisy tańszy (2.500 USD), mniejszy, szybszy a przede
wszystkim dużo bardziej przyjazny dla użytkownika. Wraz z komputerem
wprowadzono system operacyjny dla niego przeznaczony — System 1. Za-
soby komputera (pliki, programy itp) przedstawiano w nim pod postacią
ikon, umieszczonych w oknach pozwalając tym samym na ich grupowanie.
7
Sama idea łączenia komputerów za pomocą sieci lub innego łącza jest jak pisaliśmy
znana wcześniej. Jednak tradycyjne łączenie w tzw. cluster zapewniało współpracę jednak
bez wspólnego systemu operacyjnego. Każdy z komputerów miał własny system i jedynie
wykonywał zlecone zadania na rzecz kolektywu.
8
Mamy wówczas do czynienia z rozproszeniem (ang. distribution) i równoległością
(ang. parallelism) przetwarzania co przekłada się na zwiększenie ogólnej wydajności.
9
Podkreślamy, do systemu a nie na konkretną maszynę!
10
Zachowanie takie określa się terminem przezroczystość (ang. transparency).
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
203
Dodatkowe opcje udostępniane były przez system menu. Kontrolę nad tymi
elementami (wybieranie, aktywacja, przemieszczanie itp.) sprawowano za
pomocą jednoprzciskowego urządzenia wskazującego — myszy. Same zaś
elementy rozmieszczono na wirtualnym biurku nazywanym pulpitem. Dą-
żąc do maksymalnej intuicyjności pracy wprowadzono na przykład ikonę
kosza — po przeciągnięciu na nią dowolnego pliku ulegał on skasowaniu.
System operacyjny pozwalał na wykonywanie w tym samym czasie tylko
jednego programu; nie było pamięci wirtualnej czy chronionej a także ob-
sługi kolorów. Nie istniała możliwość zagnieżdżania katalogów (folderów
ang. folders). Pliki przechowywane były na najwyższym poziomie hierar-
chii systemu plików (ang. root level of a disk); z każdym z nich skojarzona
była jedynie nazwa folderu do którego należy plik.
Mankament ten usunięto w wersji systemu znanej pod nazwą System 3,
kiedy to hierarchiczny system plików HFS (Hierarchical File System), za-
stąpił używany do tej pory w wersji 1 i 2 MFS (Macintosh File System).
Ponadto cały czas dodawano drobne zmiany w interfejsie czyniące pracę
przyjemniejszą. Przykładem może być możliwość minimalizacji i maksyma-
lizacji okienek.
Kolejnym istotnym krokiem w rozwoju Mac OS był System 7 (1990).
System ten w końcu stał się wielozadaniowy (we wcześniejszym (System 4)
użytkownik decydował czy pracuje w trybie jedno czy wielozadaniowym).
Wprowadzono 32 bitowe adresowanie oraz pamięć wirtualną. Razem z syste-
mem zintegrowano obsługę sieci poprzez protokół AppleTalk oraz możliwość
współdzielenia plików za pomocą AppleShare (wcześniej były to dodatkowe
opcje). Pojawił się także mechanizm Drag and Drop oraz kolejne zmiany
w interfejsie, jak choćby wykorzystanie możliwości oferowanych przez kolo-
rowe monitory, w celu nadania bardziej przestrzennego wyglądu elementom
ekranu. Coraz wyraźniej zarysowywała się jednak potrzeba opracowania no-
wego systemu operacyjnego i nie zmieniło tego faktu nawet pojawienie się w
1997 Mac OS 8
11
. Systemu wielowątkowego, z ulepszonym systemem plików
HFS+, obsługą USB czy FireWire. . . ale wciąż za mocno związanego z po-
przednimi wersjami, a więc co raz mniej odpowiadającego nowym trendom
w rozwoju systemów operacyjnych.
Nadzieją na zmiany, po upadku projektu Copland stał się zakup w 1997
firmy NeXT Steve’a Jobs’a (jednego z założycieli Apple Computer)
12
. W
11
Po raz pierwszy nazwy Mac OS użyto w stosunku do System 7.6 wydanego w styczniu
1997.
12
Pierwszy system NeXTSTEP wydany został w 1988 roku; bazował na mikrojądrze
systemu Mach oraz elementach systemu BSD (4.3), a także oferował najbardziej zaawan-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
204
System operacyjny
efekcie 13 września 2000 po raz pierwszy zaprezentowano Mac OS X Public
Beta - zupełnie nowy system bazujący na koncepcjach NeXT
13
. Ostatnie
lata to rozwijanie „drapieżnej” linii Mac OS: 2001 — Mac OS X 10.0 Che-
etah, Mac OS X 10.1 Puma, 2002 — Mac OS X 10.2 Jaguar, 2003 — Mac
OS X 10.3 Panther.
7.10.3
MS-DOS i Windows
Około roku 1980 rynkiem mikrokomputerów zainteresował się gigant prze-
mysłu komputerowego firma IBM. Uwagę koncernu przyciągnęły nie tyle
obroty firm zajmujących się mikrokomputerami (śmiesznie małe — 100 mi-
lionów dolarów w porównaniu do 28 miliardów IBM-a), ale bardzo dyna-
miczny rozwój tego rynku (roczny wzrost równy 70%). Szybko i w dość nie-
konwencjonalny sposób jak na ten koncern powstaje mikrokomputer oparty
na 16-bitowym procesorze Intel 8088. Niestety tworzący go zespół nie miał
doświadczenia w tworzeniu oprogramowania na tego typu urządzenia. Na-
turalną drogą stało się nawiązanie współpracy z twórcą bardzo popularnego
już wówczas BASIC-a; tak IBM nawiązało pierwsze kontakty z Microsoftem
— firmą Billa Gatesa. Po wstępnych rozmowach dotyczących stworzenia
BASIC-a dla IBM, przyszedł czas na system operacyjny. Dla Microsoftu
była to niesamowita szansa na zaistnienie na rynku. Terminy narzucone
przez IBM były dość napięte i nie było mowy o tworzeniu systemu od pod-
staw. Gates zainteresował się wówczas stworzonym w Seattle Computer
Products systemem QDOS o wielce obiecującym rozwinięciu tego skrótu
Quick and Dirty Operating System (zmienionym później, grudzień 1980, na
86-DOS, (ang. Disk Operating System). W styczniu 1981 po raz pierw-
szy uruchomiono MS-DOS na prototypie komputera IBM. W czerwcu tegoż
roku Microsoft stał się właścicielem wszystkich praw do DOS. W sierpniu
1981 światło dzienne ujrzał IBM 5150 PC wyposażony w procesor Intel
8088 taktowany zegarem 4.77 MHz, wyposażony w 65kB pamięci RAM,
40 kB ROM, napęd dysków elastycznych 5.25 cala pracujący pod kontrolą
PC-DOS 1.0 (MS-DOS 1.0); cena całości — ok 3000 dolarów.
Ponieważ praktycznie wszystkie programy pracujące do tej pory pod
kontrolą rozpowszechnionego CP/M pracowały także pod kontrolą MS-DOS
system bardzo szybko zdobył sobie zaufanie użytkowników. Ówczesny DOS
zajmował 12kB pamięci i składał się z około 4000 linii kodu asemblerowego.
sowane GUI ze wszystkich dostępnych na rynku.
13
Jądro systemu znane pod nazwą Darwin faktycznie jest niezależnym, mogącym pra-
cować samodzielnie, systemem operacyjnym zgodnym z rodziną systemów UNIX.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
205
Nowością jak na tamte czasy była możliwość obsługi przez niego „mini-
dyskietek” tj. 160kB jednostronnych dysków 5.25 cala (w odróżnieniu od
8-calowych ówczesnych „normalnych” dyskietek). Podobnie jak w CP/M
także i tutaj nie było katalogów — wszystkie pliki znajdowały się w jed-
nym miejscu. Zaczęto jednak przechowywać pewne dodatkowe informacje
związane z plikami, jak choćby dokładny ich rozmiar, ulepszono algorytm
przydziału miejsca na dysku a system jako całość działał szybciej niż pier-
wowzór. Istniała także możliwość wykonywania prostych skryptów powłoki.
Kolejne lata to ciągłe usprawnianie i dodawanie nowych cech funkcjonalnych
do systemu. O ile przez pierwsze lata swojego istnienia DOS okazał się cał-
kiem udanym produktem, o tyle na początku lat 90-tych stało się jasne, że
ze względu na ograniczenia — szczególnie dobrze widoczne przy porówna-
niu z systemami rodziny UNIX — należy zaprzestać dalszego jego rozwoju.
Moment rozstania z DOS-em został nieznacznie przesunięty w czasie dzięki
Windows 3.1 — nakładce na DOS pozwalającej na bardziej intuicyjną i
przyjazną pracę, ale na horyzoncie widać było już Windows 95 — początek
końca DOS-a.
We wrześniu 1981 roku Microsoft rozpoczął prace nad czymś co nazwano
Interface Manager. W projekcie tym wykorzystano efekty prac laboratorium
Xerox-a z Palo Alto, gdzie po raz pierwszy pojawiła się idea interfejsu gra-
ficznego — GUI (ang. Graphical User Interface). Warto zauważyć, że w
tamtych czasach GUI postrzegane było raczej w kategoriach ciekawostki niż
przedsięwzięcia mającego przynieść poprawę w kontaktach człowiek – ma-
szyna. Na wiosnę 1983 Microsoft ujawnił fakt prowadzenia prac nad swoją
wersją GUI nazwaną Windows. W sierpniu 1985 pojawiła się Windows 1.0,
który wówczas nie był niczym więcej niż nakładką na DOS-a (konkretnie
MS-DOS 2.0). Operował jednak paletą 256 kolorów, pozwalał zmieniać roz-
miar okien aplikacji (których poza dostarczonymi wraz z Windows takimi
jak kalendarz, notatnik, zegarek, organizator nie powstało za wiele), mini-
malizować, maksymalizować i zmniejszać do ikony okna; nie było jednak
możliwości nakładania się okien. Po prawie dwóch latach (kwiecień 1987)
światło dzienne ujrzał Windows 2.0. Ta wersja zawierała wiele istotnych
usprawnień: uwzględniono możliwości nowego procesora Intel 286, dodano
wsparcie dla kart graficznych VGA, pamięci rozszerzonej, mechanizmów dy-
namicznej wymiany danych (DDE - ang. Dynamic Data Exchange); okna
mogły być swobodnie przemieszczane po ekranie a użytkownik mógł korzy-
stać z klawiatury w celu szybszego wykonywania pewnych operacji (tzw.
skróty klawiszowe). Pojawiła się także wersja przeznaczona dla procesora
Intel 386, oznaczona Windows 2.0/386, pozwalająca na jednoczesne uru-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
206
System operacyjny
chamianie wielu aplikacji DOS-owych. Także ta wersja nie zyskała więk-
szej sympatii użytkowników aczkolwiek wielu programistów zaczęło tworzyć
wówczas pierwsze aplikacje przeznaczone dla Windows (ewentualnie zaczęło
poważnie rozważać taką możliwość). Wydany w maju 1990 roku Windows
3.0 mimo iż szybko zastąpiony wersją 3.1 przyniósł kolejne zmiany: wspar-
cie dla nowego procesora Intel 386 wykorzystujące jego 32-bitowe własności
oraz zmienione środowisko tworzenia aplikacji (SDK ang. Software Deve-
lopment Kit) — teraz programista mógł skupić się wyłącznie na tworzeniu
aplikacji w oparciu o dostarczone funkcje zamiast poświęcać część czasu na
pisanie sterowników urządzeń. W kwietniu 1992 pojawił się Windows 3.1
dodające do cech znanych z wersji 3.0 obsługę multimediów — wsparcie dla
urządzeń dźwiękowych, odtwarzania plików video oraz czcionek TrueType
dzięki czemu edycja tekstu co raz bardziej zbliża się do idei WYSIWYG
(ang. What You See Is What You Get), czyli założenia, że obraz na ekra-
nie odzwierciedla dokładnie to, co otrzymujemy na wydruku. Windows w
tej wersji (oraz wersji sieciowej Windows for Workgroups) sprzedał się w
około 10 milionach egzemplarzy. W sierpniu 1993 na rynku pojawia się
Windows NT 3.1, pomimo zbliżonej do Windows 3.1 nazwy i niewątpliwie
wyglądu jest to zupełnie inny produkt. Stworzony z myślą o zastosowaniu
w wysokowydajnych systemach serwerowych wyznaczał nowe kierunki, je-
śli wziąć pod uwagę bezpieczeństwo, skalowalność czy wydajność. Sierpień
1995 przyniósł największe wydarzenie w historii Windows – wówczas ujrzała
światło dzienne wersja nazywana Windows 95 (milion egzemplarzy w ciągu
czterech pierwszych dni sprzedaży), która nie jest już jedynie nakładką na
MS-DOS, ale pełnym, samodzielnym 32-bitowym systemem operacyjnym
14
.
Z ważniejszych cech należy wymienić wsparcie dla obsługi stosu protokołów
TCP/IP oraz Internetu, wprowadzenie obsługi mechanizmów Plug and Play
oraz wiele zmian w wyglądzie i funkcjonalności interfejsu. Ważne jest także,
że przesiadka z Windows 3.1 na Windows 95, czy później Windows 98, nie
wiązała się z koniecznością drastycznej modernizacji sprzętu, co niestety w
późniejszych wersjach staje się regułą. Wydany w lutym 2000 roku Win-
dows 2000 to system mający zastąpić Windows 95, 98, NT na rynku za-
stosowań profesjonalnych. Październik 2001, wydany zostaje Windows XP,
system mający w założeniu zatrzeć różnicę pomiędzy systemem profesjo-
nalnym a jego domowym odpowiednikiem (biorąc pod uwagę najważniejsze
cechy funkcjonalne).
14
Wprawdzie podczas ładowania systemu mamy do czynienia z DOS-em, konkretnie
MS-DOS 7.0, to jednak Windows 95 po załadowaniu przejmuje całkowicie kontrolę nad
systemem. Prawdą jest również, że zawierał on w sobie sporo kodu 16-bitowego.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
207
7.10.4
NetWare
We wczesnych latach 70-tych Novell Data Systems konstruuje wieloużyt-
kownikowy system komputerowy złożony z jednostki głównej (zawierającej
procesor, pamięci, napędy dyskowe, interfejsy do podłączenia urządzeń ze-
wnętrznych takich jak na przykład drukarka) oraz terminali pozwalających
na zdalną pracę na jednostce głównej. Całość pracowała pod kontrolą sys-
temu operacyjnego bazującego na CP/M i Unix, i nosiła nazwę NOS (ang.
Network Operating System). W tamtych czasach istniało wiele firm oferu-
jących podobne rozwiązania. Na ich tle Novell wyróżnił się, i zdobył swoją
pozycję, dokonując kilku nietypowych, jak na ówczesne czasy, wyborów do-
tyczących dalszego rozwoju:
• Gdy tylko światło dzienne ujrzały pierwsze komputery IBM PC, No-
vell zaakceptował ich współistnienie w świecie komputerów, wycho-
dząc z założenia, że system w którym „końcówki” nie są jedynie ter-
minalami, ale pełnoprawnymi komputerami będzie działał sprawniej.
• Nie traktował opracowanego NOS-a jako dodateku do sprzedawanego
systemu, ale raczej skupia się na NOS-ie jako takim, oferując wsparcie
dla wszystkich (oczywiście w ramach możliwości) istniejących syste-
mów. W ten sposób omijały firmę „wojny sprzętowe”. Uniezależnienie
się od sprzętu, a raczej wspieranie jego szerokiej gamy, powodowało, że
bez względu na panujące w danym momencie trendy techniczne NOS
Novell-a zawsze pozostawał do dyspozycji potencjalnych klientów.
• Rozwinął ideę serwera plików zamiast powszechnej koncepcji serwera
dysków, czyli przydziału użytkownikom partycji (określonych frag-
mentów przestrzeni dyskowej) do ich wyłącznej dyspozycji. Serwer
plików w niedługim czasie zaczyna spełniać rolę nie tyle magazynu
plików (ang. file repository), ale zdalnego systemu plików przez co
serwer umożliwia sprawowanie kontroli nad tym kto i co robi z prze-
chowywanymi plikami.
Kolejne wersje NOS, począwszy od Advanced NetWare/286 powstałego
dla komputerów PC/AT, przeznaczone są główne dla procesorów z rodziny
Intel. Wraz z nadejściem w 1989 NetWare/386 (nazywanego też NetWare
3) rozwijana jest koncepcja modularności oprogramowania wchodzącego w
skład systemu. Wydany w 1993 NetWare 4 oprócz dalszego rozwijania i
podziału systemu na niezależne moduły, wprowadza NDS (ang. NetWare
Directory Services, Novell Directory Services). NDS jest kompleksowym
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
208
System operacyjny
i wszechstronnym mechanizmem obsługi obiektowo zorientowanej bazy da-
nych zawierającej informacje o wszelkich zasobach i obiektach w sieci. Teraz
w ramach jednej sieci może funkcjonować wiele serwerów o czym użytkow-
nik nie musi wiedzieć traktując system tak jak gdyby był tylko jeden serwer
(centralne zarządzanie tożsamością i uprawnieniami).
NetWare 4.10 i 4.11 oprócz kolejnych usprawnień i ułatwień, głównie
natury administracyjnej (nowe i przyjaźniejsze oprogramowanie), stanowi
zwrot w stronę technologi internetowych (obsługa stosu protokołów TCP/IP,
mechanizm IPX/IP Gateway, NetWare/IP, Web Server).
W NetWare 5 największą zmianą jest „prawdziwa” obsługa stosu pro-
tokołów TCP/IP. Owszem, wcześniej TCP/IP było obsługiwane, ale fak-
tycznie cała komunikacja odbywała się w oparciu o stos IPX/SPX. Ponadto
dodano wsparcie dla maszyn wieloprocesorowych a także umożliwiono wy-
mianę podzespołów systemu podczas jego pracy (ang. hot-swap). W miejsce
istniejącego do tej pory systemu plików pojawia się nowy, nazywany NSS
(ang. Novell Storage Services). Trudności związane z nadzorowaniem in-
dywidualnych stacji wchodzących w skład sieci ma pomagać rozwiązywać
ZENworks (ang. Zero Effort Networking), a proces drukowanie dokumentów
usprawniać NDPS (ang. Novell Distributed Print Services). Dla wygody
administratora w końcu pojawia się pracujące na serwerze GUI. Oferowane
oprogramowanie umożliwia zbudowanie kompletnego serwera sieciowego do
zastosowań e-commerce.
NetWare 6 to przede wszystkim większa otwartość na użytkownika, ro-
zumiana tutaj jako umożliwienie dostępu do wszelkich zasobów sieci (pliki,
drukarki, bazy danych). Wsparcie dla pracy grupowej poprzez: pocztę elek-
troniczną, terminarze, kalendarze itp. bez względu na rodzaj sieci, plat-
formy na której działa serwer czy urządzenie klienta (wystarczy dowolne
urządzenie umożliwiające dostęp do Internetu jak choćby telefon komór-
kowy czy palmtop).
7.10.5
OS/390
System operacyjny OS/390 firmy IBM stworzony został z myślą o produ-
kowanych przez nią komputerach typu mainframe serii System/370 (1970
rok), który był następcą linii System/360
15
). A docelowo miał być sercem
15
Liczba 360 w nazwie miała symbolizować cały zakres zapotrzebowań jakie była w
stanie pokryć rodzina maszyn tej serii. Podkreślać miała uniwersalność zastosowań oraz
dostępność dla szerokiego kręgu odbiorców o różnych potrzebach i możliwościach finan-
sowych. Stąd 360 — czyli 360 stopni kątowych. Drugie źródło tłumaczy nazwę jako
pochodzącą od lat 60-tych i następne od kolejnych dekad ubiegłego wieku.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
209
komputerów System/390. W prostej linii pochodzi on od systemu MVS,
do którego dodano pewne usługi systemów typu Unix. Po raz pierwszy
pojawił się w 1995 roku a obecnie, po wprowadzeniu wsparcia dla maszyn
64 bitowych, występuje pod nazwą z/OS i jest przeznaczony dla maszyn
zSeries.
MVS (ang. Multiple Virtual Storage) po raz pierwszy wydany został
w 1974 roku. Stanowił on rozwinięcie długiej listy systemów operacyjnych
przeznaczonych dla maszyn System/360. Pierwszy z nich to PCP (ang.
Primary Control Program) — system, który nie wspierał wielozadaniowości;
drugi to MVT (ang. Multitasking with a Variable number of Tasks) zawierał
już wsparcie dla wielozadaniowości. Kolejny system — SVS (ang. Single
Virtual Storage) wykorzystywał pojedynczą (jedną dla wszystkich zadań)
wirtualną przestrzeń adresową. MVS, który był rozwinięciem cech poprzed-
ników, pozwalał aby każde z wielu zadań posiadało swoją własną przestrzeń
adresową. Zasadnicza interakcja z systemem odbywała się za pomocą ję-
zyka JCL (ang. Job Control Language) oraz TSO (ang. Time Sharing
Option). JCL jest językiem pozwalającym na uruchamianie programów w
trybie wsadowym (ang. batch mode), czyli bez interakcji z użytkownikiem.
Określano w nim jakie operacje były do wykonania, na jakich danych oraz
jakie zasoby komputera dla nich przeznaczono. Od momentu uruchomienia
takiego zadania, aż do zakończenia nie wymagało ono interwencji operatora
systemu. Naturalnym uzupełnieniem języka JCL był TSO, który pozwalał
na interaktywną pracę — na przykład operację na plikach czy nadzorowanie
wykonania zadań wsadowych.
Jeśli by chcieć porównywać systemy operacyjne tak jak samochody, to
MVS byłby osiemnastokołową ciężarówką. Takiego pojazdu nie używa się ze
względu na jego szybkość, ale po to aby mieć pewność, że uda się możliwie
najbezpieczniej przewieźć bardzo duży ładunek
16
. Mówiąc o mocy kompu-
terów typu mainframe, musimy zdawać sobie sprawę, że jest to coś zupełnie
innego niż moc superkomputerów. Te drugie zoptymalizowane są pod kątem
jak najszybszego wykonywania bardzo dużej liczby operacji arytmetycznych.
Mainframe to z kolei maszyna zdolna do wykonania niewielkiej ilości pro-
stych operacji na ogromnej ilości danych (liczby rzędu setek tysięcy nie są
tu rzadkością). W tym przypadku nacisk kładziony jest na optymalizację
operacji wejścia/wyjścia, które to w znacznym stopniu stanowić będą ramy
określające czas potrzebny na przeprowadzenie operacji. Drugim ważnym
aspektem, który brano pod uwagę przy projektowaniu systemów klasy ma-
inframe i oczywiście systemów operacyjnych je wspierających, to niezawod-
16
Zaczerpnięte z [DuC01].
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
210
System operacyjny
ność. Projektowano je do profesjonalnych zastosowań, gdzie najmniejszy
błąd mógł kosztować setki tysięcy dolarów, czy też ludzkie życie. Dlatego
też systemy te do dzisiejszego dnia są wykorzystywane przez banki czy inne
organizacje, dla których pewność rozwiązania jest najważniejsza.
7.10.6
OS/400
Historia OS/400 sięga swymi korzeniami daleko w przeszłość. Wprawdzie
system ten pojawił się w 1988 jednak był on konsekwencją działań po-
dejmowanych od końca lat 60-tych. W roku 1961 DEC (Digital Equipment
Corporation) wprowadza na rynek komputer PDP-1 (Programmed Data Pro-
cessor 1), postrzegany przez wielu jako pierwsze urządzenie nadające się do
zastosowań komercyjnych. W dość krótkim czasie liczne grono powstałych
na jego bazie konstrukcji rozwojowych udowodniło, że rynek niewielkich (i
relatywnie tanich) komputerów (nazywanych minikomputerami dla odróż-
nienia od „prawdziwych” komputerów
17
) może być atrakcyjny nawet dla
takich gigantów jak IBM. IBM wkracza na rynek minikomputerów w roku
1969 przedstawiając System/3. W sześć lat później pojawia się pierwszy
przedstawiciel rodziny System/3X — System/32. Niestety zarówno on, jak
i wprowadzony w 1977 roku System/34 nie zdobyły większego zaintereso-
wania ze strony potencjalnych klientów. Dopiero pochodzący z 1978 Sys-
tem/38 a w szczególności wprowadzony w 1983 System/36 zyskują uznanie
w oczach odbiorców — każdy z innych powodów. System/36 – głównie za
sprawą przyjaznego interfejsu i łatwości obsługi. System/38 był natomiast
zaawansowanym technicznie urządzeniem, w którym wcielono w życie tak
rewolucyjne pojęcia jak obiekt czy enkapsulacja danych a w szczególności
maszyna wirtualna. Pomysł polegał na uniezależnieniu oprogramowania od
fizycznie istniejących komponentów. Osiągnięto to wprowadzając interfejs
programistyczny znany niegdyś pod nazwą MI (ang. Machine Interface), a
obecnie jako TIMI (ang. Technology Independent Machine Interface). Użyt-
kownik/programista mógł komunikować się ze sprzętem tylko i wyłącznie
przez ten interfejs; nie miał żadnej możliwości wglądu w to co dzieje się
pod nim. Tworzone oprogramowanie w pierwszej fazie przekształcane było
do kodu mogącego wykonywać się właśnie na takiej abstrakcyjnej maszynie.
Następnie za pośrednictwem interfejsu, bez ingerencji człowieka, przekształ-
cane było do postaci nadającej się do wykonania na maszynie rzeczywistej.
Połączenie technicznych koncepcji System/38 z łatwością użytkowania
System/36 zaowocowało powstaniem w 1988 komputera AS/400 (ang. AS
17
Które w tamtych czasach zajmowały pokaźne powierzchnie.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.10 Przykładowe systemy operacyjne
211
— Application System, pierwotnie Advanced System). Wraz z komputerem
powstał też i system operacyjny pozwalający na pracę z nim — OS/400.
OS/400 traktowany jest w AS/400 jak zwykły program użytkownika w
tym sensie, że również on musi uzyskiwać dostęp do systemu za pośrednic-
twem MI. Jednakże część usług przypisywanych systemowi operacyjnemu
jak choćby zarządzanie procesami czy pamięcią musi mieć dostęp do fizycz-
nie istniejących urządzeń. Tą część OS-a zdefiniowano poniżej warstwy MI
udostępniając, jeśli to konieczne, jedynie odpowiedni interfejs do komuni-
kacji z częścią OS-a leżącą powyżej MI. Jako, że wszystko co jest poniżej
MI ukryte jest przed światem zewnętrznym, praktycznie nie ma możliwości
zastąpienia oryginalnego OS/400 innym systemem operacyjnym lub wy-
korzystania go na innej platformie sprzętowej. Stąd też nazwy OS/400 i
AS/400 używane są przez wielu jak synonimy, choć nimi nie są.
7.10.7
Unix i rodzina
Jak to napisano we wstępie w 1965 roku trzy organizacje Bell Telephone La-
boratories, General Electric Company oraz MIT, w ramach projektu MAC.
próbowały stworzyć system Multics. Ponieważ jednak projekt nie przynosił
spodziewanych efektów Bell odstąpił od udziału w projekcie i podjął własne
wysiłki skonstruowania systemu wspierającego pracę wieloużytkownikową,
zapewniającego współdzielenie zasobów i udostępnianie mocy obliczenio-
wej. W 1971 roku w wydziale patentowym Bell Laboratories zainstalowano
pierwszą wersję systemu Unix
18
. System ten cechował się małymi wymo-
gami, zaledwie 16KB dla samego systemu i 8KB dla programów użytkowych,
obsługiwał dysk o pojemności 512KB oraz pozwalał na utworzenie pliku nie
przekraczającego 64KB. W krótkim czasie zostaje wymyślony i zaimplemen-
towany w tym systemie nowy język programowania C, zaś w 1973 roku w
tym języku właśnie przepisany zostaje cały system operacyjny. Ponieważ
firma w której powstawał Unix ze względu na pewne zobowiązania wobec
rządu federalnego nie miała prawa sprzedawać komputerów oddała Unix
Uniwersytetom, które zaczęły wykorzystywać go do celów dydaktycznych.
W 1977 roku liczba instalacji Unixa wynosi 500, z czego 125 było na uni-
wersytetach. Przez lata system ten był rozwijany zarówno wewnątrz AT&T
jak i na Uniwersytecie Kalifornijskim w Berkeley. Stąd powstały wtedy nie-
jako dwie gałęzie: jedna nazwana System V i wspierana przez AT&T oraz
druga 4.3 BSD wspierana przez uniwersytety. W chwili obecnej istnieje ro-
18
Źródła podają, że autorem nazwy Unix, która była kalamburem słowa Multics, był
Brian Kernighan.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
212
System operacyjny
dzina trzech systemów z serii BSD: FreeBSD, OpenBSD i NetBSD, które są
dostępne za darmo. Na początku 1984 roku na świecie odnotowano około
100000 instalacji systemu Unix, co więcej były to instalacje na przeróżnych
komputerach i procesorach, od małych jak na tamte czasy, do dużych ma-
szyn. W tamtym okresie żaden system nie mógł poszczycić się taką prze-
noszalnością, którą Unix posiadał dzięki kilku cechom. Po pierwsze, był
napisany w języku wysokiego poziomu C, dzięki czemu przenoszenie kodu
nie sprawiało tylu trudności co przenoszenie w asemblerze na inny mikro-
procesor. Co prawda nie wystarczyło na nowym komputerze posiadającym
kompilator języka C przekompilować cały system. Wymagało to często spo-
rego wysiłku dostosowywania do innej architektury, jednak nie był to proces
tak żmudny jak przepisywanie ręczne programów w asemblerze. Po drugie,
system Unix posiadał prosty interfejs, oraz zawierał wiele narzędzi do bu-
dowy programów. Po trzecie, posiadał spójny i hierarchiczny system plików,
oraz dostarczał prostych funkcji do operowania na nich, nie zależnych od
fizycznego położenia pliku. Po czwarte był systemem wielodostępnym i wie-
loprocesorowym, co więcej izolował poprzez warstwę abstrakcji użytkownika
od architektury sprzętowej. W tamtym czasach żaden inny system nie mógł
poszczycić się powyższymi cechami oraz taką popularnością.
W chwili obecnej trudno mówić o systemie Unix jako takim, istnieje cała
rodzina systemów Unixo podobnych, kompatybilnych z nim w mniejszym
lub większym stopniu. Aby trochę ogarnąć ten chaos zaproponowano wiele
standardów, jednym z nich jest POSIX i obecnie większość szanujących się
systemów Unixowych jest zgodna z tym właśnie standardem wprost lub też
przez emulację. Jedną z najpopularniejszych obecnie „odmian” Unixa jest
Linux. System ten został napisany w zgodzie ze standardem POSIX, a tam
gdzie POSIX nie precyzuje rozwiązań, Linux naśladuje System V. Co więcej
w celu zwiększenia uniwersalności system ten zawiera biblioteki pozwalające
emulować działania BSD. Istnieją co prawda wyjątki, gdyż system podsieci
został zupełnie przeniesiony z BSD i jest oparty na idei gniazd. System
Linux został zaprojektowany w 1991 roku przez młodego studenta Uniwer-
sytetu w Helsinkach Linusa Torvaldsa. Linus pisząc swój system oparł się na
innym Unixo podonym systemie Minix, jednak napisał go od nowa i udostęp-
nił na prawach licencji GPL. Licencja GPL jest tak skonstruowana, że kod
przez nią udostępniany jest wolny w sensie wolności dystrybucji i otwartości
źródeł
19
. Spowodowało to, że cały świat internetu miał dostęp do źródeł sys-
temu Unixo podobnego, co spotkało się z dużym zainteresowaniem. W ciągu
kilku zaledwie lat system ten obrósł dodatkowymi programami i bibliote-
19
Nie oznacza to automatycznie, że jest on za darmo
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
7.11 Zadania
213
kami, by w chwili obecnej stać się jednym z najpopularniejszych na świecie,
zwłaszcza w kręgach ludzi młodych oraz środowiskach akademickich. W
dniu dzisiejszym jest on jednym z najchętniej wybieranych systemów ser-
werowych, oraz coraz częściej wykorzystywany przez programistów z racji
bardzo dużej stabilności pracy i ogromnej ilości narzędzi programistycznych
właśnie.
7.11
Zadania
1. Wymień główne zadania stawiane systemowi operacyjnemu.
2. Porównaj systemy jedno i wielozadaniowe.
3. Porównaj systemy jedno i wieloużytkownikowe (wielodostępowe).
4. Wymień co najmniej dwa współczesne systemy operacyjne i spróbuj
je scharakteryzować.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
214
System operacyjny
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Rozdział 8
Sieci komputerowe
A wtedy z chaosu odezwał się głos i powiedział:
„Bądź cicho, mogło być gorzej.”
Byłem cicho i pogorszyło się.
Nieznany administrator sieci
8.1
Po co mi ona?
Jedną z najcenniejszych rzeczy w dzisiejszym świecie jest informacja. Skon-
struowanie pierwszych komputerów w połowie XX wieku pozwoliło na nie-
spotykane przyspieszenie przetwarzania danych. Komputery najpierw po-
woli, głównie za sprawą swojej ceny i skomplikowanej obsługi, z czasem coraz
szybciej znajdowały zastosowanie w najprzeróżniejszych dziedzinach naszej
egzystencji. Wraz ze wzrostem ich ilości, problemy zaczęła sprawiać wy-
miana danych pomiędzy nimi. Coraz więcej urządzeń musiało dysponować
bądź takimi samymi danymi, bądź pojawiały się komputery, które posia-
dały informację użyteczną dla innych. W tej sytuacji potrzebne dane trzeba
było wciąż kopiować na taśmę lub dyskietkę, przenosić i wgrywać w nowym
miejscu. Rozwiązanie takie nie należało do najbezpieczniejszych, głównie
za sprawą podatności na utratę zapisanych danych i przypadkowe zniszcze-
nia fizyczne a także potencjalną możliwość uzyskania do nich dostępu przez
osoby do tego nieuprawnione. Ponieważ zarówno szybkość przetwarzania
jak i możliwe pola zastosowań ulegały ciągłemu zwiększaniu, aktualizacje
zgromadzonych i przetwarzanych informacji musiały być coraz częstsze. W
tej sytuacji najefektywniejszą metodą, zarówno pod względem szybkości
jak i niezawodności, przenoszenia danych stało się połączenie komputerów
za pomocą przewodu. Z czasem, mimo związanych z tym kosztów i wzrostu
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
216
Sieci komputerowe
stopnia komplikacji, łączono ze sobą coraz więcej systemów, gdyż korzyści
jakie dzięki temu osiągano, przeważały poniesione nakłady.
Dzięki takiemu rozwiązaniu stało się możliwe współużytkowanie a ra-
czej współdzielenie danych; wystarczyło, że składowane są one na jednym
komputerze a pozostałe, jeśli ich potrzebują, mają możliwość szybkiego
ich otrzymania, dzięki istnieniu bezpośredniego, pracującego bez ingerencji
człowieka, systemu ich przekazywania. Ponieważ w takiej sytuacji informa-
cje przechowywane są w jednym miejscu, zatem ekonomicznie uzasadnione
staje się konstruowanie wyspecjalizowanych systemów przeznaczonych do
ich zarządzania, kontrolowania i ochrony — powstają bazy danych, serwery
FTP, serwery WWW, serwery poczty itd.
Kolejne ważne zagadnienie to zwiększenie niezawodności i funkcjonalnej
dostępności. W sytuacji, gdy wiele komputerów połączonych jest ze sobą i
nastąpi awaria jednego lub nawet kilku z nich, ich funkcje przejmują auto-
matycznie jednostki sprawne. Jeśli z kolei użytkownik prosi o pewne dane
znajdujące się na kilku komputerach, to otrzyma je od tego, który w danym
momencie może zrobić to najszybciej skracając tym samym czas dostępu do
danych.
8.2
Struktura fizyczna sieci
Charakteryzując fizyczną strukturę jakiekolwiek sieć komputerowej poda-
jemy zwykle jej zasięg i topologię.
8.2.1
Zasięg sieci
Pod względem zasięgu zasadniczo wyróżniamy sieci typu LAN, WAN i
MAN, które pokrótce można scharakteryzować w następujący sposób:
LAN — (ang. local area network) sieć lokalna łączy ze sobą urządzenia sie-
ciowe znajdujące się w „niewielkiej” odległości. Termin „niewielkiej”
równie dobrze może oznaczać 1 metr — gdy łączymy się z kompute-
rem kolegi stojącym na biurku obok, jak i 200 metrów — gdy łączymy
się z komputerem znajdującym się w sąsiednim budynku. Zawsze po-
zostanie to jednak ograniczony obszar, niewielki (wręcz punktowy) w
skali kraju czy świata.
WAN — (ang. wide area network) sieć rozległa to, oprócz dużo większego
zasięgu niż sieci LAN, skalowalność rozwiązania. Sieci tego typu muszą
umożliwiać rozbudowę w miarę potrzeb, przy założeniu łączenia wielu
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.2 Struktura fizyczna sieci
217
węzłów rozmieszczonych w znacznych odległościach od siebie. Węzeł
to zarówno jeden komputer, jak i równie dobrze cała sieć LAN. Sieci
WAN integrują wiele różnorodnych technologii sieciowych w jeden sys-
tem umożliwiający wymianę informacji bez względu na występujące
różnice sprzętowe, programowe i logiczne.
MAN — (ang. metropolitan area network) sieć miejska jest czymś pośred-
nim między siecią lokalną a rozległą. Jeszcze 10 lat temu wyraźnie
można było powiedzieć, która sieć jest siecią miejską. Obecnie jest to
trudne, gdyż sieci miejskie są włączane w ogólny szkielet Internetu,
czyli sieć rozległą, co powoduje, że stają się jego częścią.
8.2.2
Topologia sieci
Mówiąc o topologii sieci mamy na myśli jej niejako ułożenie fizyczne, okre-
ślające sposób połączenia wchodzących w jej skład urządzeń. I tak zasad-
niczo wyróżnia się trzy topologie występujące w sieciach LAN oraz jedną
dodatkową stosowaną w MAN i WAN.
Topologia magistrali — uzyskuje się ją łącząc wszystkie urządzenia za
pomocą pojedynczego kabla (rysunek 8.1). W chwili obecnej realizo-
wane jest to jedynie za pomocą kabla koncentrycznego (zob. 8.5.2).
Obecnie jest to technologia wymierająca, z racji dużej awaryjności
oraz kłopotliwości w serwisowaniu.
Topologia pierścienia — charakteryzuje się tworzeniem zamkniętego po-
łączenia (rysunek 8.2). Każdy komputer łączy się ze swoimi dwoma
najbliższymi sąsiadami i tylko z nimi wymienia on bezpośrednio in-
formacje.
Topologia gwiazdy wszystkie węzły łączą się w jednym punkcie (rysunek
8.3).
Topologia oczek pełnych — tutaj każdy węzeł połączony jest ze wszyst-
kimi pozostałymi (rysunek 8.4). Otrzymujemy w ten sposób naj-
bardziej niezawodną i odporną na uszkodzenia fizyczne konfigurację.
Oczywistą wadę takiego rozwiązania stanowi szybki wzrost liczby po-
łączeń, pociągający za sobą wzrost stopnia komplikacji i kosztów, wraz
ze wzrostem ilości obsługiwanych węzłów.
Topologia mieszana — stanowi dowolne połączenie powyższych rozwią-
zań, wbrew pozorom jest dość często stosowana. Przykładowo w firmie
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
218
Sieci komputerowe
Rysunek 8.1: Topologia magistrali.
istnieje topologia magistrali a zarząd nie chce podjąć decyzji o przebu-
dowie istniejącej infrastruktury a jednocześnie chce podłączyć kolejne
komputery, wtedy nowe będą np. w topologii gwiazdy.
Mówiąc o topologii pamiętajmy, aby nie mylić organizacji fizycznej i lo-
gicznej sieci. Fizyczna organizacja to właśnie powyższe modele, które można
zobaczyć gołym okiem albo dotknąć, jeśli ktoś będzie miał takie życzenie.
Organizacja logiczna wykorzystuje natomiast fizycznie istniejące połączenia
do zorganizowania przesyłania danych. Organizacja ta jest całkiem nie-
zależna od organizacji fizycznej. Dlatego nic nie stoi na przeszkodzie, aby
istniała sieć o fizycznej strukturze gwiazdy działająca na (logicznej) zasadzie
pierścienia.
8.3
Architektura sieci
Ostatnią z cech, jaką należy zasygnalizować jest architektura sieci. Nie-
sie ona ze sobą informację o konfiguracji urządzeń podłączanych do jednej
z wcześniej omawianych topologii. Tu wymienia się głównie architekturę
klient-serwer (zob. 8.3.2) oraz równorzędną (zob. 8.3.1). W celu lep-
szego przybliżenia idei powyższych, wprowadzimy wpierw terminy klient i
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.3 Architektura sieci
219
Rysunek 8.2: Topologia pierścienia.
Rysunek 8.3: Topologia gwiazdy.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
220
Sieci komputerowe
Rysunek 8.4: Topologia oczek pełnych.
serwer.
Serwerem nazywany jest dowolny komputer przyłączony do sieci i udo-
stępniający swoje zasoby innym urządzeniom. Poprzez zasób rozumiemy tu-
taj zarówno dysk, pamięć, czy też moc obliczeniową. Na ogół sposób pracy
i konstrukcja fizyczna serwera zoptymalizowane są pod kątem wykonywania
określonej funkcji. Nie zapominajmy jednak, iż „serwer” nie musi oznaczać
osobnego komputera; kilka serwerów może funkcjonować w ramach jednej
fizycznej maszyny, wtedy też mówi się nie o serwerze a usłudze lub usługach
jakie udostępnia. Ze względu na sposób pracy wyróżnia się zwykle:
Serwer plików służy do składowania plików i ich udostępniania użytkow-
nikom sieci. Mechanizm centralnego przechowywania plików daje ła-
twiejszą kontrolę nad tworzonymi dokumentami. Teraz każdy zamiast
„osobistej” wersji pewnych plików przechowywanych na swoim kom-
puterze korzysta z tych zapisanych na serwerze. Gdy nastąpi jego
zmiana, każdy przy następnym jego pobraniu automatycznie otrzyma
uaktualnioną wersję. Uwalnia nas to od konieczności przeglądania
wszystkich potencjalnych miejsc przechowywania i ciągłego kontrolo-
wania zachodzących zmian. Kolejną niezaprzeczalna zaletą jest uprosz-
czenie tworzenia kopii zapasowych, które są niezbędne do zapewnienia
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.3 Architektura sieci
221
bezpieczeństwa w razie awarii. Dość łatwo można wykonać kopię zaso-
bów jednego komputera (tego na którym wszyscy przechowują pliki)
podczas gdy dla większej ich ilości wymagany jest większy nakład
pracy, sprawna organizacja i co najważniejsze pilnowanie użytkowni-
ków, by w ogóle wykonywali te kopie.
Serwer aplikacji jest miejscem wykonywania (uruchamiania) programów
wykonywalnych. Jego istotą jest właśnie to, że programy urucha-
miane są na tymże serwerze a nie na komputerze użytkownika, co mia-
łoby miejsce gdyby były przechowywane na serwerze plików. Innymi
słowy serwer aplikacji udostępnia swoje zasoby poprzez bezpośrednie
wykonywanie zainstalowanych na nim programów na rzecz odległego
klienta. Stosowanie serwerów aplikacji daje sposobność wygodnego
kontrolowania używanego oprogramowania.
Serwer wydruków. Pomimo, iż żyjemy w epoce komputerów i cyfrowej
informacji, nadal często zachodzi potrzeba sporządzenia dokumentów
w postaci zadrukowanej kartki papieru. W tym celu należy zapew-
nić użytkownikom dostęp do odpowiednich urządzeń. Indywidualna
drukarka dla każdego, to rozwiązanie nieuzasadnione ekonomicznie.
Zwykle ilość drukowanych stron to kilka, kilkadziesiąt miesięcznie. W
takiej sytuacji dużo lepiej zainwestować w serwer wydruków, który
wszystkim użytkownikom sieci udostępnia podłączone do niego dru-
karki, których jest znacznie mniej niż potencjalnych użytkowników.
Przyjmuje on zlecenia druku od wszystkich urządzeń w sieci, ustawia
je w kolejkę i kieruje do odpowiedniej drukarki. Dzięki temu 50 kom-
puterów może korzystać z 2 drukarek, praktycznie w taki sam sposób
jakby stały one tuż obok każdego stanowiska. Jedyna niedogodność,
to konieczność „przespacerowania się” po gotowe wydruki do miejsca
gdzie stoją drukarki.
Serwer bazy danych jest miejscem przechowywania danych. Istotnym
czynnikiem odróżniającym go od serwera plików, na którym również
można składować dane, jest zdolność do zarządzania, kontroli i prze-
twarzania przechowywanych informacji. Korzystając z serwera plików
wysyłamy do niego lub otrzymujemy plik, którego zawartości nada-
jemy znaczenie dopiero my sami. Natomiast między użytkownikiem a
serwerem baz danych przesyłana jest tylko konkretna informacja. Za-
łóżmy, że zapisujemy codziennie wielkość naszego majątku oraz ile i na
co wydaliśmy naszych zasobów pieniężnych. Po pewnym czasie chcąc
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
222
Sieci komputerowe
dowiedzieć się kiedy wydaliśmy więcej niż 100 złotych w przypadku
serwera plików pobieramy plik z wydatkami i przeglądamy go ręcz-
nie w poszukiwaniu żądanych pozycji. Korzystając natomiast z usług
serwera baz danych, wysyłamy do niego zapytanie, które nieformalnie
brzmieć może: „Podaj mi te dane, w których dziennywydatek > 100”.
Serwer odpowiada na nasze zapytanie przesyłając nam tylko poszuki-
wane informacje.
Serwer poczty umożliwia użytkownikom wymianę informacji na zasadach
zbliżonych do funkcjonowania poczty tradycyjnej. Serwer udostępnia
swoje usługi w postaci wysyłania lub odbierania wiadomości z okre-
ślonego miejsca sieci oraz jej przechowywania. Wysyłając do kogoś
list elektroniczny podajemy adres według wzoru:
nazwa_użytkownika@serwer.poczty
Część po znaku @ określa miejsce w sieci gdzie list ten zostanie prze-
słany (jest to nazwa fizycznego komputera — hosta), natomiast po-
została informuje, do której „skrzynki” należy go przekazać, czyli kto
jest adresatem.
Serwer WWW udostępniając swoje usługi pozwala na tworzenie ogólno-
dostępnych, interaktywnych, niezależnych od platformy sprzętowej,
hipertekstowych dokumentów. Utożsamiany często z samym Interne-
tem faktycznie, wraz z językiem HTML (HyperText Markup Langu-
age), przyczynił się znacznie do jego rozwoju.
Serwer . . . Wspominamy tylko o najczęściej spotykanych serwerach, gdyż
ich ilość jest dość znaczna. W zasadzie każde urządzenie przyłączone
do sieci i wykonujące jakąś usługę na rzecz innych maszyn nazywamy
serwerem.
Klientem nazywamy urządzenie korzystające z usług serwera za po-
mocą sieci. Ważne jest to, że każdy komputer może być zarówno klientem
jakiejś usługi jak i serwerem innej, wszystko to zależy od konfiguracji opro-
gramowania.
8.3.1
Architektura równorzędna
W sieciach równorzędnych (ang. Peer-to-Peer — P2P) zwanych również
sieciami każdy-z-każdym, nie występuje tzw. dedykowany serwer. Ozna-
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.3 Architektura sieci
223
cza to, iż każde z urządzeń może pełnić funkcję zarówno klienta jak i ser-
wera. Sieci tego typu zbudować można w oparciu o dowolną topologię,
co więcej nie ma konieczności stosowania specjalnych środowisk pracy czy
systemów operacyjnych. Dzięki temu ich koszt i niezbędny nakład pracy
związany z instalacją zredukowane są do minimum. Praktycznie w opar-
ciu o każdy dzisiejszy komputer (a raczej ich zbiór) można zbudować sieci
tego typu bez większego nakładu pracy i środków. Trzeba jednak przy
tym pamiętać o pewnych zagrożeniach i ograniczeniach wynikających z ta-
kiej struktury. Bezpieczeństwo w tego typu systemach zależy od każdego
z użytkowników. Wszyscy muszą przestrzegać pewnych zasad i procedur
postępowania. Niewiele warte staną się nawet najwymyślniejsze hasła użyt-
kowników, gdy jeden z nich ujawni (celowo lub przez przypadek) swoje.
Ponadto współpraca kilkunastu osób wymagać może ciągłej wymiany pew-
nych dokumentów. Problemem staje się wówczas zapewnienie dostępu do
ich najaktualniejszej wersji. Zwykle poszukiwany plik będzie znajdował się
na kilku maszynach, co zmusi nas do ich przejrzenia i wybrania tego wła-
ściwego. Co więcej, może się okazać, że komputer z najaktualniejszą wersją
właśnie został wyłączony, gdyż jego użytkownik postanowił właśnie zakoń-
czyć pracę i zapomniał poinformować o tym fakcie pozostałych.
Ze względu na wspomniane cechy sieci typu każdy-z-każdym idealnie
nadają się dla małych firm, czy grup roboczych wchodzących w skład więk-
szych organizacji. Doskonale powinny zdać także egzamin w przypadku
„sąsiedzkiego” połączenia w jednym bloku mieszkalnym czy odcinku ulicy.
8.3.2
Architektura klient-serwer
Ograniczenia i problemy związane z bezpieczeństwem i administracją w
sieciach równorzędnych obejść można stosując architekturę klient-serwer.
Jedną z kluczowych cech w tej architekturze jest centralne zarządzanie,
dzięki któremu ulega znacznej poprawie bezpieczeństwo danych. Jeśli za-
chodzi potrzeba stworzenia np. kopii zapasowej, to dotyczy to tylko serwera
i zadanie to można powierzyć jednej osobie lub wręcz zautomatyzować. Nie
trzeba obarczać indywidualnych użytkowników, którzy najczęściej nie ro-
zumieją potrzeby tworzenia kopii bezpieczeństwa dopóki nie nastąpi jakaś
awaria i utrata danych. Konsekwencją centralnej weryfikacji tożsamości jest
znacznie sprawniej działający mechanizm kontroli uprawnień nadawanych
osobom korzystającym z sieci. W sieciach klient-serwer jedynie serwer od-
powiada za przetwarzanie zapytań klientów. Odciąża to znacznie poszcze-
gólne komputery klienckie. W takiej sytuacji wydajność sieci zależy często
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
224
Sieci komputerowe
od wydajności serwera. Zwykle jest to wyspecjalizowany system kompute-
rowy zoptymalizowany pod kątem pełnienia pewnej określonej funkcji i jego
wydajność zapewnia właściwe działanie sieci. Trzeba wyraźnie zaznaczyć,
że serwer pozostaje jednak najbardziej newralgicznym ogniwem sieci. Jego
awaria powoduje zatrzymanie pracy wszystkich użytkowników. Dlatego też
przykłada się wielką wagę do zapewnienia ciągłej i nieprzerwanej pracy ser-
werów czyniąc je tym samym urządzeniami skomplikowanymi i niestety dro-
gimi. Koszty podnosi konieczność stosowania specjalnego oprogramowania
nadzorującego pracę sieci a także samo jej wdrażanie i codzienna obsługa.
Właśnie ze względu na czynnik ekonomiczny stosowanie sieci klient-serwer
wydaje się ekonomicznie uzasadnione w przypadku dużych instytucji, gdzie
wymaga się zwiększonego bezpieczeństwa oraz jednolitego zarządzania i ko-
rzystania z zasobów sieci.
8.4
Kilka przydatnych pojęć
8.4.1
Pakiety i ramki
Zazwyczaj dane przesyłane przez sieć nie stanowią ciągłego strumienia bi-
tów. Dane przeznaczone do wysłania dzielone są na pewne „porcje” zwane
pakietami i dopiero wtedy transmitowane. Są dwa główne powody sto-
sowania pakietów. Po pierwsze, wspierają obsługę błędów transmisji, gdyż
dużo łatwiej jest powtórzyć transmisję niewielkiego bloku danych niż na
przykład kilku megowego pliku. Po drugie, umożliwiają prawie równole-
głą transmisję, za pomocą jednego ośrodka, danych pochodzących od wielu
nadawców. Łatwo wyobrazić sobie sytuację, gdy jeden komputer przesyła-
jący 100 MB plik wstrzymałby pracę całej sieci. Dzięki stosowaniu pakie-
tów, każdy w pewnym fragmencie przydzielonego czasu może nadać małą
porcję danych (właśnie pakiet), co chroni przed zablokowaniem dostępu dla
pozostałych komputerów (rysunek 8.5).
Ramką będziemy nazywali ciąg bitów, o ustalonym znaczeniu i kolejno-
ści w pakiecie. Ogólny schemat ramki przedstawia rysunek 8.6. Jak widać
oprócz danych użytkownika przesyłane są także pewne dodatkowe informa-
cje, są nimi np. SOH (ang. Start Of Header) — początek ramki, oraz EOT
(End Of Transmission) — koniec ramki. Wadą takiego rozwiązania jest
„marnowanie” części pakietu na dodatkowe dane, które nie niosą ze sobą
faktycznej informacji. Jednak patrząc na zagadnienie z drugiej strony, stoso-
wanie ramek i większych nagłówków jest konieczne. Zauważmy, że musimy
przecież gdzieś umieścić choćby informacje o adresacie przesyłki. Przyda się
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.4 Kilka przydatnych pojęć
225
(a)
(b)
(c)
Rysunek 8.5: Porównanie transmisji pakietowej (c) z niepakietową (b). Trzy
różne dane przeznaczone do transmisji pokazuje rysunek (a).
SOH
Nagłówek
Dane
EOT
Rysunek 8.6: Ogólny schemat ramki.
także numer kolejny przesyłki, pozwalający złożyć z danych transmitowa-
nych w pakiecie oryginalną daną przesłaną przez użytkownika jeśli zaszłaby
konieczność jej podziału. Jeśli zamierzamy potwierdzać otrzymanie prze-
syłki, to ramka powinna zwierać także adres nadawcy. Należy ponadto
wziąć pod uwagę fakt, iż rzadko kiedy transmisja w sieci jest bezproble-
mowa. To właśnie dzięki nadmiarowym informacjom znajdującym się w
nagłówkach możliwe jest zidentyfikowanie i odtworzenie lub retransmisja
błędnej informacji.
8.4.2
Protokół
Mianem protokołu określamy zbiór pewnych zasad i sposobów postępowa-
nia prowadzących do osiągnięcia pewnego celu. Zauważmy, że na codzień
spotykamy się z protokołami nie zdając sobie nawet z tego sprawy. Tele-
fonując do kogoś realizujemy „protokół nawiązania połączenia głosowego z
odległym klientem”. Gdy nasz rozmówca podniesie słuchawkę, nie mówimy
od razu tego co mamy do przekazania, lecz wpierw „inicjujemy wymianę
danych”. Zwykle następuje wymiana informacji niezbędnych do nawiązania
połączenia w rodzaju:
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
226
Sieci komputerowe
Przykład 8.1. Prosty protokół nawiązywania połączenia zakoń-
czony sukcesem.
Odbiorca: Halo.
Nadawca: Dzień dobry, mówi X.
Odbiorca: Witam serdecznie, w czym mogę pomóc.
Nadawca: Dzwonię w sprawie...
połączenie zostało nawiązane
Przykład 8.2. Prosty protokół nawiązywania połączenia zakoń-
czony porażką.
Nadawca: Mówi X. Czy mogę prosić Y?
Odbiorca: XyCVFR!* ?GHJAA;p[];,
Nadawca: Bardzo przepraszam.
połączenie nie zostało nawiązane z powodu niezgodności pro-
tokołów
Savoir-vivre to nic innego jak zbiór zasad i ogólnie przyjętych norm po-
stępowania w różnych sytuacjach życiowych. Nie obcy jest nam przecież
termin protokół dyplomatyczny. Ustalenia takie chronią przed niezręczną
lub kłopotliwą sytuacją o co nie trudno w przypadku dyplomatów mają-
cych kontakty z ludźmi wychowanymi w ramach różnych kultur. Podobnie
korzystanie z elektronicznych form przekazu, wymaga ustalenia znaczenia
pewnych sygnałów i kolejności ich wymiany w celu zainicjowania pewnego
działania. Fizyczne połączenie jest warunkiem koniecznym, ale nie wy-
starczającym dla pomyślnej realizacji komunikacji sieciowej. Jako przykład
szeroko rozpowszechnionych i obecnie najczęściej wykorzystywanych proto-
kołów sieciowych posłużyć może stos protokołów TCP/IP.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.4 Kilka przydatnych pojęć
227
8.4.3
TCP/IP
Stos protokołów TCP/IP
1
jest obecnie najczęściej stosowanym protoko-
łem w sieciach komputerowych w ogóle i jedynym w Internecie w szczegól-
ności.
W celu lepszego zrozumienia idei omawianego protokołu posłużymy się
przykładem Internetu. Jest to sieć sieci — „twór” integrujący w sobie różne
sieci zapewniając im mechanizm jednolitych usług. Oznacza to, iż wyma-
gane jest aby informacje z dowolnego komputera w jednej sieci mogły być
przekazywane do innego komputera w każdej z pozostałych. Dla realizacji
tego postulatu niezbędne okazuje się wsparcie zarówno od strony programo-
wej jak i technicznej. Aspekt techniczny jest częściowo zapewniony poprzez
odpowiednią organizację sieci rozległej (zob. 8.2.1), gdyż Internet jest wła-
śnie ogromną, bo otaczającą całą kulę ziemską siecią WAN. Dlaczego tylko
częściowo? Ponieważ, sama topologia sieci i jej konfiguracja zapewnia tylko
i wyłącznie możliwość przesyłania w niej bitów informacji, ale jak to było
powiedziane wcześniej (zob. 8.4.1), istnieje potrzeba by tę informację poka-
wałkować, a następnie wysłać do miejsca docelowego. I właśnie adresowanie
jest zapewniane poprzez jeden z dwu protokołów wchodzących w skład pro-
tokołu TCP/IP, a mianowicie protokół IP.
Można zastosować tu pewną analogię do wysyłania zwykłego listu. List
ten aby dotarł na miejsce musi posiadać adres, również w dobrym tonie
jest podać informację o nadawcy. Protokół IP zapewnia, że dane dotrą
pod wskazany adres
2
, zatem można przyjąć, że jest on rodzajem koperty w
którą zostaje włożony list. Samo adresowanie komputerów w sieci, odbywa
się poprzez nadawanie im adresów cyfrowych. Jest to tak zwany numer IP,
w formacie czterech kolejnych bajtów oddzielonych kropkami, przykładowy
adres może mieć postać: 212.191.65.2. Administrator komputera, podłą-
czając go do sieci globalnej musi mu przypisać adres i od tego momentu
komputer ten będzie widziany ze świata pod tą cyfrową reprezentacją (zob.
również 8.4.4). Można zapytać, czy każdy numer składający się z czterech
kolejnych liczb z zakresu 0 . . . 255 jest prawidłowym adresem. Oczywiście
nie, po pierwsze dlatego, że taki numer już gdzieś w sieci może istnieć, czyli
może być nadany jakiemuś komputerowi, a przecież nie można wmeldować
1
W dalszej części będziemy mówili po prostu protokół TCP/IP, chociaż słowo stos jest
tutaj bardzo adekwatne, gdyż podkreśla fakt, że nie jest to pojedynczy protokół, lecz
dwa: TCP i IP.
2
Tak naprawdę, to jest to tylko częściowe wsparcie, resztę musi dostarczyć sprzęt i
odpowiednie oprogramowanie, jednak to protokół IP jest nośnikiem adresu i oczywiście
reszty informacji.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
228
Sieci komputerowe
sublokatora komuś na siłę, po drugie dlatego, że pewne numery są zastrze-
żone. Ogólnie rzecz biorąc, w celu podłączenia komputera do sieci globalnej,
należy zgłosić się do swojego dostawcy usługi (ang. Internet Provider), aby
nadał nam numer, bądź więcej jeśli istnieje taka potrzeba.
Pozostaje pytanie do czego służy drugi z protokołów, czyli TCP (ang.
Transmission Control Protocol). Dzięki niemu zapewniono niezawodne do-
starczanie danych. Realizuje on pozornie niemożliwe zadanie, używa ofero-
wanej przez IP zawodnej usługi do wysyłania danych, gwarantując przy tym
ich poprawne przesłanie. Każdy komunikat TCP jest kapsułkowany w da-
tagram IP
3
i wysyłany siecią. Gdy datagram dociera do węzła docelowego,
protokół IP przekazuje jego zawartość do TCP. Zauważmy, że chociaż TCP
używa IP do przenoszenia komunikatów, jednak oprogramowanie IP ich nie
czyta ani nie interpretuje traktując je po prostu jako dane. W ten sposób
TCP traktuje IP jak system komunikacyjny oparty na pakietach, który łączy
węzły na dwóch końcach połączenia. Natomiast protokół IP traktuje każdy
komunikat TCP jak zwykłe dane do przesłania. Protokół TCP nazywa się
protokołem transportowym, gdyż zapewnia połączenie bezpośrednio mię-
dzy programem na jednym komputerze a programem na drugim. Drugim
jego zadaniem jest poszatkowanie zbyt długich danych, oraz zapewnienie
odtworzenia ich po drugiej stronie w odpowiedniej kolejności. Wracając do
analogii z listami, możemy wyobrazić sobie, że mamy do dyspozycji wyłącz-
nie zwykłe koperty w których nie mieści się więcej niż kilka kartek, jednak
pragniemy przesłać więcej informacji np. maszynopis książki. W tym celu
pakujemy po kilka kartek do koperty, na niej umieszczamy kolejne numery
(protokół TCP), a następnie umieszczamy ją w innej kopercie z adresem od-
biorcy (protokół IP). Dzięki temu nawet jeśli któryś list zginie to odbiorca,
będzie wiedział który, a po otrzymaniu wszystkich będzie znał kolejność
składania kartek.
8.4.4
Usługa DNS
W chwili obecnej, gdy w sieci istnieją miliony podsieci i komputerów, trudno
posługiwać się tak niewygodnym do zapamiętania adresem jak numer. Dla
większości użytkowników dużo łatwiej zapamiętać nazwę www.math.uni.lodz.pl,
niż jej cyfrową postać 212.191.65.2. Stąd też w pewnym momencie powstało
zapotrzebowanie na usługę DNS (ang. Domain Name Service), która za-
mienia nazwy symboliczne – dużo łatwiejsze do zapamiętania, na fizyczny
3
„Kapsułkowany w datagram IP” oznacza „otoczony ramką IP i traktowany jako pa-
kiet IP”.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.5 Urządzenia sieci komputerowych
229
adres komputera w sieci. W chwili obecnej usługa ta realizowana jest po-
przez różnego rodzaju serwery
4
, do których można zaliczyć np. program
bind
dostępny na wszystkich odmianach systemów UNIX.
8.5
Urządzenia sieci komputerowych
Sieć to nie tylko idee i koncepcje związane z działaniem, ale także fizyczne
urządzenia bezpośrednio tworzące jej strukturę oraz sprzęt z niej korzysta-
jący.
8.5.1
Urządzenia transmisji
Urządzenia transmisji służą do przekazywania sygnałów przez sieć od nadawcy
do odbiorcy, są nimi wszelkiego rodzaju nośniki sygnału elektrycznego i tak
możemy wyróżnić:
Kabel koncentryczny (zwany również kablem BNC) Składa się z dwóch
współosiowych przewodów rozdzielonych izolatorem. Całość osłonięta
jest koszulką ochronną (rysunek 8.7). W swoim wyglądzie jest on
podobny do kabla antenowego od telewizora, lecz posiada inną im-
pedancję falową
5
. W chwili obecnej jest już technologią zanikającą,
wspominamy go tutaj z racji istniejących wciąż instalacji opartych o
ten kabel.
Skrętka Zbudowana jest z czterech par cienkich przewodów splecionych
razem parami. Skręcenie przewodów ze sobą ma na celu znoszenie
zakłóceń elektromagnetycznych (rysunek 8.8). Jest to obecnie naj-
powszechniejsza technologii budowy sieci w firmach czy nawet małych
sieci osiedlowych, głównie ze względu na niewielkie koszty kabla i urzą-
dzeń dostępowych jak karty sieciowe.
Światłowód Wewnątrz osłonki ochronnej znajduje się nośnik, którym nie
jest jak poprzednio miedź lecz szkło lub plastik o odpowiednio dobra-
nej strukturze (rysunek 8.9). Jest to nośnik o świetnych parametrach
przewodzenia, co za tym idzie o niskim tłumieniu, jednak jest on drogi
i trudny do instalacji, przez co stosowany wyłącznie przy profesjonal-
nych instalacjach.
4
Chodzi w tym miejscu o serwer jako usługę nie zaś konkretne fizyczne urządzenie.
5
Impedancja falowa jest technicznym pojęciem elektrotechnicznym, które można, w
pewnym uproszczeniu, opisać jako oporność przewodnika, w którym płynie prąd zmienny.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
230
Sieci komputerowe
1
2
3
Rysunek 8.7: Kabel koncentryczny.
Kabel koncentryczny. 1 — osłona, 2 — izolator, 3 — przewodnik.
Rysunek 8.8: Skrętka.
Skrętka.
„Powietrze” Oczywiście powietrze jako takie nie jest żadnym nośnikiem
niemniej jednak zastało przywołane w tym miejscu jako pewne ha-
sło. Poprzez „powietrze” niejako
6
podróżują fale elektromagnetyczne
o różnej częstotliwości, są to między innymi fale radiowe, podczer-
wone czy laserowe
7
. Te trzy rodzaje fal są coraz częściej spotykane
w sieciach komputerowych, podczerwień w biurach, gdzie nie ma ko-
nieczności bądź technicznej możliwości założenia okablowania. Radio
w biurach i sieciach osiedlowych, co prawda początkowy koszt insta-
lacji jest wyższy niż przy okablowaniu, jednak zwraca się on szybko
ze względu na elastyczność rozwiązania i brak konieczności konser-
wacji kabli. Laser zaś jest stosowany na większe odległości, jednak
jest on podatny na zakłócenia takie jak deszcz, mgła i inne tego typu
czynniki, przez co bywa zawodny.
8.5.2
Urządzenia dostępowe
Urządzenia dostępowe są to wszelkiego typu składniki sieci, których zada-
niem jest aktywny udział w jej działaniu. Zauważmy, że urządzenia trans-
6
Jeszcze raz podkreślamy przenośnię tego stwierdzenia, w rzeczywistości tylko fale
dźwiękowe mogą rozchodzić się w powietrzu.
7
Lasery stosowane do transmisji danych pracują w zakresie fal widzialnych.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.5 Urządzenia sieci komputerowych
231
1
2
3
Rysunek 8.9: Światłowód.
Światłowód. 1 — osłona, 2 — wypełnienie ochronne, 3 — przewodnik
światłowodowy.
misji miały charakter pasywny. Można wymienić następujące zadania reali-
zowane przez urządzenia dostępowe:
1. Obróbka danych, w celu dalszego wysłania ich w sieci. Zatem będzie
to porcjowanie na pakiety, ramki nadawanie adresów docelowych i
nadawczych itp.
2. Fizyczne wysyłanie tak sformatowanych danych poprzez konkretne
urządzenie transmisji.
3. Odbieranie danych, które są przeznaczone dla tego urządzenia.
Ze względu na sposób działania i niejako umiejscowienie w sieci wyróżnia
się następujące podstawowe urządzenia dostępowe:
Karta sieciowa Jest to element charakterystyczny dla sieci LAN, którego
zadaniem jest umożliwienie komputerowi wysyłania i odbioru sygna-
łów w tej sieci. Można mówić o kartach posiadających możliwość wy-
syłania sygnałów przez jedno lub kilka wymienionych urządzeń trans-
misji. Zatem można mówić o karcie przeznaczonej do skrętki, wypo-
sażonej w tym celu w złącze RJ-40, czy o karcie radiowej.
Routery spełniają podobną rolę jak karty sieciowe ale w sieciach WAN,
tam właśnie są podstawowymi urządzeniami dostępowymi. Jednak
analogii tej nie można posuwać zbyt daleko, gdyż routery są urzą-
dzeniami znacznie bardziej inteligentnymi od kart sieciowych, a ich
zadanie nie sprowadza się wyłącznie do przesłania dalej danych. Wy-
maga się od nich stwierdzenia którą drogą najlepiej (najszybciej) te
dane można posłać. Z powyższego wynika, że router nie musi był po-
łączony wyłącznie z jednym sąsiadem i rzeczywiście tak jest, na ogół
jeden router ma kilku a nawet kilkunastu sąsiadów i przez kilku z nich
może wysłać informację. Przypomina to trochę sytuację z jaką mamy
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
232
Sieci komputerowe
do czynienia w mieście: jest wiele takich punktów pomiędzy którymi
można się poruszać na różne sposoby. Nie jest jednak obojętne któ-
rędy pójdziemy, co więcej często jest to bardzo zmienne i zależne np.
od natężenia korków ulicznych.
Wzmacniaki Ograniczony zasięg sieci lokalnych wynika miedzy innymi ze
zjawiska tłumienia (słabnięcia) sygnałów elektrycznych w przewod-
niku wraz z przebywaną odległością. W celu redukcji tego ograni-
czenia stosuje się wzmacniaki, czyli urządzenia monitorujące sygnał
w przyłączonych do niego kablach, inna ich nazwa to koncentratory
(ang. hub). Po wykryciu sygnału w którymś z przewodników, przeka-
zuje jego wzmocnioną „kopię” do pozostałych. Wzmacniaki nie inter-
pretują formatów ramek ani adresów fizycznych, po prostu przesyłają
sygnały elektryczne z jednego miejsca do drugiego, dokonując przed-
tym jego wzmocnienia. Ponieważ koncentratory są obecnie bardzo
często wykorzystywane jako centralny punkt sieci wykonanej w topo-
logii gwiazdy (zob. 8.2.2), zapomina się o ich podstawowej cesze jaką
jest wzmacnianie.
Mosty (ang. bridge) umożliwiają połączenie dwóch osobnych segmentów
sieci, jednak w przeciwieństwie do wzmacniaka, przekazuje tylko pewne
ramki, a zatem przekazywanie to jest inteligentne. Przykładowo je-
śli komputer A z segmentu 1 sieci przesyła informacje do komputera
B to wzmacniak przekaże sygnały z tego segmentu do drugiego bez
względu na to, w którym z nich jest B. Jeśli natomiast segmenty po-
łączymy mostem, wówczas sygnały zostaną przekazane z jednego seg-
mentu do drugiego tylko wtedy, gdy komputery A i B będą w różnych
segmentach. Dzięki temu generowany jest dużo mniejszy ruch w obu
segmentach, podnosząc tym samym wydajność sieci.
Przełączniki (ang. switch) stanowią rozwinięcie koncepcji mostów. Za-
sadnicza różnica pojawia się w sposobie pracy. Otóż przełącznik po-
trafi zestawiać indywidualne i niezależne połączenia dwóch kompute-
rów. Mówiąc obrazowo, składa się on z wielu „minimostów” łączących
komputery na zasadzie każdy-z-każdym i wybierających w danej chwili
tylko potrzebne połączenie.
Rysunek 8.10 przedstawia obrazowo koncepcję WAN-u wraz z zaadreso-
wanymi routerami, oraz stacjami klienckimi podłączonymi do sieci rozległej
na różne sposoby.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
8.6 Zadania
233
Rysunek 8.10: Ogólny schemat komputerów w sieci.
8.6
Zadania
1. Omów główne rodzaje topologii sieci komputerowych.
2. Omów różnicę pomiędzy architekturą klient-serwer a architekturą Peer-
to-Peer.
3. Wymień i omów cechy znanych ci urządzeń transmisji.
4. Co to jest adres IP i usługa DNS?
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
234
Sieci komputerowe
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Dodatek A
Podstawowe jednostki
i pojęcia w informatyce
Informatyka podobnie jak każda współczesna wiedza rozwijająca się dyna-
micznie posiada własne słownictwo i swoje symbole, którymi się posługuje.
W dodatku tym zawarliśmy, naszym zdaniem, najważniejsze z nich, najczę-
ściej używane, które stanowią tylko wybór z bogactwa słownictwa informa-
tycznego.
Poniższy wykaz został sporządzony w porządku alfabetycznym.
bajt — (ang. byte) jest zbiorem 8-miu bitów, zatem bajt informacji to
osiem dowolnych wartości z dwuelementowego zbioru wartości {0, 1}.
Dla przykładu następujące dwa ciągi zero-jedynkowe są bajtami in-
formacji 01101101, 11101100, należy zauważyć, że bajty zawsze są za-
pisywane w postaci ośmiu bitów, niezależnie od tego czy na początku
są zera czy też nie. Jako oznaczenie dla jednostki bajtu przyjęto dużą
literę „B”.
bit — (ang. bit) jest najmniejszą jednostką miary informacji, bitem może
przyjmować jedną z dwu wartości ze zbioru {0, 1}. Należy zwrócić
uwagę, że zero w tym wypadku również niesie ze sobą informację,
podobnie jak jedynka. Jako oznaczenie dla jednostki bitu przyjęto
małą literę „b”.
host — słowo oznaczające komputer, zwykle w odniesieniu do komputera
podłączonego do sieci Internet.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
236
Podstawowe jednostki i pojęcia w informatyce
interfejs — (ang. interface) określa urządzenie, które jest pewnego ro-
dzaju pośrednikiem umożliwiającym komunikację dwu lub więcej urzą-
dzeń. Np. drukarka komunikuje się z komputerem poprzez port rów-
noległy, można powiedzieć, że jest to interfejs równoległy.
Kb, KB — są to jednostki wyrażające wielokrotności odpowiednio bitu i
bajtu, przy czym należy je czytać k-bit bądź bajt (tj. najpierw samo
„k” potem bit bądź bajt), nie należy czytać ich „kilo”. Słowo kilo
zgodnie z układem jednostek i miar SI określa wielokrotność 1000, zaś
literka „K” (zwróćmy uwagę, że jest to duże K a nie małe k — ozna-
czające kilo) oznacza wielokrotność 1024 co jest równe 2
10
. Jednak
bardzo często mówi się kilo, gdyż jest to znacznie łatwiejsza forma do
wypowiedzenia.
kompatybilny — (ang. compatible) oznacza zgodny, czyli mówiąc, że ja-
kieś urządzenie jest kompatybilne z innym mamy na myśli, że jest
zgodne w jakimś sensie. Dla przykładu mówimy że procesory firmy
AMD są kompatybilne na poziomie listy z procesorami firmy INTEL,
co oznacza, że z powodzeniem możemy używać oprogramowania prze-
znaczonego do platformy INTEL na platformie AMD
1
.
najmłodszy bit — jest to bit pierwszy od prawej strony bajtu.
najstarszy bit — jest to bit znajdujący się najdalej po lewej stronie bajtu.
1
Jednak zgodność ta występuje w ramach pewnego podzbioru rozkazów, i tak zarówno
np. Pentium 4 ma pewną klasę rozkazów, które nie występują w procesorach AMD, i
procesory AMD mają rozkazy klasy SSE, które nie występują w procesorach INTEL.
Jeśli program będzie wykorzystywał te specyficzne rozkazy to oczywiście nie może zostać
uruchomiony na obu tych procesorach.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Dodatek B
Kody ASCII
Tabele zawiera wykaz podstawowych znaków i przypisanych im kodów ASCII.
Dec
Hex
Znak
Dec
Hex
Znak
Dec
Hex
Znak
Dec
Hex
Znak
32
20
SPC
33
21
!
34
22
”
35
23
#
36
24
$
37
25
%
38
26
&
39
27
’
40
28
(
41
29
)
42
2A
*
43
2B
+
44
2C
,
45
2D
-
46
2E
.
47
2F
/
48
30
0
49
31
1
50
32
2
51
33
3
52
34
4
53
35
5
54
36
6
55
37
7
56
38
8
57
39
9
58
3A
:
59
3B
;
60
3C
<
61
3D
=
62
3E
>
63
3F
?
64
40
@
65
41
A
66
42
B
67
43
C
68
44
D
69
45
E
70
46
F
71
47
G
72
48
H
73
49
I
74
4A
J
75
4B
K
76
4C
L
77
4D
M
78
4E
N
79
4F
O
80
50
P
81
51
Q
82
52
R
83
53
S
84
54
T
85
55
U
86
56
V
87
57
W
88
58
X
89
59
Y
90
5A
Z
91
5B
[
92
5C
\
93
5D
]
94
5E
^
95
5F
_
96
60
‘
97
61
a
98
62
b
99
63
c
100
64
d
101
65
e
102
66
f
103
67
g
104
68
h
105
69
i
106
6A
j
107
6B
k
108
6C
l
109
6D
m
110
6E
n
111
6F
o
112
70
p
113
71
q
114
72
r
115
73
s
116
74
t
117
75
u
118
76
v
119
77
w
120
78
x
121
79
y
122
7A
z
123
7B
{
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
238
Kody ASCII
Dec
Hex
Znak
Dec
Hex
Znak
Dec
Hex
Znak
Dec
Hex
Znak
124
7C
—
125
7D
}
126
7E
∼
127
7F
Del
Tabela zawiera wykaz niedrukowlanych znaków ASCII oraz ich kody.
Dec Hex
Znak
znaczenie (ang.)
znaczenie (pol.)
0
0
Ctrl-@ (NUL)
null
brak znaku
1
1
Ctrl-A (SOH)
start of heading
początek nagłówka
2
2
Ctrl-B (STX)
start of text
początek tekstu
3
3
Ctrl-C (ETX)
end of text
koniec tekstu
4
4
Ctrl-D (EOT)
end of transmission
koniec transmisji
5
5
Ctrl-E (ENQ)
enquiry
zapytanie
6
6
Ctrl-F (ACK)
ackonowledge
potwierdzenie
7
7
Ctrl-G (BEL)
bell
sygnał akustyczny
8
8
Ctrl-H (BS)
backspace
cofnięcie
9
9
Ctrl-I (HT)
horizontal tab
tabulacja pozioma
10
A
Ctrl-J (LF)
line feed
przesunięcie o wiersz
11
B
Ctrl-K (VT)
vertical tab
tabulacja pionowa
12
C
Ctrl-L (FF)
form feed
wysunięcie strony
13
D
Ctrl-M (CR)
carriage return
powrót karetki
14
E
Ctrl-N (SO)
shift out
przełączenie na zestaw
niestandardowy
15
F
Ctrl-O (SI)
shift in
przełączenie na zestaw
standardowy
16
10
Ctrl-P (DLE)
data link escape
znak sterujący
transmisją
17
11
Ctrl-Q (DC1)
device controls
znak sterowania
urządzeniami
18
12
Ctrl-R (DC2)
19
13
Ctrl-S (DC3)
20
14
Ctrl-T (DC4)
21
15
Ctrl-U (NAK)
negative
negatywne potwierdzenie
acknowledgment
22
16
Ctrl-V (SYN)
synchronous
synchronizacja
23
17
Ctrl-W (ETB) end of transmission
koniec bloku transmisji
block
24
18
Ctrl-X (CAN)
cancel
kasowanie
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
239
Dec Hex
Znak
znaczenie (ang.)
znaczenie (pol.)
25
19
Ctrl-Y (EM)
end of medium
fizyczne zakończenie
nośnika
26
1A
Ctrl-Z (SUB)
substitute
zastąpienie
27
1B
Ctrl-[ (ESC)
escape
znak unikowy
28
1C
Ctrl- (FS)
file separator
separator plików
29
1D
Ctrl-] (GS)
grou separator
separator grup
30
1E
Ctrl-ˆ(RS)
record separator
separator rekordów
31
1F
Ctrl- (US)
united separator
separator połączony
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
240
Kody ASCII
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
242
Kodowanie polskich znaków
Dodatek C
Kodowanie polskich znaków
Standard
ą
ć
ę
ł
ń
ó
ś
ź
ż
ISO 8859-2
1
B1
E6
EA
B3
F1
F3
B6
BC
BF
CP 1250
2
B9
E6
EA
B3
F1
F3
9C
9F
BF
CP 852
3
A5
86
A9
88
E4
A2
98
AB
BE
Mazowia
86
8D
91
92
A4
A2
9E
A6
A7
Cyfromat
90
91
92
93
94
95
96
98
97
IEA-Swierk
A0
9B
82
9F
A4
A2
87
A8
91
Ventura
96
94
A4
A7
91
A2
84
82
87
ELWRO-Junior
E1
E3
E5
EC
EE
EF
F3
FA
F9
AmigaPL
E2
EA
EB
EE
EF
F3
F4
FA
FB
TeXPL
A1
A2
A6
AA AB
F3
B1
B9
BB
Atari-Calamus
D1
D2
D3
D4
D5
D6
D7
D8
D9
CorelDraw!
E5
EC
E6
C6
F1
F3
A5
AA
BA
Unicode
105 107 119 142 144
F3
15B 17A 17C
Standard
Ą
Ć
Ę
Ł
Ń
Ó
Ś
Ź
Ż
ISO 8859-2
4
A1
C6
CA
A3
D1
D3
A6
AC
AF
CP 1250
5
A5
C6
CA
A3
D1
D3
8C
8F
AF
CP 852
6
A4
8F
A8
9D
E3
E0
97
8D
BD
Mazowia
8F
95
90
9C
A5
A3
98
A0
A1
Cyfromat
80
81
82
83
84
85
86
88
87
IEA-Swierk
8F
80
90
9C
A5
99
EB
9D
92
Ventura
97
99
A5
A6
92
8F
8E
90
80
ELWRO-Junior
C1
C3
C5
CC
CE CF
D3
DA
D9
AmigaPL
C2
CA CB
CE
CF
D3
D4
DA
DB
TeXPL
81
82
86
8A
8B
D3
91
99
9B
Atari-Calamus
C1
C2
C3
C4
C5
C6
C7
C8
C9
CorelDraw!
C5
F2
C9
A3
D1
D3
FF
E1
ED
Unicode
104 106 118 141 143
D3 15A
179
17B
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Dodatek D
Organizacje standaryzujące
Dodatek ten zawiera listę z krótkim opisem organizacji zajmujących się
ustanawianiem standardów związanych z różnymi technologiami informa-
tycznymi. Odwołania do tych organizacji można znaleźć w wielu miejscach
niniejszego opracowania.
ANSI (ang. The American National Standards Institute) — Amerykański
Narodowy Instytut Normalizacji jest to prywatna organizacja nieko-
mercyjna, której celem jest ułatwienie rozwoju różnych nowych tech-
nologii. Osiągane jest to poprzez koordynację i publikowanie nieobli-
gatoryjnych standardów. Zauważmy, że użyte zostało słowo nieobliga-
toryjnych, co oznacza, że to co opublikuje ta organizacja nie jest dla
nikogo obowiązkowe i nie ma konieczności posługiwania się tymi a nie
innymi normami. Niemniej jednak bardzo często standardy te stają
się później obowiązującymi na mocy ustaleń innych organizacji, dzieje
się tak głównie z uwagi na fakt, że ANSI w Stanach Zjednoczonych
reprezentuje organizacje ISO i IEC.
IEEE (ang. The Institute of Electrical and Electronic Engineers) — In-
stytut Elektryków i Elektroników jest organizacją zajmującą się de-
finiowaniem i publikowaniem standardów telekomunikacyjnych. Dla
przykładu jednym z jej produktów jest seria standardów 802, która
określa normy dla sieci LAN i MAN.
ISO (ang. International Organization for Standarization)
1
— Międzynaro-
1
Formalnie poprawnym skrótem jest IOS jednak, zarówno świat jak i sama organizacja
woli łatwiejszy do zapamiętania akronim ISO. Skrót ISO pochodzi od greckiego słowa isos
oznaczającego równy lub standardowy.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
244
Organizacje standaryzujące
dowa Organizacja Normalizacyjna została utworzona w 1946 roku w
Genewie, gdzie do dziś znajduje się jej siedziba. Celem tej organizacji
jest ustalanie wszelkich norm międzynarodowych, do tego celu została
wynajęta przez ONZ. ISO jest potężną instytucją składającą się obec-
nie z ponad dziewięćdziesięciu różnych mniejszych organizacji, zakres
jej działania jest również imponujący, gdyż zawiera w sobie wszystkie
dziedziny ludzkiej nauki za wyjątkiem elektryki i elektroniki.
IEC (ang. International Electrotechnical Commission) — Międzynarodowa
Komisja Elektrotechniczna została utworzona w 1909 roku i mieści
się w Genewie. Jej celem jest ustalanie międzynarodowych norm w
zakresie elektryki i elektroniki, zatem uzupełnia zakres działalności
organizacji ISO.
IAB (ang. The Internet Architecture Board) — Komisja Architektury In-
ternetu, znana poprzednio jako Komisja Działań Internetu (ang. In-
ternet Activities Board) jest organizacją, której celem jest zarządzanie
techniczną stroną rozwoju Internetu. W jej skład wchodzą dwie grupy
robocze: Grupa Robocza ds. Technicznych Internetu (ang. Internet
Engineering Task Force (IETF)) oraz Grupa Robocza ds. Nauko-
wych Internetu (ang. Internet Research Task Force (IRTF)). Zada-
niem grupy naukowej jest badanie nowych technologii w zakresie ich
przydatności do rozwoju bądź poprawienia jakości Internetu. Zada-
niem grupy technicznej jest wdrażanie i testowanie nowych technologii
jak i opieka nad istniejącą infrastrukturą.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Dodatek E
Rozwiązania zadań
W dodatku tym znajdują się odpowiedzi lub rozwiązania do zadań zamiesz-
czonych w publikacji. Zamieszczamu odpwiedzi i rozwiązania wyłącznie do
zadań obliczeniowych, bądź problemowych. Wszystkie odpowiedzi, które
zawarte są wprost w treści rozdziału, są pomijane.
E.1
Rozwiązania do rozdziału 2
1. Nad znakami równości umieszczono numery praw z których korzy-
stano.
2. W każdym podpunkcie pierwsza liczba zapisana jest w systemie dzie-
siętnym, druga — dwójkowym, trzecia — ósemkowym, czwarta —
szesnastkowym.
a) 172 →
10101100
→
254
→
AC
b) 517 → 1000000101 → 1005 →
205
c) 778 → 1100001010 → 1412 → 30A
d)
13
→
1101
→
15
→
D
e)
76
→
1001100
→
114
→
4C
f)
107
→
1101011
→
153
→
6B
g) 300 →
100101100
→
454
→ 12C
h) 201 →
11001000
→
310
→
C8
i)
472
→
111011000
→
730
→ 1D8
j)
802
→ 1100100010 → 1442 →
322
3. W każdym podpunkcie pierwsza liczba zapisana jest w systemie dwój-
kowym, druga — ósemkowym, trzecia — szesnastkowym, czwarta —
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
246
Rozwiązania zadań
dziesiętnym.
a)
11100 →
34 →
1C →
28
b)
1011110001 → 1361 → 2F1 →
544
c)
10001010001 → 2121 →
451 → 1105
d)
100100100 →
444 →
124 →
292
e)
1110011100 → 1634 → 39C →
805
f)
101110001 →
561 →
171 →
369
g)
1001001100 → 1114 → 24C →
578
h)
101010000 →
520 →
150 →
336
i)
10100001 →
241 →
A1 →
161
j)
1000101 →
105 →
45 →
69
4. W każdym podpunkcie pierwsza liczba zapisana jest w systemie dwój-
kowym, druga — ósemkowym, trzecia — szesnastkowym, czwarta —
dziesiętnym.
a)
F2 →
11110010 →
362 →
242
b)
11F →
100011111 →
437 →
287
c)
AAA → 101010101010 → 5252 → 2730
d)
100 →
100000000 →
400 →
256
e)
1AB →
110101011 →
653 →
427
f)
123 →
100100011 →
443 →
291
g)
FF →
11111111 →
377 →
255
h)
F0 →
11110000 →
360 →
240
i)
BAB → 101110101011 → 5653 → 2987
j)
307 →
110111 →
67 →
55
5. W każdym podpunkcie pierwsza liczba zapisana jest w systemie ósem-
kowym, druga — dwójkowym, trzecia — szesnastkowym, czwarta —
dziesiętnym.
a) 123 →
1010011 →
53 →
83
b) 457 → 100101111 → 12F → 303
c)
177 →
1111111 →
7F → 127
d)
65 →
110101 →
25 →
37
e)
22 →
10010 →
12 →
18
f)
10 →
1000 →
8 →
8
g)
27 →
10111 →
17 →
23
h)
55 →
101101 →
2D →
45
i)
222 →
10010010 →
92 → 146
j)
512 → 101001010 → 14A → 330
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
E.1 Rozwiązania do rozdziału 2
247
6. W każdym podpunkcie pierwsza liczba zapisana jest w systemie sió-
demkowym, druga zaś w piątkowym.
a) 565 → 2023
b) 100 →
144
c)
62 →
134
d)
12 →
14
e) 166 →
342
f)
306 → 1103
g) 255 → 1023
h)
32 →
143
i)
836 → 3113
j)
56 →
131
7. W każdym podpunkcie pierwsza liczba jest zapisana w systemie piąt-
kowym, druga zaś w jedenastkowym.
a) 1234 → 167
b) 4222 →
45
c) 2131 → 245
d) 1421 → 140
e) 3123 → 346
f)
1121 → 137
g) 2041 → 227
h) 4131 → 452
i)
3211 → 362
j)
3114 → 342
8. W każdym podpunkcie pierwsza liczba jest zapisana w systemie trzy-
nastkowym, druga zaś w dziewiątkowym.
a)
C99 → 2710
b)
2A5 →
553
c)
91 →
141
d)
65 →
102
e) 3BC →
772
f)
910 → 1874
g)
B7 →
176
h)
18 →
23
i)
301 →
624
j)
40C →
800
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
248
Rozwiązania zadań
E.2
Rozwiązania do rozdziału 3
1. W każdym podpunkcie pierwsza liczba jest całkowitą liczbą zapisaną
w systemie dziesiętnym, druga zaś odpowiadającą jej liczbę dwójkową
w notacji znak-moduł.
a)
-20 →
10010100
b)
+20 →
00010100
c)
+47 →
00101111
d)
-18 →
10010010
e)
-37 →
00100101
f)
-128 → 1000000010000000
g) +372 → 0000000101110100
h)
-420 → 1000000110100100
i)
-42 →
10101010
j)
-15 →
10001111
2. W każdym podpunkcie pierwsza liczba jest całkowitą liczbą zapisaną
w systemie dziesiętnym, druga zaś odpowiadającą jej liczbę dwójkową
w notacji uzupełnień do dwu.
a)
-20 →
11101100
b)
+87 →
01010111
c)
+65 →
01000001
d)
-18 →
11101110
e)
+27 →
00011011
f)
-99 →
10011101
g)
-300 →
11010100
h)
+77 →
01001101
i)
-77 →
10110011
j)
+503 → 0000000111110111
3. W każdym podpunkcie pierwsza liczba jest rzeczywistą liczbą dzie-
siętną, druga zaś rzeczywistą dwójkową.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
E.2 Rozwiązania do rozdziału 3
249
a)
0.5625 =
0.1001
b)
7.4375 =
111.0111
c) 11.0625 = 1011.0001
d)
4.6875 =
100.1011
e)
2.8125 =
10.1101
f)
13.875
= 1101.111
g)
9.625
= 1001.1010
h) 14.75
= 1110.11
i)
15.375
= 1111.011
j)
5.0625 =
101.0001
k)
3.3125 =
11.0101
l)
8.1875 = 1000.0011
4. W każdym podpunkcie pierwsza liczba jest rzeczywistą liczbą dwój-
kową, druga zaś rzeczywistą dziesiętną.
a) 1111.01
= 15.25
b) 1011.101
= 11.625
c) 1000.111
=
8.875
d)
1.1011 =
1.6875
e)
0.1111 =
0.9375
f)
1100.0001 = 12.0625
g)
100.0111 =
4.4375
h) 1001.001
=
9.125
i)
101.1101 =
5.8125
j)
10.1001 =
2.5625
k) 1101.011
= 13.375
l)
1010.1
= 10.5
5. W każdym podpunkcie pierwsza liczba jest rzeczywistą liczbą dwój-
kową zapisaną zgodnie z formatem opisanym w poleceniu ćwiczenia,
druga zaś rzeczywistą dziesiętną.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
250
Rozwiązania zadań
a) 01000000 =
+ 0.01171875
b) 10100101 =
- 0.3125
c)
00010010 =
+ 0.033203125
d) 10101001 =
- 5.0
e)
00000100 =
+ 0.125
f)
10100010 =
- 0.0390625
g) 01111101 = + 120.0
h) 10001110 =
- 128.0
i)
00101011 =
+ 20.0
j)
10011111 =
- 288.0
k) 01010110 =
+ 3.25
l)
10000011 =
- 0.0625
6. Tabelki ruchów.
a)
Stan
Zawartość
taśmy
s
b
a
b
a
t
b
a
a
b
b
.
s
b
b
b
a
t
b
a
a
b
b
.
s
b
b
a
a
t
b
a
a
b
b
.
s
b
b
a
b
t
b
a
a
b
b
.
s
b
b
a
b
a
b
a
a
b
b
.
s
b
b
a
a
a
b
a
a
b
b
.
s
b
b
a
a
b
b
a
a
b
b
.
s
b
b
a
a
b
a
a
a
b
b
.
s
b
b
a
a
b
a
b
a
b
b
.
s
b
b
a
a
b
a
b
b
b
b
.
s
b
b
a
a
b
a
b
b
a
b
.
s
b
b
a
a
b
a
b
b
a
a
.
k
b
b
a
a
b
a
b
b
a
a
.
b)
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
E.3 Rozwiązania do rozdziału 4
251
Stan
Zawartość
taśmy
s
b
b
a
t
a
a
b
b
t
a
.
s
b
b
a
t
a
a
b
b
t
a
.
s
b
b
a
t
a
a
b
b
t
a
.
1
b
b
a
t
a
a
b
b
t
a
.
1
b
b
a
t
a
a
b
b
t
a
.
1
b
b
a
t
a
a
b
b
t
a
.
1
b
b
a
t
a
a
a
b
t
a
.
1
b
b
a
t
a
a
a
a
t
a
.
s
b
b
a
t
a
a
a
a
t
a
.
s
b
b
a
t
a
a
a
a
t
a
.
k
b
b
a
t
a
a
a
a
t
a
.
c)
Stan
Zawartość
taśmy
s
a
a
b
t
a
b
t
b
.
s
a
a
b
t
a
b
t
b
.
s
a
a
b
t
a
b
t
b
.
1
a
a
b
a
a
b
t
b
.
1
a
a
a
a
a
b
t
b
.
1
a
a
a
a
a
b
t
b
.
1
a
a
a
a
a
b
t
b
.
1
a
a
a
a
a
a
t
b
.
2
a
a
a
a
a
a
a
b
.
2
a
a
a
a
a
b
b
b
.
2
a
a
a
a
a
b
b
b
.
2
a
a
a
a
a
b
b
b
.
k
a
a
a
a
a
b
b
b
.
E.3
Rozwiązania do rozdziału 4
1.
a) 1100
b) 0111
c) 1111
d) 0010
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
252
Rozwiązania zadań
2.
a) 0011
b) 1011
c) 0111
d) 1000
3.
a) Błąd podczas transmisji.
b) Transmisj poprawna.
c) Błąd podczas transmisji.
d) Błąd podczas transmisji.
E.4
Rozwiązania do rozdziału 5
1. Przykład E.1 prezentuje wersję iteracyjną, zaś E.2 wersję rekuren-
cyjną.
Przykład E.1. Funkcja obliczająca potęgę — podejście itera-
cyjne.
potega_i(x, y)
begin
w := 1;
while (y > 0)
begin
w := w * x;
y := y - 1;
end
potega_i := w;
end
Przykład E.2. Funkcja obliczająca potęgę — podejście reku-
rencyjne.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
E.4 Rozwiązania do rozdziału 5
253
potega_r(x, y)
begin
if (y=0)
w := 1;
else
w := x * potega_r(x, y-1);
potega_r := w;
end
2. Schemat blokowy dla iteracyjnego algorytmu obliczania potęgi z po-
przedniego zadania pokazany jest na rysunku 2.
Rysunek E.1: Schamat blokowy algorytmu obliczającego potęgę.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
254
Rozwiązania zadań
3. Algorytm zapisany w postacji pseudo-jezyka podany jest w przykła-
dzie E.3. Algorytm ten realizuje wyznaczanie Największego Wspól-
nego Dzielnika dwu liczb naturalnych.
Przykład E.3. Algorytm wyznaczania NWD.
nwd(x, y)
begin
while (a != b)
begin
if (a > b) then
a := a - b
else
b := b - a
end
nwd := a
end
4. Funkcja wyszukiwania połówkowego zrealizowany rekurencyjnie jest
przedstawiony w przykładzie E.4. Pierwsze wywołanie takiej funkcji
dla tablicy 10-cio elementowej o nazwie tablica, gdzie chcemy zna-
leźć element o wartości 45, będzie miało postać szukaj(45, 1, 10,
tablica)
. Funkcja ta zwróci indeks znalezionego elementu w przy-
padku sukcesu oraz wartość −1 w przypadku braku poszukiwanego
elementu w tablicy.
Przykład E.4. Rekurencyjna funkcja wyszukiwania połówko-
wego.
szukaj(co, start, koniec, tablica)
begin
if (start > koniec)
szukaj := -1
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
E.4 Rozwiązania do rozdziału 5
255
else
begin
polowa := (start + koniec) / 2
if (tablica[polowa] = co)
szukaj := polowa
else
if (tablica[polowa] < co)
szukaj := szukaj(co, start, polowa-1, tablica)
else
szukaj := szukaj(co, start+1, koniec, tablica)
end
end
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
256
Rozwiązania zadań
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Bibliografia
[AD89]
M. Adiba and C. Delobel. Relacyjne bazy danych. WNT, War-
szawa, 1989.
[B
+
99]
M. Beck et al. Linux kernel jądro systemu. MIKOM, Warszawa,
1999.
[Bab89] R. L. Baber. O oprogramowaniu inaczej. Biblioteka inżynierii
oprogramowania. WNT, Warszawa, 1989.
[Bac95] M. J. Bach. Budowa systemu operacyjnego UNIX. WNT, War-
szawa, 1995.
[Bie96]
Janusz Biernat. Arytmetyka komputerów. PWN, Warszawa, 1996.
[Chu41] A. Church. The calculi of lambda-conversion. Ann. of Math.
Studies, 6, 1941.
[Com00] D. E. Comer. Sieci komputerowe i intersieci. WNT, 2000.
[Coo70] E. F. Cood. A relational model of data for large shared data
banks. Comm. ACM, 13(6):377–387, 1970.
[DuC01] B. DuCharme. Operating Systems Handbook. McGraw-Hill, 2001.
[Fe98]
Z. Fryźlewicz and Z. Huzar etc. ADA 95. Helion, 1998.
[FLB77] G. Goos F. L. Bauer. Informatyka. WNT, Warszawa, 1977.
[Hal96]
F. Halsall. Data Communications, Computer Networks and Open
Systems.
Electronic Systems Engineering Systems. Addison-
Wesley, 1996.
[Har00] D. Harel. Rzecz o istocie informatyki, algorytmika. Klasyka infor-
matyki. WNT, 2000.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
258
BIBLIOGRAFIA
[Hed87] R. Hedtke. Systemy mikroprocesorowe. WNT, Warszawa, 1987.
[Kle36]
S. C. Kleene. General recursive functions of natural numbers.
Mathematische Annalen, 112:727–742, 1936.
[Kąc86] E. Kącki. Elektroniczna technika obliczeniowa. Matematyka dla
politechnik. PWN, Warszawa, 1986.
[LE94]
A. M. Lister and R. D. Eager. Wprowadzenie do systemów ope-
racyjnych. WNT, Warszawa, 1994.
[Lig92]
R. Ligonni´ere. Prehistoria i historia komputerów. Ossolineum,
Wrocław, 1992.
[Mac99] B. J. MacLennan. Principles of Programming Languages. Oxford
University Press, New York, 1999.
[Mar54] A. Markow. Theory of algorithms. Trudy Mat. Inst. Steklov., 42,
1954.
[MI86]
S. Matwin M. Iglewski, J. Madey. Pascal. WNT, Warszawa, 1986.
[Nau79] P. Naur. Zarys metod informatyki. WNT, Warszawa, 1979.
[Ove01] M. L. Overton. Numerical Computing with IEEE Floating Point
Arithmetic. SIAM, Philadelphia, 2001.
[RS87]
A. Rydzewski and K. Sacha. Mikrokomputer elementy, budowa,
działanie. NOT SIGMA, Warszawa, 1987.
[S
+
94]
M. M. Sysła et al. Elementy informatyki. Wydawnictwo Naukowe
PWN, Warszawa, 1994.
[Sha48] C. Shannon. A mathematical theory of communication. The Bell
System Technical Journal, 27:379–423, July 1948.
[Ste98]
W. R. Stevens. Biblia TCP/IP, Protokoły, volume Tom 1. Wy-
dawnictwo RM, Warszawa, 1998.
[Str00]
B. Stroustrup. Język C++. Klasyka informatyki. WNT, War-
szawa, 2000.
[Tur36]
A. M. Turing. On computable numbers, with an application to the
entscheidungsproblem. Proc. London Math. Soc., 2(42):230–265,
1936.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
BIBLIOGRAFIA
259
[Wir71a] N. Wirth. Program development by step-wise refinement. Comm.
ACM, 14(4):221–227, 1971.
[Wir71b] N. Wirth. The programming language pascal. Acta Informat.,
1(1):35–63, 1971.
[Wir01] N. Wirth. Algorytmy + struktury danych = programy. Klasyka
informatyki. WNT, 2001.
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
Indeks
ścisła typizacja, 168
światłowód, 229
Łukasiewicz, Jan, 170
łączenie
dynamiczne, 179
statyczne, 179
4.3 BSD, 211
Abakus, 17
ADA, 22, 178
Ada Augusta hrabina Lovelace, 21
Address Unit, 84
addytywny system liczbowy, 46
adres
efektywny, 84, 91
adresowanie, 90
bezpośrednie
z pamięci, 91
z rejestru, 91
natychmiastowe, 91
pośrednie
przez rejestr bazowy, 91
przez rejestr bazowy i indek-
sowy, 92
przez rejestr bazowy i offset,
92
przez rejestr bazowy, indeksowy
i offset, 92
przez rejestr indeksowy, 92
przez rejestr indeksowy i off-
set, 92
układów wejścia/wyjścia, 92
Aiken, Howard, 23
al-Chorezmi, Muhammad, 18
alfabet, 71, 183
Algebra Boole’a, 100
algebra Boole’a, 39
algorytm, 15, 17, 18, 129
Euklidesa, 18, 129
obliczeniowy, 143
sortowania, 144
algorytmika, 29
algorytmy, 29
genetyczne, 35
Altair, 24
ALU, 83
analiza
algorytmów, 131
analiza złożoności, 153
ANSI, 243
architektura
fizyczna komputera, 190
von neumannowska, 24
architektura klient-serwer, 223
architektura sieci, 218
ARPA, 32
ARPANET, 32
Arythmetic Logic Unit, 83
arytmometr, 24
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
INDEKS
261
asemblacja, 178
asembler, 96, 178
AU, 84
AX (AH/AL), 86
B-code, 181
Babbage, Charles, 19
Backus, John, 160, 183
bajt, 235
bazy danych, 30
hierarchiczne, 30
obiektowe, 30
relacyjne, 30
sieciowe, 30
Bell, 22
Berners-Lee, Tim, 33
biblioteki, 178
dzielone, 179
systemowe, 178
bit, 235
bit parzystości, 121
Boole, George, 39
BP, 87
bramka
AND, 75
NAND, 75
NOR, 75
NOT, 75
OR, 75
bramka logiczna, 75
bridge, 232
Bull, 22
BX (BH/BL), 86
Byte-Code, 181
cache, 82
CD-R, 82
CD-R/W, 82
cecha, 110
Cerf, Vinton, 33
Chomsky, Noam, 183
Church, A., 130
Church, Alonzo, 29
Codd, E. F., 30
Colmerauer, Alain, 172
Colos I, 23
Colos II, 23
Computer Science, 16
CRC, 125
CS, 86
CX (CH/CL), 86
Cyclic Redundancy Code, 125
cyfra, 46
cyfrowe układy scalone, 75
cykl, 84
odczytu, 84
pobrania, 84
wykonania, 85
zapisu, 85
cykl pracy procesora, 84
cykliczny kod nadmiarowy, 125
część wspólna zbiorów, 136
czas dostępu, 81
datagram IP, 228
DEC, 210
deklaracja, 166
Delphi, 163
DI, 87
diagram przejść, 71
diagramy
składni, 185
DNS, 228
dopisanie elementu do pliku, 137
dostęp
swobodny, 133
DS, 86
dwuelementowa algebra Boole’a, 44
DX (DH/DL), 86
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
262
INDEKS
działania arytmetyczno–logiczne, 24
dziedziczenie, 169
EDSAC, 24
EDVAC, 24
efektywność algorytmów, 153
elementy języka programowania, 159
ENIAC, 23
enkapsulacja danych, 210
EOT, 224
ES, 87
etykieta, 98
Euklides, 18
flaga
kierunku, 88
parzystości, 88
pomocnicza, 88
pracy krokowej, 88
przeniesienia, 88
przepełnienia, 89
zera, 88
zezwolenia na przerwanie, 88
znaku, 88
FLAGS, 87
Floating Point Unit, 83
FPU, 83
funkcja, 148
rekurencyjna, 148
funkcja następnego ruchu, 71
Gates, Bill, 25, 204
gliniane tabliczki, 17
GNU Prolog (gprolog) jest wersją na
licencji Open Source., 175
grafika komputerowa, 31
gramatyka
bezkontekstowa, 183
formalna, 183
kontekstowa, 183
GUI, 202, 205
Hollerith, Henrich, 30
Hollerith, Herman, 22
host, 235
HTML, 222
hub, 232
I/O, 78
IAB, 244
IBM, 22, 23, 210
IEC, 244
IEEE, 243
implementacja klasy, 168
inżynieria oprogramowania, 32, 164
indeksowanie tablic, 133
informacja, 16, 215
Input/Output, 78
Instruction Unit, 83
instrukcja, 166
do–while, 141
pętli, 141
podstawienia, 140
warunkowa, 140
while, 141
interfejs, 235
interfejs klasy, 168
International Business Machine, 22
interpretacja, 180
interpreter, 178, 180
IP, 87
IPX/SPX, 208
ISO, 243
ISO 8859-2, 101
iteracja, 148
IU, 83
język, 183
ADA, 177
Algol-60, 161, 176
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
INDEKS
263
Algol-68, 162
asembler, 96
BASIC, 25
bezkontekstowy, 183
C, 212
C++, 177
FORTRAN, 160
FORTRAN 77, 161
FORTRAN 90, 161
FORTRAN IV, 161, 176
JAVA, 182
Java, 177
JCL, 209
kontekstowy, 183
LISP, 169
LOGO, 169
maszynowy, 177
mnemoniczny, 96
Pascal, 162, 174, 177
PERL, 180
PHP, 180
Prolog, 171
Smalltalk, 169
zorientowany obiektowo, 167
język adresów symbolicznych, 178
język prekompilowany, 181
język programowania, 157
języki
skryptowe, 180
języki programowania, 32
Jacquard, 21
jednoczesność zadań, 196
jednostka
adresująca, 84
arytmetyczno-logiczna, 83
dekodowania rozkazów, 83
sterująca, 24
zarządzająca pamięcią, 84
zmienno-przecinkowa, 83
JIT, 182
kabel BNC, 229
kabel koncentryczny, 229
Kahn, Robert, 33
kalkulator elektroniczny, 23
karta sieciowa, 231
karty perforowane, 21, 22
katalog, 198
KB, 236
Kb, 236
Kernighan, Brian, 211
Key, Alan, 169
klasa, 167
Kleene, Stephen, 29
klient, 222
kod
BCD, 62
CRC, 125
Morsa, 119
kod źródłowy, 177, 178
kod ASCII, 100
kod pośredni, 181
kod szesnastkowy, 56
kodowanie, 100
kompatybilny, 236
kompilacja, 178
kompilator, 178
komprocesor, 83
komputer
Apple II, 25
AS/400, 210
biologiczny, 28
klasy PC, 25
PC, 25
PDP-1, 210
komunikat TCP, 228
koncentratory, 232
koniec ramki, 224
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
264
INDEKS
koprocesor numeryczny, 78
kryptografia, 31
lampy elektronowe, 23
LAN, 216
Leibniz, Gottfried Wilhelm, 19
licencja GPL, 212
liczba całkowita, 103
liczba naturalna, 103
liczby Fibonacciego, 151
licznik rozkazów, 193
liczydło, 18
litera, 183
logika rozmyta, 35
ludy sumeryjskie, 17
młyn, 20
magazyn, 20
magistrala
adresowa, 80
danych, 80
sterująca, 80
systemowa, 78
Mainframe, 34
MAN, 216
mantysa, 110
MARK I, 23
maszyna
analityczna, 20
licząca, 19
różnicowa, 19
Turinga, 23
wirtualna, 210
Z1, 23
Z2, 23
Z3, 23
Z4, 23
Maszyna Turinga, 29, 70
maszyna Turinga, 69
maszyna wirtualna, 181
mechaniczna maszyna licząca, 19
mechanizm
sterujący, 21
Memory Managment Unit, 84
metoda
różnicowa, 20
zerojedynkowa, 44
zstępująca, 174
metodologia
obiektowa, 167
mikroprocesor jednoukładowy, 78
MMU, 84
moc obliczeniowa, 16
Mors, Samuel, 119
most, 232
MVS, 209
MVT, 209
najmłodszy bit, 236
najstarszy bit, 236
NCR, 22
NDS, 207
Neper, John, 19
Network Operating System, 207
Newmann, John von, 24
NFSNET, 33
niedomiar
dodatni, 112
ujemny, 112
nośniki informacji, 16
NOS, 207
notacja BNF, 184
numer IP, 227
Nyquist, Harry, 119
obiekt, 166, 210
objekt, 167
odczyt z pliku, 199
odczytanie następnego elementu pliku,
137
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
INDEKS
265
oprogramowanie
osadzone, 200
wbudowane, 200
otwarcie pliku, 137
pałeczki Nepera, 19
pakiet, 166
pakiety, 224
pamięć, 24, 78
o dostępie swobodnym, 80
RAM, 80
pamięć o dostępie swobodnym, 78
pamięć podręczna, 82
Pascal, Blaise, 19
Pascaliny, 19
PCP, 209
plik, 133, 136, 198
obiektu, 178
sekwencyjny, 137
pobranie wstępne, 85
początek ramki, 224
podejście
iteracyjne, 148
rekurencyjne, 148
podprogramy, 166
podstawa systemu liczbowego, 46
podsystem
interpretacji poleceń, 189
ochrony, 189
wejścia/wyjścia, 189
zarządzania pamięcią masową, 188
zarządzania pamięcią operacyjną,
188
zarządzania procesami, 188
podział
obciążenia, 193
zasobów, 193
pojemność, 82
pola, 135
polska notacja, 170
POSIX, 212
Post, E., 130
postać kanoniczna, 45
pozycyjny system liczbowy, 46
prawo
łączności, 40
De Morgana, 42
dopełnienia, 40
idempotentności, 41
identyczności, 40
identyczności drugie, 41
pochłaniania, 41
przemienności, 40
rozdzielności, 40
prekompilacja, 181
problem dziesiątkowania, 18
problem stopu, 149
proces, 193
procesor, 78
INTEL, 34
Mororola, 25
PowerPC, 25, 34
program, 131, 193
wykonywalny, 177
program źródłowy, 178
program wykonywalny, 178
programowanie
bezproceduralne, 171
funkcjonalne, 169
obiektowe, 175
sekwencyjne, 173
strukturalne, 174
w logice, 169, 171
protokół, 225
https, 31
NCP, 32
SSL, 31
TCP/IP, 227
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
266
INDEKS
protokół IP, 227
przełącznik, 232
przecięcie
zbiorów, 136
przepełnienie
dodatnie, 112
ujemne, 112
przynależność do zbioru, 136
pseudo-język programowania, 139
punkty
decyzyjne, 137
zbiegu, 138
różnica
zbiorów, 136
RAD, 163
ramka, 224
redundancja, 120
reguły
gramatyczne, 159
znaczeniowe, 159
reguły składniowe, 159
rejestr
źródła, 87
akumulatora, 86
bazowy, 86
danych, 86
dodatkowy, 87
flagowy, 87
kodu, 86
licznika, 86
przeznaczenia, 87
stosu, 86
wskaźnika bazy, 87
wskaźnika rozkazów, 87
wskaźnika stosu, 87
rejestry, 83
ogólnego przeznaczenia, 86
segmentowe, 86
stanu, 87
stosu, 87
wskaźnikowe, 87
rejestry procesora, 193
rekord, 133, 135
z wariantami, 136
rekurencja, 148
rekursja, 148
reprezentacja
zmiennoprzecinkowa, 23
reprezentacja uzupełnień do dwu, 105
reprezentacja zero–jedynkowa, 100
reprezentacja znak–moduł, 104
Roussel, Philippe, 172
router, 231
rozgałęzienia, 137
rozkazy
arytmetyczne i logiczne, 97
przerwań, 99
przesunięć, 97
skoków, 98
sterujące stanem procesora, 99
rozproszony
system komputerowy, 201
rząd systemu liczbowego, 46
S/360, 34
słownik, 183
słowo, 183
schemat blokowy, 137
Schickard, Wilhelm, 19
semantyka, 159
serwer, 220
aplikacji, 221
bazy danych, 221
plików, 220
poczty, 222
WWW, 222
wydruków, 221
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
INDEKS
267
Shannon, Claude, 36, 39, 118
SI, 87
sieć
każdy-z-każdym, 222
Peer-to-Peer, 222
równorzędna, 222
sieć działań, 138
sieć klient-serwer, 223
sieć komputerowa, 215
lokalna, 216
miejska, 217
rozległa, 216
zasięg, 216
sieci komputerowe, 32
sieci neuronowe, 35
składnia, 159
skrętka, 229
SOH, 224
sortowanie, 144
sortowanie przez wstawianie, 145
SP, 87
SS, 86
stan
końcowy Maszyny Turinga, 71
Maszyny Turinga, 71
odrzucający Maszyny Turinga, 71
procesu, 194
aktywny, 194
gotowy, 194
wstrzymanie, 194
stan akceptujący Maszyny Turinga,
71
stos protokołów TCP/IP, 227
strona kodowa, 101
struktura fizyczna sieci, 216
struktury danych, 132
suma
zbiorów, 136
suma kontrolna, 122
sumator arytmetyczny, 19
SVS, 209
switch, 232
symbol końcowy Maszyny Turinga,
71
symbol pusty Maszyny Turinga, 71
symbol taśmowy, 71
system
Amoeba, 193
czasu rzeczywistego, 192
rygorystyczny, 192
dwójkowy, 19, 23, 47
dziesiętny, 45
liczbowy addytywny, 46
liczbowy pozycyjny, 46
operacyjny, 187
Amoeba, 201
BSD, 34
CP/M, 25, 207
FreeBSD, 212
jednoużytkownikowy, 190, 192
jednozadaniowy, 190
Linux, 34
Mac OS, 202
MS-DOS, 197, 204
NetBSD, 212
NetWare, 207
OpenBSD, 212
OS/390, 208
OS/400, 210
QDOS, 204
QNX, 192
rozproszony, 192
UNIX, 34
Unix, 192, 207, 211
wieloużytkownikowy, 192
wielozadaniowy, 192
Windows, 204
Windows 2000, 206
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
268
INDEKS
Windows NT, 206
Windows XP, 206
plików, 198
rzymski, 46
szesnastkowy, 56
Windows 95, 192
System V, 211
systemy
osadzone, 165
szerokość magistrali, 80
sztuczna inteligencja, 35, 169
sztuczne sieci neuronowe, 35
szyfr Cezara, 31
tablica, 133
tablica przejść, 71
Tabulating Machine Company, 22
Tanenbaum, Andrew, 193, 201
TCP/IP, 33, 208, 227
teoria
obliczalności, 29
teoria informacji, 36
teza Churcha, 75
Tomilnson, Roy, 33
topologia
gwiazdy, 217
magistrali, 217
mieszana, 217
oczek pełnych, 217
pierścienia, 217
topologia sieci, 217
Torvalds, Linus, 212
tryb pracy krokowej, 88
TSO, 209
Turbo Pascal, 163
Turing, Alan, 22, 29, 69, 70, 130
tworzenie pliku, 199
typ, 166
liczbowy, 133
logiczny, 133
plikowy, 133
prosty, 133
rekord, 133, 135
tablicowy, 133
wyliczeniowy, 163
złożony, 133
zbiorowy, 133
znakowy, 133
układ
sterowania magistrali, 83
wykonawczy, 83
ukrywanie informacji, 165
Unicode, 102
UNIVAC, 24
upraszczanie wyrażeń booleowskich,
45
urządzenia
dostępowe, 230
transmisji, 229
usługa DNS, 228
usuwanie pliku, 199
utworzenie pliku, 137
uzupełnienie dwójkowe, 106
virtual machine, 181
wątek, 198
WAN, 216
warunek
dyskretności, 130
efektywności, 130
jednoznaczności, 130
uniwersalności, 130
warunek stopu, 149
Wejście/Wyjście, 78
wiadomość, 118
wiadomość elektroniczna, 33
wielomian generacyjny, 125
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004
INDEKS
269
wieloprogramowość, 196
wielozadaniowość, 196
bez wywłaszczania, 196
z wywłaszczaniem, 196
Windows 3.1, 205
Windows 3.11, 197
Windows 95, 205
Wirth, Niklaus, 162
wyrażenie, 166
WYSIWYG, 206
wyszukiwanie
binarne, 147
liniowe, 147
połówkowe, 147
wzmacniaki, 232
XML, 30
złożoność obliczeniowa, 153
zadanie, 166, 198
zapewnienie
komunikacji, 193
niezawodności, 193
zapis do pliku, 199
zapis stałoprzecinkowy, 109
zarządzanie
pamięcią, 198
zasada
dualności, 40
zbiór, 133, 136
zbiory funkcjonalnie pełne, 76
zegar systemowy, 78
znaki
narodowe, 101
semigraficzne, 101
znaki alfanumeryczne, 100
Zuse, Konrad, 23
c
2001-2003 by P. Fulmański & Ś. Sobieski, Uniwersytet Łódzki. Wersja RC1 z dnia: 4 stycznia 2004