home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1997 #3
/
amigamamagazinepolishissue03-1
/
ma_1995
/
05
/
ami044.txt
< prev
next >
Wrap
Text File
|
1997-04-07
|
22KB
|
463 lines
C dla kaûdego (cz. 1.)
----------------------
POCZÂTKI
<txt>Jëzyk C to dzisiaj jeden z najpopularniejszych jëzyków
programowania, a bez wâtpienia najpopularniejszy jëzyk
programowania wyûszego poziomu na Amidze.
<a>Kamil Iskra, Dariusz Ûbik
<txt>Moûna by wymieniê wiele zalet jëzyka C, ale naszym zdaniem
naprawdë waûne sâ tylko trzy.
-- Prostota. C jest bardzo surowy, moûna wrëcz powiedzieê --
ascetyczny. Trzon jëzyka jest niezwykle skromny, dziëki czemu
îatwo go opanowaê (naszym zdaniem znacznie îatwiej niû np.
promowany w polskim szkolnictwie Pascal). C jest elastyczny i
nakîada na programistë niewiele ograniczeï.
-- Powszechnoôê. Niemal kaûda publikacja na temat programowania
Amigi dotyczy wîaônie tego jëzyka. W tym jëzyku jest napisany
system operacyjny naszego komputera (niecaîy -- czëôê, tzn.
fragmenty wymagajâce maksymalnej prëdkoôci, zostaîa napisana w
asemblerze).
-- Bardzo dobre kompilatory. Jest ich wiele. Od tych dziaîajâcych
juû na A500 z 0,5 MB RAM, aû po kolubryny ledwie pracujâce na
A1200 z 6 MB RAM.
<sr>Kompilatory
<txt>Co do róûnych kompilatorów, to od razu pojawia sië pewien
problem. Po prostu róûne kompilatory sâ ze sobâ nie do koïca
zgodne. My, podobnie jak [sts] (ach, wy tajniacy -- patrz Magazyn
AMIGA 6/94, artykuî "SAS C") uwaûamy, ûe najlepszy z dostëpnych
na Amidze kompilatorów to SAS/C 6, wiëc wszystkie przykîady bëdâ
pisane z myôlâ o nim. Nie powinno byê jednak wiëkszych problemów
przy uûywaniu innych kompilatorów.
Co do opcji kompilatora, to sugerujemy zadbaê, aby typ "char" byî
bezznakowy (wartoôci od 0 do 255, a nie od -128 do 127). W SAS/C
6 robi sië to podajâc opcjë UCHAR, w Manx Aztec C 5 opcjë -PP, w
GNU CC opcjë -FUNSIGNED-CHAR. Naleûy sië równieû upewniê, ûe typ
"int" jest 32-bitowy (long-int), a nie 16-bitowy (short-int) --
kompilatory powinny mieê standardowo ustawionâ wîaôciwâ wartoôê.
<sr>Program kursu
<txt>Czas napisaê, czego chcielibyômy Was nauczyê i co zakîadamy,
ûe juû umiecie. Zaczynajâc od tego drugiego: NIE bëdziemy uczyê
podstaw jëzyka C. Na ten temat istnieje mnóstwo publikacji, poza
tym podstawy sâ na kaûdym komputerze takie same, a wiëc moûna sië
uczyê nawet z ksiâûek o pececie. My polecamy zdobycie "biblii
jëzyka C" -- ksiâûki "Jëzyk ANSI C" autorstwa Briana W.
Kernighana i Dennisa M. Ritchie (jest to nowa pozycja, wydana
przez WNT, Warszawa 1994 -- nie polecamy pierwszego,
przestarzaîego juû, wydania). Ksiâûka ta opisuje w doôê
przystëpny sposób standard jëzyka, bez ûadnych pecetowych
rozszerzeï (jest tylko jeden rozdziaî o Unixie).
Czego wiëc chcemy Was nauczyê? Chcemy daê Wam podstawy niezbëdne
do pisania zgodnych ze ôrodowiskiem systemu operacyjnego
aplikacji. Moûna by wiëc powiedzieê, ûe kurs ten to nie kurs
jëzyka C, ale kurs programowania zgodnego z systemem operacyjnym.
Co chcemy przez to powiedzieê? To, ûe zdecydowanâ wiëkszoôê
zawartych w tym kursie informacji bëdâ mogli wykorzystywaê nie
tylko programujâcy w C, ale równieû programujâcy w asemblerze,
Pascalu, E itd.
Nasz kurs jëzyka C nie jest pierwszym w polskiej prasie
komputerowej. Co wiëc nowego mamy zamiar wnieôê w stosunku do
kursów prowadzonych kiedyô przez Bohdana R. Raua w "Amigowcu" i
Jarosîawa Chrostowskiego w "C64+4 & AMIGA"? Przede wszystkim nasz
kurs bëdzie nowoczeôniejszy. System operacyjny sië zmienia (no,
ostatnio nieco wolniej, ale miejmy nadziejë, ûe to zastój
chwilowy). Kurs z "Amigowca" bazowaî na systemie operacyjnym w
wersji 1.3, my tymczasem mamy zamiar bazowaê na wersji 2.04
systemu, nie zapominajâc przy tym o systemach 2.1 i 3.0.
Chcielibyômy to jeszcze raz podkreôliê: BËDZIEMY PISALI O OS
2.04+. Wiëkszoôê przykîadów (jeôli nie wszystkie) bëdzie wymagaê
przynajmniej tej wersji systemu operacyjnego.
Zaczniemy od tego, co z punktu widzenia uûytkowników jest
najbardziej widoczne -- od graficznego interfejsu uûytkownika,
tzn. ekranów, okien, gadûetów, menu. System operacyjny Amigi to
jednak nie tylko okienka. Istnieje masa wielce przydatnych
bibliotek nie zwiâzanych z GUI (Graphic User Interface --
Graficzny Interfejs Uûytkownika). Opiszemy wiëc "exec.library",
czyli System Executor -- bibliotekë zarzâdzajâcâ caîym systemem,
oraz "dos.library" -- bibliotekë zarzâdzajâcâ wysokopoziomowym
I/O. Wîaôciwie to chcielibyômy po trochu opisaê wszystkie
najwaûniejsze elementy systemu operacyjnego, aby daê Wam dobre
rozeznanie w tym, co system jest w stanie programiôcie
zaoferowaê. Chcielibyômy wiëc napisaê równieû o
"amigaguide.library", "commodities.library", "workbench.library",
"locale.library", "iffparse.library" itd. Sâ to, rzecz jasna,
nasze poboûne ûyczenia, a czy te ambitne plany uda nam sië
zrealizowaê, czas pokaûe.
Jak juû wczeôniej wspomnieliômy, chcemy daê Wam "podstawy".
Oznacza to, ûe NIE bëdziemy dokîadnie opisywaê wszystkich
funkcji, pól struktur czy staîych. Jest to po prostu fizycznie
niemoûliwe. System operacyjny jest tak obszerny, ûe jego peîny
opis zajmuje tysiâce stron (mówimy o serii ksiâûkowej "Reference
Manuals"). Z koniecznoôci wiëc bëdziemy opisywali tylko
najwaûniejsze elementy systemu, najczëôciej uûywane w typowych
programach. W tekôcie artykuîu znajdâ sië teû z pewnoôciâ pewne
niedomówienia oraz póîprawdy -- chodzi po prostu o to, ûe
gdybyômy zbyt czësto zastrzegali sië, ûe "nie do koïca jest tak,
jak piszemy, bo...", to niezbyt dobrze obeznani z tematem
Czytelnicy po prostu utraciliby gîówny wâtek artykuîu. Zagubiliby
sië w tych wszystkich niuansach (albo zaczëliby sâdziê, ûe "ktoô"
usiîuje ich "zrobiê w konia"); poza tym artykuî znacznie by sië
wtedy wydîuûyî.
Rzecz jasna, bëdziemy sië starali robiê jak najmniej bîëdów.
Najprawdopodobniej wszystkie przykîady bëdâ intensywnie testowane
przy uûyciu opisanych przeze mnie w Magazynie AMIGA 12/94--1/95
debuggerów. Jeûeli jednak znajdziecie w artykule bâdú w
przykîadach jakieô bîëdy, lub teû macie inne uwagi/sugestie
dotyczâce tego kursu, to piszcie do redakcji. Nie oczekujcie
jednak, ûe Wasze listy znajdâ odzwierciedlenie juû w kolejnej
czëôci kursu. Ze wzglëdu na dîugi cykl wydawniczy Magazynu AMIGA
oraz na to, ûe piszemy z dwumiesiëcznâ "zakîadkâ", Wasze uwagi
moûemy uwzglëdniê najwczeôniej 3 miesiâce po ich otrzymaniu.
<sr>Inkludy
<txt>Chcielibyômy skupiê sië na chwilë na "inkludach", czyli
plikach nagîówkowych, doîâczanych przez kompilator dyrektywâ
"#include". Na Amidze sâ one bardzo rozszerzone w stosunku do
standardu ANSI -- zawierajâ wszystkie definicje i deklaracje
niezbëdne do pisania aplikacji korzystajâcych z zasobów systemu
operacyjnego. Istniejâ róûne wersje "inkludów" -- musicie mieê je
przynajmniej w wersji dla OS 2.0, a w niektórych wypadkach
potrzebne bëdâ inkludy dla OS 3.0 (my uûywamy inkludów dla OS 3.1
i Wam teû to polecamy -- moûna je znaleúê na dysku CD Freda Fisha
bâdú w Internecie: serwer "ftp.rz.uni-wuerzburg.de", katalog
"pub/amiga/frozenfish/bbs/cbm"). O strukturze inkludów
powinniôcie wiedzieê tyle, ûe opisy "device'ów" znajdujâ sië w
katalogu "devices", a bibliotek w katalogu "libraries" (nie
zawsze -- duûe biblioteki majâ osobne katalogi, np. "exec",
"intuition", "dos"). W katalogu "clib" znajdujâ sië prototypy
(deklaracje) funkcji z poszczególnych bibliotek i niektórych
device'ów. Twórcy kompilatorów tworzâ czësto dodatkowy katalog, o
nazwie "pragmas" bâdú "inline", zawierajâcy pewne informacje
umoûliwiajâce kompilatorom tworzenie bardziej efektywnych wywoîaï
funkcji systemowych. Czasami tworzâ teû oni katalog "proto",
zawierajâcy proste pliki powodujâce zaîadowanie jednym ruchem
deklaracji i pragm, np. wykonanie w SAS/C "#include
<proto/intuition.h>" powoduje doîâczenie
"clib/intuition_protos.h" i "pragmas/intuition_pragmas.h".
Niestety, nie we wszystkich kompilatorach tak jest. Niektóre nie
majâ plików "proto" i trzeba "rëcznie" doîâczaê deklaracje i
pragmy. Niektóre nie majâ równieû pragm -- wtedy doîâcza sië
tylko deklaracje.
Wydaje mi sië, ûe jak na wstëp, to ten fragment zrobiî sië to
nieco przydîugi. Aby wiëc nie traciê czasu ani cennego miejsca,
juû dziô zaczynamy "regularny" kurs. "Oddajë wiëc klawiaturë" w
rëce mego wspólnika:
"-- Aleû dziëkujë Kamilku za okazanâ mi îaskë w postaci
wysîuûonej dyskietki, o otrzymaniu klawiatury nie ômiaîbym marzyê
nawet skrycie."
<sr>Co to jest multitasking?
<txt>Multitasking jest to moûliwoôê wykonywania jednoczeônie (lub
jeôli ktoô chciaîby byê dokîadny, prawie jednoczeônie) kilku
programów. Taki system pracy komputera pozwala na peîniejsze
wykorzystanie mocy procesora z dwóch zasadniczych powodów.
Po pierwsze komputer domowy w wiëkszoôci wypadków czeka na sygnaî
od uûytkownika lub urzâdzeï zewnëtrznych, w tym czasie inny
program moûe efektywnie wykorzystywaê system (obciâûenie
procesora da sië îatwo sprawdziê, np. za pomocâ programu Spy -- w
graficzny sposób przedstawia on stopieï zajëcia procesora, czas,
przez jaki pracowaî on "na peînych obrotach" oraz przez jaki
"zbijaî bâki").
Drugim równie waûnym powodem budowy takich systemów jest
moûliwoôê wspóîpracy kilku niezaleûnych programów, które mogâ na
bieûâco przekazywaê sobie wyniki swojej pracy, a w ten sposób
zaoszczëdziê czas potrzebny na zapis i odczyt danych z/do plików,
co jest znaczâce przy wiëkszych obliczeniach. Taki sposób pracy
jest szalenie wygodny. W tym wîaônie celu programy sâ wyposaûane
w interface ARexxa (Amiga Rexx jest jëzykiem stworzonym w celu
nadzorowania pracy programów (patrz Magazyn AMIGA 1/92,
wrzesieï).
Niestety, nie ma róûy bez kolców: z multitaskingiem trzeba
uwaûaê. Piszâc programy naleûy pamiëtaê o tym, ûe podczas ich
wykonywania mogâ sië znajdowaê w pamiëci inne programy. To jest
nasz problem -- problem programistów, którzy muszâ pamiëtaê, ûe
"nie sâ sami", ûe nie wolno "grzebaê" w nie swojej pamiëci oraz
zmuszaê procesora do pracy, jeôli nie jest to konieczne.
Zabronione jest tworzenie tak zwanych busy loopów, czyli
wykonujâcych sië bez przerwy pëtli sîuûâcych do oczekiwania na
informacjë (dokîadniej zajmiemy sië tym przy okazji opisu funkcji
Execa Wait() oraz portów).
Kolejnym problemem jest nieco wolniejsze funkcjonowanie
programów, jednak twórcy borykajâ sië z nim raczej rzadko,
poniewaû zastosowanie multitaskingu spowalnia dziaîanie programów
w niewielkim stopniu (poza tym moûna programowi nadaê wyûszy
priorytet, dziëki czemu bëdzie on miaî pierwszeïstwo w stosunku
do pozostaîych).
Jednak jeôli komuô zaleûaîoby na wyciôniëciu z maszyny
wszystkiego, moûe wyîâczyê pozostaîe zadania (taski). Do tego
celu przeznaczone sâ funkcje Execa (Forbid(), Permit()), jednak
nie bëdziemy sië nimi zajmowali (przynajmniej na poczâtku).
Amigowski multitasking jest doôê zgrabnie zorganizowany -- nawet
jeôli dojdzie do katastrofy i jakiô program sië "powiesi", to nie
oznacza to caîkowitej klëski systemu. Problem taki jest znany
uûytkownikom programu Windows 3.1, który ma multitasking
kooperatywny, czyli, mówiâc zîoôliwie, multitasking bez
multitaskingu -- programy zwalniajâ procesor, gdy tego pragnâ,
brak tam nadzorcy (patrz PC World Komputer Luty 1994: "Dos
umarî!"). System zastosowany w Amidze wyglâda inaczej,
powiedziaîbym, ûe jest pod wieloma wzglëdami lepszy. Na tym
komputerze stale funkcjonuje program w trybie nadzorcy
(Supervisor -- tryb procesora), zajmujâcy sië przydzielaniem
czasu procesora programom znajdujâcym sië na liôcie oczekujâcych
(ten program to taki komitet kolejkowy). Istnienie
"wszechmocnego" nadzorcy pozwala na wykrycie i usuniëcie z listy
zawieszonego programu, dziëki czemu system moûe dziaîaê nadal. W
zasadzie mowa tu o anormalnym zachowaniu sië oprogramowania,
jednak takie nieszczëôcia z caîâ pewnoôciâ spotkajâ Czytelników
podczas pisania i testowania programów. Tyle wiedzy na temat
multitaskingu powinno wystarczyê. Nareszcie moûemy sië zajâê
bibliotekami, które sâ wypeînione po same brzegi funkcjami.
<sr>Dlaczego biblioteki?
<txt>Stosowanie bibliotek zewnëtrznych wynika z zastosowania
multitaskingu. W wypadku pecetowego DOS-u funkcje znajdujâ sië w
bibliotekach, które przy linkowaniu (konsolidacji) programu sâ
doï doîâczane -- postëpowanie takie znacznie wydîuûa kod
programu, a poza tym w wypadku funkcjonowania kilku programów
jednoczeônie jest wprost zabójcze dla pamiëci (w wypadku Amigi
równieû istniejâ takie biblioteki, ale czësto ich praca ogranicza
sië do otwarcia zewnëtrznej biblioteki i wywoîania jakiejô jej
funkcji). Biblioteki amigowe to wygoda i oszczëdnoôê -- spróbujmy
to udowodniê. W chwili, gdy kilka programów korzysta z takiej
samej funkcji, powiedzmy z file-requestera (okna wyboru plików),
nie muszâ one mieê takiej funkcji w swoim kodzie -- wystarczy, ûe
skorzystajâ z biblioteki systemowej "asl.library", która zawiera
takâ funkcjë. Wykorzystywanie funkcji bibliotecznych oszczëdza
równieû czas przeznaczony na pisanie i testowanie programów, poza
tym dziëki zastosowaniu bibliotek programy sâ podobne do siebie
zarówno pod wzglëdem obsîugi, jak i graficznego interfejsu
uûytkownika (GUI). Spróbujmy sobie wyobraziê, ûe kaûde okno ma
gadûet zamykania w innym miejscu, a zrozumiemy, co znaczy
standard.
Czëôê bibliotek znajduje sië w pamiëci staîej komputera (od
systemu 2.0 jest tego 512 KB), pozostaîe biblioteki znajdujâ sië
na dysku, przewaûnie w katalogu "LIBS:". Podstawowâ bibliotekâ
jest "exec.library", bez jej udziaîu nie jest moûliwe
funkcjonowanie wîaôciwie ûadnego programu. Biblioteka ta jest
otwierana przy inicjacji systemu i pozostaje otwarta do koïca
jego pracy. W jej zasobach znajdujâ sië funkcje sîuûâce do
przydzielania pamiëci, otwierania innych bibliotek oraz wiele
innych niezwykle poûytecznych narzëdzi. Ze wzglëdu na swój
specyficzny charakter biblioteka Exec musi byê dostëpna dla
kaûdego i w kaûdej chwili. Z tej wîaônie przyczyny, w
przeciwieïstwie do pozostaîych bibliotek, nie ma potrzeby jej
otwierania.
<sr>Dlaczego otwieramy biblioteki?
<txt>Biblioteka podczas otwierania jest umieszczana w pamiëci,
jeôli pochodzi z dysku, jeôli natomiast pochodzi z ROM-u, to
pozostaje w nim, a w pamiëci RAM zapisywana jest jedynie
pomocnicza struktura opisujâca bibliotekë. W celu otwarcia
biblioteki naleûy posîuûyê sië funkcjâ Execa:
<l>struct Library *OpenLibrary( UBYTE *libName, unsigned long version );
<txt>Pierwszym argumentem funkcji jest wskaúnik na nazwë
biblioteki, drugim minimalna wymagana wersja biblioteki. Jeûeli
funkcja odnajdzie ûâdanâ bibliotekë w odpowiedniej wersji, to
zwróci adres opisujâcej jâ struktury "Library", w przeciwnym
wypadku zwróci 0 (NULL). Dlaczego istnieje parametr ograniczajâcy
wersjë biblioteki? Odpowiedú jest prosta: biblioteki rozrastajâ
sië i majâ coraz wiëcej funkcji, programiôci sâ i czësto muszâ
byê wybredni, wîaônie dlatego umiera system w wersji 1.3, a
poprzednie juû zostaîy pochowane. Funkcja OpenLibrary w tej
formie pojawiîa sië w systemie 1.2 -- wczeôniej istniaîa funkcja
o tej samej nazwie róûniâca sië tym, ûe nie sprawdzaîa, jakâ
wersjë biblioteki otwiera. Stara funkcja zostaîa zachowana dla
utrzymania zgodnoôci systemu z juû napisanym oprogramowaniem --
obecnie nazywa sië OldOpenLibrary(), ma jedynie pierwszy
argument.
Wartoôê zwróconâ przez OpenLibrary() naleûy zapamiëtaê w zmiennej
wskaúnikowej o ôciôle okreôlonej nazwie (np. IntuitionBase dla
"intuition.library", ReqToolsBase dla "reqtools.library" itd.),
poniewaû zmienna ta jest wykorzystywana przy wywoîaniach funkcji
z danej biblioteki.
<sr>Dlaczego zamykamy biblioteki?
<txt>Kiedy otwarta przez nas biblioteka nie jest nam juû dîuûej
potrzebna, czyli zwykle pod koniec programu, naleûy jâ zamknâê.
Sîuûy do tego funkcja Execa:
<l>void CloseLibrary( struct Library *library );
<txt>Jako jej parametr naleûy podaê wartoôê zwróconâ przez
OpenLibrary(), czyli wskaúnik na strukturë "Library".
Poczâtkujâcy programiôci czësto majâ wâtpliwoôci, czy zamykanie
bibliotek rzeczywiôcie jest potrzebne. Faktem jest, ûe jeûeli sië
biblioteki nie zamknie, to nie bëdzie jakiejô strasznej
katastrofy (nie dojdzie do zawieszenia programu), jednak porzâdny
program ZAWSZE powinien zostawiaê po sobie porzâdek -- jeûeli sië
coô (bibliotekë, czcionkë, plik, okno itd.) otworzyîo (bâdú
utworzyîo), to naleûy to coô zamknâê, aby zapewniê sprawne
dziaîanie systemu, umoûliwiê zwrot przydzielonej przy otwieraniu
pamiëci.
Proponujemy przeêwiczyê otwieranie i zamykanie bibliotek na
przykîadzie -- Listing #1.
W tym programiku otwieramy biblioteki, ich adresy przechowujemy w
zmiennych o odpowiednich nazwach, po czym zamykamy biblioteki.
Nie korzystamy jeszcze z ûadnych funkcji zawartych w
bibliotekach (nie wszystko naraz).
Tym, którzy dopiero zaczynajâ programowaê w C, naleûy sië drobne
wyjaônienie odnoônie jednej z linii programu:
<l>if (GfxBase=(struct GfxBase*)OpenLibrary("graphics.library", 0))
<txt>Jëzyk C jest dosyê elestyczny i pozwala na jednoczesne
przypisanie wartoôci i sprawdzenie, czy wartoôê ta jest róûna od
zera. Z takimi jëzykowymi idiomami bëdziemy sië czësto spotykaê;
dla "uîatwienia" bëdâ jeszcze wzbogacone o znak "!", czyli po
prostu negacjë (UWAGA: niektóre kompilatory mogâ wygenerowaê
ostrzeûenie o moûliwoôci wystâpienia bîëdu w wypadku takiej
formy, jest ona jednak w peîni poprawna, a ostrzeûenia sâ po to,
by odszukaê literówki -- '=' zamiast '=='). Podobnie naleûaîoby
przypomnieê, co oznacza dziwolâg umieszczony poniûej, ale tym
zajmiemy sië za chwilë.
<l>IntuitionBase=(struct IntuitionBase*)OpenLibrary...
<sr>Struktura opisujâca bibliotekë
<txt>Jak juû mówiliômy, podczas otwierania biblioteki otrzymujemy
wskaúnik na strukturë "Library". Znajomoôê tej struktury nie jest
moûe niezbëdna przy pisaniu programów, zawsze jednak warto
wiedzieê dokîadnie, "co w trawie piszczy". Jednym z jej pól jest
"lib_OpenCnt", w tym polu jest zapisana liczba uûytkowników
korzystajâcych z biblioteki w danej chwili. Jeôli biblioteka
straci wszystkich uûytkowników (pole lib_OpenCnt == 0), to moûe
zostaê usuniëta z pamiëci i tak sië stanie, ale dopiero w wypadku
braków pamiëci. Jeôli problemy braku pamiëci nie wystâpiâ,
biblioteka bëdzie pozostawaê w pamiëci, pomimo iû nikt z niej nie
korzysta (czeka na lepsze czasy). Przejdúmy do pól "lib_Version"
i "lib_Revision". W polach tych zapisany jest numer wersji
biblioteki. Wîaônie po tych polach moûna sprawdziê, z jakâ wersjâ
systemu pracujemy. Patrz Listing #2.
W kolejnych programach bëdziemy korzystaê z funkcji check_os(),
której dla oszczëdnoôci miejsca nie bëdziemy za kaûdym razem
przepisywaê, wiëc Czytelnik bëdzie zmuszony doîâczaê jâ (oraz
definicje staîych "OS_xx") do kolejnych programów. Dwa sîowa
odnoônie UWORD w deklaracji funkcji check_os() -- jest to nic
innego jak "unsigned short int". Analogicznie ULONG oznacza
"unsigned long int", a UBYTE -- "usigned char".
W tym krótkim programiku pokazaliômy, jak moûna wykorzystaê
zmiennâ "SysBase", która jest wskaúnikiem na strukturë "ExecBase"
(wartoôê tej zmiennej nadaje doîâczony podczas linkowania
programu moduî startowy, pobierajâc jâ z komórki pamiëci pod
adresem 0x00000004 -- ta informacja jest waûna raczej dla
programujâcych w asemblerze). Zawartoôê struktury "ExecBase"
moûna poznaê analizujâc systemowe inkludy, a ôciôlej mówiâc, plik
"exec/execbase.h". Pierwszym polem tej struktury jest "LibNode"
typu "Library", co oznacza, ûe struktura ta jest rozbudowanâ
wersjâ struktury "Library", dziëki czemu moûemy swobodnie
zastosowaê rzutowanie typów (ang. casting), z którym spotkaliômy
sië juû w pierwszym przykîadzie podczas przypisywania wartoôci
zmiennym "IntuitionBase" i "GfxBase". Poza polem "LibNode"
struktura "ExecBase" zawiera pewne specyficzne dla niej dane,
takie jak np. adres obecnie wykonywanego zadania ("ThisTask"),
typ procesora ("AttnFlags") oraz wiele innych, czësto prywatnych,
informacji (tj. takich, których aplikacje nie powinny
wykorzystywaê).
Do danych zawartych w polu LibNode struktury "ExecBase" moûemy
odwoîywaê sië na dwa róûne sposoby:
<l>ver=SysBase->LibNode.lib_Version;
ver=((struct Library*)SysBase)->lib_Version;
<txt>Analogicznie moûemy postëpowaê z pozostaîymi rozbudowanymi
strukturami, opisujâcymi biblioteki:
<l>opc=IntuitionBase->LibNode.lib_OpenCnt;
opc=((struct Library*)IntuitionBase)->lib_OpenCnt;
<txt>Odwoîania te wskazujâ dokîadnie na të samâ zmiennâ, obie
formy sâ poprawne.
Powróêmy do struktury "ExecBase". Zapoznajmy sië z kolejnym
przykîadem. Patrz Listing #3.
Pole "ThisTask", jak juû wspomnieliômy, zawiera adres struktury
"Task", w której znajdujâ sië informacje o wykonywanym w danej
chwili zadaniu, a wiëc naszym programie. Informacji tych jest
caîa masa (patrz "exec/tasks.h"), my pobieramy tylko te o nazwie
procesu (bëdzie to najprawdopodobniej "Shell Process", choê mogâ
sië zdarzyê i inne) oraz jego priorytecie (niemal zawsze 0).
Komentarza moûe wymagaê uûyty w nim "for". Staîe symboliczne
"AFB_68xxx" sâ zdefiniowane w pliku "exec/execbase.h". Staîa
AFB_68010 ma wartoôê 0, AFB_68020 to 1 itd. Dane zawarte w polu
"AttnFlags" sâ zapisane w formie maski bitowej; gdy jest obecny
dany procesor, to bit o numerze "AFB_68xxx" jest ustawiony,
ustawione sâ jednak równieû niûsze bity, tyczâce sië starszych
procesorów -- z tego powodu zastosowaliômy pëtlë z licznikiem
malejâcym, zaczynajâcâ sprawdzanie od najnowszych procesorów.
Warunek "licznik==-1" bëdzie speîniony dla procesora MC68000,
który nie jest odnotowany w "AttnFlags". Przykîad ten wyôwietli
nieprawdziwe informacje dla procesora MC68060 (potraktuje go
najprawdopodobniej jako MC68040), jako ûe odpowiedniej staîej
brakuje w pliku "exec/execbase.h". Warto w tym momencie wspomnieê
o róûnicy pomiëdzy staîymi "AFB_68xxx" i "AFF_68xxx": staîe "B"
oznaczajâ NUMER bitu, a staîe "F" sâ gotowâ MASKÂ bitowâ (moûna
by nieformalnie napisaê: "F"=1<<"B"). Radzimy o tym pamiëtaê,
poniewaû jest to ogólnie uûywana konwencja, a pomylenie jednych
staîych z drugimi staje sië przyczynâ bîëdnego dziaîania
programu.
Na tym koïczymy dzisiejszy odcinek i zapraszamy do lektury
nastëpnej czëôci kursu. A za miesiâc bierzemy sië do okien,
zajmiemy sië równieû informacjami pochodzâcymi od okna.
<przyp>
Zalecana literatura:
-- Inkludy (pliki dla kompilatora).
-- AutoDoce (podzielony na poszczególne biblioteki i "device'y",
przesortowany alfabetycznie suchy opis wszystkich funkcji systemu
operacyjnego).
-- "AMIGA ROM Kernel Reference Manual: Libraries, Devices"
(przystëpnie napisany opis poszczególnych czëôci systemu
operacyjnego, masa przykîadów).
-- Brian W. Kerninghan, Dennis M. Ritchie "Jëzyk ANSI C", WNT,
Warszawa, 1994.