Inbyggda System utbildning: projektarbete Kommando och generell funktion för att anropa sorteringsalgoritmer samt Subversion versionshantering. Introduktion Målet för projektet var att göra ett program för sortering som har grundrutiner som kan sortera både strukturer av rådata och strukturer med pekare till rådata, se projektbeskrivning. Programmet skall kunna anropas via ett kommandoanrop i Windows command prompt eller i Linux (Fedora 17). I princip skulle detta programpaket kunna användas för att integrera vilken sorteringsrutin som helst som bara kräver att man specificerar en funktion som avgör om data objekt är större, mindre eller lika med varandra. Det skulle exvis kunna användas för att jämföra exekveringshastigheter Jag har implementerat ett kommandogränssnitt för sortering samt en subrutin som kan användas för att sortera olika typer av heltal / integers i C och C strängar av characters(strängarna är uppbyggda med C typen char). I princip skall vilken sorteringsrutin som helst kunna anslutas till mitt programpaket, se mer nedan. Som en del av detta har jag även installerat en subversion server för versionshantering under Cygwin, på en av kursens tillhandahållna Windows 7 Professional försedda PC. Cygwin är en gratis programvara för Unix/Linux-emulering under Windows från Redhat som står bakom Linux distributionerna Fedora och Redhat. I Cygwin ingår en Linux-version av Subversion servern från "Apache Software Foundation" (som gör bl.a. den fria webservern Apache, de fria "Big Data"-verktygen Hadoops och Hive m.m.) Jag har använt Subversion's cygwin-klient respektive TortoiseSVN's Windows klient för versionshanteringen. Den senare är integrerad i själva utforskaren som ett shell extension.jag har dessutom valt att använda cygwin's ssh server för att kunna tunnla via ssh till subversion servern under Cygwin/Windows, även om det i första hand använts för att tunnla in till Cygwin's subversion-server direkt på den lokala hosten (men även från min Linux-dator hemma i mitt lokala nätverk). Problembeskrivning Jag har gjort detta med subrutiner preprocessor-definitioner som i princip gör det möjligt att anropa vilken som helst sorteringsrutin med listor/arrayer av olika integer-datatyper eller listor av strängar. Listorna skall kunna finnas dels sammanhängande i minnet som är vanligast 1-
Inbyggda System utbildning: projektarbete för vanliga heltal/andra korta datatyper, och dels kunna vara av typen listor/arrayer av C strängar, implementerade som listor/arrayer av pekare till strängar. Jag har implementerat en kommandomottagning för Windows kommandoprompt respektive Linux/Unix terminalen och en subrutin och ett antal preprocessor macros för att åstadkomma detta. Jag har också sett till att ha modern versionshantering för mina filer med Subversion för versionshanteringen, i Linux, Windows 7 och i Windows 7, men med Linux/Unix emulerat av Cygwin. Teori Sorteringsrutiner som bubble-sort och qsort kan i princip sortera vad som helst, man behöver bara specificera en relation som anger hur man avgör om ett objekt av en datatyp är större än, mindre än eller lika stor som ett annat objekt av samma datatyp. Jag har begränsat mig till dessa två sorteringsrutiner eftersom huvuduppgiften för projektet är att göra en generell driver för godtyckliga sorteringsrutinter för godtyckliga C typer (av normal längd, d.v.s. vad som var standard i den första ansi C versionen). För C's egna datatyper är det inbyggt i C kompilatorn hur man gör en jämförelse med hjälp av >, < och = operatorerna, detta kan användas för dessa typer. För C strängar i ANSI-kod använder man traditionellt sett strcmp rutinen för att avgöra detta, men det går att generalisera den strängjämförelse-funktionen till alla typer av data som beskrivs av noll-terminerade arrayer av godtycklig längd (en bra källa för koden till strcmp() är f.ö. Kernigan & Ritchie s ANSI-C bok). Listor/arrayer av C-strängar innehåller normalt sett bara pekarna till noll-terminerade arrayer av characters i ANSI-kod, jag har valt generalisera detta till alla typer av data på detta format. 2-
Inbyggda System utbildning: projektarbete KOMMANDO Kommandot för att sortera integers ser ut enligt nedan: iterate_over_word_list_int_cont [-csrgq] [file...] [file...] där alternativen -csrgq motsvarar -c CSV format, komma separerat format -s Sortera lista -r Sortera i omvänd ordning (reverse order) -g Gruppera i jämna och udda listor, konkatenera sedan ihop listorna (eventuellt efter sortering) -q Sortera med quicksort (annars i dag med bubble-sort) Argumenten på slutet, fil att läsa från och fil att skriva till är icke-obligatoriska, det första hittade argumentet antas vara in-filen och det andra argumentet utfilen. Om ingen in-fil eller ut-fil finns/finns angiven läser/skriver man istället från vanliga kommandoprompten i Windows/kommandoraden i terminalen i Linux/Unix. Uppbyggnad av programmet. Programmet består av dessa filer: iterate_over_word_list_int_cont.c sorteringskommando, anropar my_sort_int_cont.c iterate_over_word_list_int_cont.h - deklarationer av gränssnitt mot my_sort_int_cont.c my_sort_int_cont.c - subrutiner för hantering av listor och sortering comp_anything_scalar.h - COMP macro skalära C typer comp_anything_vector.h h - COMP macro nollterminerade vektorer av C typer handle_integer_lists.h - macron för listor av alla integer typer read_write_int_list_cont.h - gränssnitt mot read_write_int_list_cont.c read_write_int_list_cont.c - in- och utmatning av integer data 3-
Inbyggda System utbildning: projektarbete Klient och server för versionshantering. För att kunna ha en modern miljö för versionshantering och bakkopior har jag använt den fria programvaran subversion, jag har satt upp en Subversion server under Linux/Unixemuleringen cygwin som jag sedan anropar via en ssh-tunnel mot min egen maskin, localhost. Som klient har jag både använt Cygwin s Subversion-klient och TortoiseSVN s Subversion klient. Material HW och SW som använts Programvara som kör på PC med Windows 7 Professional 64-bitars version CodeBlocks GUI/IDE för debuggning programvaruutveckling i C mingw32-gcc kompilator Tortoise SVN Subversion klient (ett GUI), ett shell-tillägg som är integrerat i utforskaren. Programvara som går under Unix/Linux emulering på Windows m.hj.a. Cygwin, 64- bitars version ssh server ssh klient subversion server subversion klient mingw32-gcc kompilator GDB debugger Emacs och dess Lisp moder Compile mode för att kompilera och parsa kompileringsfel Gud-moden för att debugga m.hj.a gdb debuggern 4-
Inbyggda System utbildning: projektarbete vc-mode utbyggd för subversion för versions-hantering Linux maskin med Fedora 17's x86-version CodeBlocks GUI/IDE för debuggning programvaruutveckling i C gcc kompilator GDB debugger ssh klient. svn klient emacs Compile mode för att kompilera och parsa kompileringsfel Gud-moden för att debugga m.hj.a gdb debuggern vc-mode utbyggd för subversion för versionshanteringen Metod Jag har implementerat ett generellt kommando-gränssnitt för att anropa sorteringsrutinerna från Windows kommando prompt eller terminal i unix/linux. I princip skall det kommandot klara av att anropa en generell sorteringsrutin (se nästa stycke) för både noll-terminerade strängar och andra datatyper, men just nu har denna rutin enbart implementerats för vanliga heltal med tecken, signed int. (För teständamål har jag också gjort en version som hanterar korta heltal med tecken, signed short.) Denna del av programvaran hanterar även inläsning och utskrift av ursprungliga listorna och de sorterade listorna. Jag har implementerat en subrutin och preprocessor-makro definitioner för den funktion som anger hur man bestämmer om ett data-objekt är större än ett annat. De två preprocessor-makron som används för att generera "comp"-funktionerna för olika datatyper och list-typer är mycket generella och klarar av att definiera dels vanliga 5-
listor/arrayer och dels listor/arrayer av pekare till dataobjekt och sortera dem, se nedan och koden. För närvarande har bara alla normallånga typer av data och C strängar av char / ANSI-tecken implementerats som en del av själva funktionerna för sortering, även om preprocessormakrona finns att göra detta för alla de normal-långa standardtyperna i C. MJUKVARA I C FÖR SORTERING Skrivit ett kommando för att sortera integer data, C-typen int. Testat att göra om detta kommando för att sortera data av C-typen short int. Skrivit ett separat program för att testa sortering av strängar. Alla programmen anropar min generella subrutin för sortering. Sorteringsrutinen utför sortering listor/arrayer av pekare till strängar och vanliga listor/arrayer av de olika normallånga typerna av integers i C. -6-
SUBRUTIN ANROPAD FRÅN KOMMANDO-DEL Jag har definierat en generell subrutin för sortering av godtyckliga typer av data inklusive typerna ovan (om den anropas med ej implementerade typer av data listor/arrayer så leder det till programfel med en felutskrift via ett assert-anrop). Subrutinen void Create_sorted_list_of_anything(...) deklarerad/definierad i filerna iterate_over_word_list_int_cont.h/my_sort_int_cont.c har definierats att kunna sortera olika typer av datalistor, och ser ut enligt nedan, utdrag ur header-fil: // Parameters: // char *signedness - pointer to string "signed" or "unsigned" to indicate sign of used data type, // the first part of the data type name for the objects sorted // char *type - pointer to string containing the second part of the name of the used data type // of the objects sorted // bool bool_vector_list - boolean that has logical value true if array/list contains pointers to the data objects // sorted // bool bool_vector_list - boolean that has logical value true if array/list contains pointers to the data objects // sorted // bool reverse - boolean that has logical value true if the array/list is to be sorted in the reverse order // bool qsort_bool - boolean that has logical value true if the array/list is to be sorted using qsort method(default when // false is sorting using bubble-sort method) void Create_sorted_list_of_anything(void **sorted_primary_list_ptr, int count, bool reverse, bool qsort_bool, void *primary_list_ptr, const char *signed_ness, const char *type, bool bool_vector_list ); -7-
MACROS FÖR "COMP" : Macro i filen comp_anything_scalar.h // Macro defining function for comparing // anything scalar (that is a data object itself, // not a pointer to a data object), where type of scalar // is defined by inputs to macro as // SIGNEDNESS A_TYPE #define COMP_ANYTHING_W_DIRECTION(SIGNEDNESS,A_TYPE) signed int comp_##signedness##_##a_type##_w_direction (const void * elem1, const void * elem2 ) { signed int reverse_sign = 1; signed int result = -2; if( comp_direction_reverse ) { reverse_sign = -1; } const SIGNEDNESS A_TYPE *f = ((const SIGNEDNESS A_TYPE *)elem1); const SIGNEDNESS A_TYPE *s= ((const SIGNEDNESS A_TYPE *)elem2); if( *f > *s ) { result = 1; } else if( *f == *s ) { result = 0; } else { result = -1; } return ( reverse_sign * result ); } -8-
Macro i filen comp_anything_vector.h // Macro defining function for comparing // anything vector (that is a pointer to the data object itself, // not the data object, part of a zero-terminated vector list/array), // where type of scalar is defined by inputs to macro as // // SIGNEDNESS A_TYPE // // Most usual case of this is an ordinary string #define COMP_ANYTHING_VECTOR_W_DIRECTION(SIGNEDNESS,A_TYPE) signed int comp_##signedness##_##a_type##_vector_w_direction (const void * elem1, const void * elem2 ) { signed int reverse_sign = 1; signed int result = -2; if( comp_direction_reverse ) { reverse_sign = -1; } const SIGNEDNESS A_TYPE *f = *((const SIGNEDNESS A_TYPE **)elem1); const SIGNEDNESS A_TYPE *s= *((const SIGNEDNESS A_TYPE **)elem2); while( *f && *s && ( *f == *s ) ) { f++; s++; / } if( *f == *s ) { result = 0; } else if( *f > *s ) { result = 1; } else { result = -1; } return ( reverse_sign * result ); } -9-
INST. AV IDE/GUI (UTOM C::B) OCH SVN. VERSIONSHANTERING INST. AV CYGWIN MED EMACS GUI, GCC, SVN&SSH KLIENT&SERVER Hämta cygwin från exempelvis www.cygwin.org och installera (det är klokt att göra det i 2 steg, ladda ner först, och installera från lokal kopia sedan, så du kan flytta installationen mellan PC) Installera emacs, gcc, gdb, allt i svn och ssh (det går att söka fram paketen i installationsverktyget) INST. AV SVN&SSH KLIENTER Installera TortoiseSVN från http://tortoisesvn.net/ (jag använder själv bara Subversion klienten) och ssh klient och agent för nyckel, Putty och Pageant från http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html och installera. -10-
ANV. AV SVN ÖVER SSH MOT CYGWIN INST. AV SVN&SSH SERVER SAMT SVN&SSH KLIENT I CYGWIN Jag har av praktiska skäl valt att använda SVN servern i Cygwin, eftersom jag också jobbar i Cygwin med Emacs som GUI/IDE för utveckling. Jag hittade en tråd nedan, och har själv kompletterat den med uppdaterade instruktioner: http://www.coderhaus.com/?p=8#more-8 En viktig detalj är sedan att stänga ssh för inloggning via password, se tråd: http://linux-tips.org/article/60/disabling-ssh-password-authentication KONF. AV TORTOISESVN SVN&SSH KLIENT I WINDOWS 7 Det finns information om detta i tråden ovan, men det är viktigt att läsa tillägget här om hur man sätter upp TortoiseSVN för att använda Pageant för hantering av privata nycklar när man kontaktar Cygwin server via svn + ssh (via localhost, IP loop adressen för för den lokala maskinen). (Eftersom jag redan har en SVN server under Cygwin använder jag inte server delen av TortoiseSVN). Se tråd nedan för hur man använder pageant utan att referera till en Putty session (bättre när man skall dela sin utcheckning av SVN-repositoriet med SVN klienten i Cygwin): http://tortoisesvn.net/ssh_howto_logemann.html -11-
Resultat TEST AV PROGRAMKOD Jag har dels testat att sortera listor av C-typerna "signed int" och "signed short int" med kommandot ovan, dels i originalversion, dels hackat för att hantera listor med "signed short int". Jag har också gjort en test-rutin för att testa sortering av listor. Allting har packats i en gzippad tar fil, export_dir.tar.gz. Denna fil finns att ladda ner tillsammans med projektrapporten från min egen hemsida http://mimer.homeip.net Resultatet av testkörningarna finns under: export_dir/test_int - test med sortering av integer export_dir/test_short - test med sortering av short integer export_dir/test_string - test med sortering av strängar Källkoden är bifogad under: export_dir/ - källkod och makefiler RESULTAT AV TEST Sorteringen har fungerat som den skall i alla de fall jag provat i Cygwin's emulering av Linux/Unix enligt ovan. Det skall inte vara någon skillnad om man kör under Windows och kompilerar med CodeBlocks (projektfil finns) istället samt testar med hj.a. motsvarande batscript (fås från författaren på anmodan). Slutsats Jag har implementerat och verifierat en generell subrutin för sortering av listor av normallånga integers och listor av strängar. Detta visar att det i princip är möjligt att göra ett generellt kommando för sortering av både listor av data objekt och noll-terminerade listor av pekare till data-objekt av standard-typerna inom C. -12-
För att göra detta med rimlig arbetsinsats behöver man dels skriva om själva kommandomottagningen och listhanteringen runt den att hantera listor med typerna void och (void *), dels på något sätt generera rutinerna för in- och utmatning av resp. list-typ med hjälp av C- preprocessorn. Till hjälp för detta skulle antagligen man kunna ha nytta av en befintlig headerfil som omdefinierar standardtyperna så att preprocessorn kan avgöra hur scanf och printf's formatkoder skall automat-genereras för resp. typ respektive om resp. typ är en pekare eller ej. Jag har byggt en mycket bra och fungerande korsmiljö mellan Unix/Linux emulering (via Cygwin) och Windows 7 med bra debug-iden i båda fallen och väl fungerande versionshantering med Subversion. För Cygwin och Emacs gäller också att versionshanteringen integrerats med IDE/GUI-et för programproduktion och debuggning. Förbättringsförslag Lägg till parametrar för typ av indata till kommando ovan, använd listor/arrayer av typen "void" och "void *" där, och gör sedan generella rutiner för in och ut-matning av de olika typerna på samma sätt som vi gjorde rutiner för jämförelse i subrutinpaketet enligt ovan. Implementera allt detta med preprocessning med automatisk avkänning av typerna, om de är pekare/ej pekare och eventuellt även lesser/bigger-endian (gäller förstås allt typer av data i systemet man jobbar i). Implementera ett test-script i PERL istället för två test-script för respektive Cygwin och Windows 7's kommando-prompt. Registrera den använda datorn med en fri dynamisk DNS-service så att Subversion-servern kan adresseras med ett domännamn istället för med ip-adressen som kan variera. Fixa ett GUI/IDE med Subversion integrerat för Windows 7. Använd dessa rutiner för att implementera motsvarande sorteringsrutiner som C++ STL-bibliotek erbjuder men med mindre footprint. -13-