11. előadás (2005. május 10.) A make segédprogram Alacsony szintű műveletek és bitmezők Fájl, katalógus rendszer hívások 1
make A make segédprogram (utility) egy intelligens program menedzser, amellyel megőrizhetjük egy modulokból álló program integritását. Nem a C (vagy más) nyelv része. Pl. main.c f1.c fn.c cc -o main main.c f1.c fn.c Csak a megváltozottakat: cc -o main main.c f1.c... fi.o.. fj.o... fn.c ( cc -c main.c a main.o előállítására ) Időrabló, fáradságos, hibaforrás. 2
make programozás A make program egy sor parancs, ami leírja, hogy hogyan lehet a programot a forrás fájlokból felépíteni. A make program fájl függőségi és kontrukciós szabályokat tartalmaz. Függőségi szabály: bal oldal : jobb oldal A bal oldal az előállítandó célfájlok neveit adja meg, míg a jobb oldal megadja azokat a fájlneveket, melyektől a cél függ. Ha a cél dátuma korábbi mint az alkotóké, akkor a make a függőségi szabályokat követő konstrukciós előírásokat végrehajtja. 3
make programozás Megj.: a make fájlok minden olyan parancsot végrehajtanak, amit parancssorban kiadhatunk (pl. backup fájl készítése). A make fájl bármely szövegszerkesztővel létrehozható. Pl. prog: prog.o f1.o f2.o cc -o prog prog.o f1.o f2.o -lm prog.o: header.h prog.c cc -c prog.c f1.o: header.h f1.c cc -c f1.c f2.o: Explicit szabályok: megnevezzük a fájlokat. 4
make programozás Implicit szabályok, pl.: f1.o: f1.c cc -c f1.c f2.o: f2.c cc -c f2.c általánosítható:.c.o: cc -c $<.forrás_kiterjesztés.cél_kiterjesztés : parancs $< a.c kiterjesztést jelenti # a sor megjegyzés 5
make programozás A make több a Unix parancsokhoz hasonló beépített, vagy tényleges Unix paranccsal rendelkezik, pl.: break, date, mkdir, type, chdir, cp(copy), mv(move or rename), cd, rm(remove), ls, path 6
make makrók Makrók definiálhatók forrásfájl nevek, objectfájl nevek, compiler opciók és könyvtár linkek tárolására: SOURCES = main.c f1.c f2.c CFLAGS = -g -C LIBS = -lm PROGRAM = main OBJECTS = (SOURCES:.c =.o),ahol a (SOURCES:.c =.o) a SOURCES.c kiterjesztését.o -vá teszi. 7
make programozás Makró hívása: $(makrónév), pl.: $(PROGRAM) : $(OBJECTS) Egy sor függőséget és célt állít fel. $(LINK.C) -o $(OBJECTS) $(LIBS) Néhány belső makró: $* az aktuális függő fájl neve (kiterjesztés nélkül) az aktuális cél teljes neve $< a cél.c fájlja 8
make futtatása Parancssorban: make automatikusan az aktuális könyvtárban a Makefile nevű fájlt keresi és hajtja végre. Felülbírálható: make -f make_fájlnév Pl.: make -f sajat_make További opciók a kézikönyvekben, pl. a gnu.org -ról kiindulva. Példák forrása: Dave Marshall 9
Alacsony szintű műveletek és bitmezők Bitenkénti műveletek: & (AND), | (OR), ^ (XOR), ~ (egyes komplemens) > (jobbra tolás) Bitmezők Memória takarékosság céljából használjuk: - egybites információ tárolására: flag (pl. compiler szimbólumtábla) - nem szabványos külső fájl formátum olvasásakor, pl. 9 bites egész 10
Bitmezők Deklarációja, pl.: struct packed_struct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int f4:1; unsigned int type:4; unsigned int funny_int:9; } pack; A C a lehető legtömörebben tárolja a fenti bitmezőket, feltéve, hogy a mezők maximális hossza kisebb vagy egyenlő a gép egész szavánál. Kompatibilitás! 11
Bitmezők Tagok elérése a szokásos módon, pl.: pack.type = 7; Megj.: - csak az n alsó bit rendelődik egy n bites mezőhöz - a bitmezők mindíg egésszé konvertálódnak a számítások során - a standard típusok és a bitmezők vegyesen használhatók - az unsigned definíció fontos 12
Bitmezők használata: diszk kontroller Az eszközvezérlő regiszterei egy egész szóba pakolhatók (Dave Marshall): 13
Bitmezők használata: diszk kontroller A regiszter definíciója: struct DISK_REGISTER { unsigned ready:1; unsigned error_occured:1; unsigned disk_spinning:1; unsigned write_protect:1; unsigned head_loaded:1; unsigned error_code:8; unsigned track:9; unsigned sector:5; unsigned command:5; }; 14
Bitmezők használata: diszk kontroller A diszk regiszter memória címre definíálunk egy pointert: struct DISK_REGISTER *disk_reg = (struct DISK_REGISTER *) DISK_REGISTER_MEMORY; Kódrészlet pl. olvasásra: 15
Bitmezők használata: diszk kontroller /* Define sector and track to start read */ disk_reg->sector = new_sector; disk_reg->track = new_track; disk_reg->command = READ; /* wait until operation done, ready will be true */ while ( ! disk_reg->ready ) ; /* check for errors */ if (disk_reg->error_occured) { /* interrogate disk_reg->error_code for error type */ switch (disk_reg->error_code) } 16
Bitmezők: portabilitás Gondok: - az egészek lehetnek signed vagy unsigned - sok compiler a bitmező hosszát az int típus méretére korlátozza: 16 vagy 32 bit - bizonyos bitmezőket balról-jobbra, másokat jobbról- balra tárolnak a memóriában - ha a bitmező túl nagy, akkor a következő bitmező közvetlenül utána, vagy a következő szóban kezdődhet. 17
Bitmezők: portabilitás Ha a portabilitás fontos, akkor használjuk a bit shift-et és a maszkolást, pl.: unsigned int *disk_reg = (unsigned int *) DISK_REGISTER_MEMORY; /* see if disk error occured */ disk_error_occured = (disk_reg & 0x ) >> 31; 18
Fájl, katalógus rendszer hívások A cd, ls, rm, cp, mkdir, stb. megvalósítása C programból. Katalógus kezelő függvények Katalógus váltás int chdir(char *path) Munkakatalógus lekérdezése (teljes útvonal) char *getwd(char *path) Hiba: NULL A Unix cd parancsának C emulációja: 19
Fájl, katalógus rendszer hívások #include main(int argc,char **argv) { if (argc < 2) { printf("Usage: %s <pathname \n",argv[0]); exit(1); } if (chdir(argv[1]) != 0) { printf("Error in chdir \n"); exit(1); } 20
Fájl, katalógus rendszer hívások Fájl hozzáférés meghatározása: int access(char *path, int mode) mode: R_OK - olvasási engedély W_OK - írási engedély X_OK - végrehajtás vagy keresés engedély F_OK - a fájlhoz vezető út kereshető és létezik-e 0 sikeres, -1 hiba és errn o beállítás És így tovább... 21