TDDI04 Concurrent Programming, Operating Systems, and Real-time Operating Systems Overview § History § Common organization of a program § Data types in C § Constants and enumerations § Composite datatypes (struct, union, array) A short introduction to C § Pointers § Function pointers Programming, Compiling, Linking § Storage classes (static and automatic variables) § Dynamically allocated memory § Preprocess, compile and link Copyright Notice: The lecture notes are mainly based on Silberschatz’s, Galvin’s and Gagne’s book (“Operating System Concepts”, 7th ed., Wiley, 2005). No part of the lecture notes may be reproduced in any form, due to the copyrights reserved by Wiley. These lecture notes should only be used for internal teaching purposes at the Linköping University. Acknowledgment: The lecture notes are originally compiled by C. Kessler, IDA. § More information Acknowledgment: Some slides are adapted from a presentation by Sorin Manolache, IDA Klas Arvidsson, IDA, Linköpings universitet. TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.2 A Short History of C Common organization of a C/C++ program § C was developed in the early 1970’s by Dennis Ritchie at Bell Labs (-> UNIX) § A C/C++ program is a collection of C/C++ source files • Objective: structured but flexible programming language e.g. for writing device drivers or operating systems • Book 1978 by Brian W. Kernighan and Dennis M. Ritchie (”K&R-C”) • Module files (extensions .c, .cc) containing implementations of functionality (similar .java) • Header files (.h, .hh) containing declarations of global variables, functions, #include’d from all module files that need to see them, using the C preprocessor (missing in Java) § ”ANSI-C” 1989 standard by ANSI (”C89”) • • • • The C standard for many programmers (and compilers...) Became the basis for standard C++ Java borrowed much of its syntax The GNU C compiler implemented a superset (”GNU-C”) § ”ISO-C” 1999 standard by ISO, only minor changes (”C99”) TDDI04, K. Arvidsson, IDA, Linköpings universitet. § When a module file is compiled successfully, an object code file (object module, binary module) is created (.o, corresponds to Java .class files) § An executable (program) is a single binary file (a.out) built by the linker by merging all needed object code files § There must be exactly one function called main() TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.3 Common organization of a program (2) Common organization of a program (3) glob.h #include abc.c compile abc.o #include #include preprocess mymain.c compile def.c /* Comment: declaration of globally visible functions and variables. */ extern int inc(int); extern int initval; #include ”glob.h” Note the difference: Declarations announce signatures (names+types). Definitions declare (if not already done) AND allocate memory. Header files should never contain definitions! TDDI04, K. Arvidsson, IDA, Linköpings universitet. /* definition of func. incr: int inc( int k ) { compile mymain.o def.o libc.a link C run-time library is linked with the user code a.out (executable) TDDI04, K. Arvidsson, IDA, Linköpings universitet. mymain.c abc.c stdio.h glob.h xy.h 2.4 2.5 /* definition of * var. Initval */ int initval = 17; /* local to file */ static char charval; static void noop() {} noop(); return k+1; #include <stdio.h> #include ”glob.h” int counter; /*global*/ int main(int argv, char* argv[]) { counter = initval; printf(“counter:%d”, inc(counter)); /* compile errors */ charval = ’a’; noop(); } } 2.6 1 Common organization of a program (4) mylist.h #include ”mylist.h” /* PRIVATE */ /* PUBLIC */ struct listelement { … } struct mylist { … } void init(mylist* list); #include <stdio.h> #include ”mylist.h” int main( void ) { mylist foo; listelement* create(listelement*, int data) { … } void insert(mylist* l, int data); /* ”constructor” */ init(foo); /* use the list */ insert(foo, 4711) … … /* PUBLIC */ void free(mylist* list); /* * definition of * public functions */ void init() {…} … TDDI04, K. Arvidsson, IDA, Linköpings universitet. § Primitive types • integral types: char, short, int, long; enum mymain.c mylist.c #ifndef MYLIST_H #define MYLIST_H Data types in C > can be signed or unsigned, e.g. unsigned int counter; > sizes are implementation dependent (compiler/platform), use sizeof( datatype ) operator to write portable code floatingpoint types: float, double, long double pointers § Composite data types • • • • • /* ”destructor” */ free(foo); } arrays structs unions § Programmer can define new type names with typedef TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.7 2.8 Constants and Enumerations Composite data types (1): structs § In C/C++, constants are often capitalized: RED, BLUE, ... struct my_complex { • 2 #define BLUE 4 #define GREEN 5 x.re x.im }; Symbolic names, textually expanded before compilation #define RED x: int re, im; § With the preprocessor ( C ): struct my_complex x; // definition of x typedef struct my_complex complex; // introduce new type name ’complex’ complex y; int main ( void ) #define YELLOW 6 { int color = GREEN; /* GREEN replaced by 5 */ x.re = 2; § Enumerations or constants ( C/C++ ): • y.im = 3 * x.re; Symbolic names checked by compiler printf(”x needs %d bytes, an complex needs %d bytes\n”, sizeof( x ), sizeof( complex ) ); enum color { RED = 2, BLUE = 4, GREEN, YELLOW }; const int NUM_COLORS = 4; } /* checked and optimized by compiler */ // Remark: the sizeof operator is evaluated at compile time. enum color mycolor = RED; TDDI04, K. Arvidsson, IDA, Linköpings universitet. // Remark: gcc may accept some C++ features when compiling C-code depending enabled extensions. An example is // comments. TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.9 Composite data types (2): unions Composite data types (3): Arrays § Unions implement variant records: all attributes share the same storage (start at 0) § Unions break type safety • can interpret same memory location with different types § If handled with care, useful in low-level programming union my_flexible_complex { struct my_complex ic; // integer complex (re, im) – see above float f; // floatingpoint value – overlaps with ic } c; c.ic.re = 1141123417; printf(”%s %s %f\n”, ”Float value interpreted from this”, ”memory address contents is ”, c.f ); // writes 528.646057 TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.11 2.10 c: c.ic.re, c.f c.ic.im § Declaration/definition very similar to Java: int a[20]; 3 6 int b[] = { 3, 6, 8, 4, 3 }; complex c[4]; float matrix [3] [4]; 8 4 3 § Addressing: Location of element a[i] starts at: (address of a) + i * elsize where elsize is the element size in bytes § Use: a[3] = 1234567; a[21] = 345; // ??, there is no array bound checking in C c[1].re = c[2].im; § Dynamic arrays: write your own § Arrays are just a different view of pointers TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.12 2 Pointers Pointer arithmetics § Each data item of a program exist somewhere in memory • Hence, it has a (start) memory address. § Integral values can be added to / subtracted from pointers: § A variable of type pointer_to_type_X may take as a value the memory address of a variable of type X int a; int *p; // defines just the pointer p, not its contents! p = 0x14a236f0; // initialize p § Dereferencing a pointer with the * operator: *p = 17; // writes 17 to whatever address contained in p § The address of a variable can be obtained by the & operator: p = &a; // now, p points to address of a § Use the NULL pointer (which is just an alias for address 0) to denote invalid addresses, end of lists etc. TDDI04, K. Arvidsson, IDA, Linköpings universitet. int *q = p + 7; // new value of q is (value of p) + 7 * sizeof(int) § Arrays are simply constant pointers to their first element: • • Notation b[3] is ”syntactic sugar” for *(b + 3) b[0] is the same as *b b: 6 8 4 3 § A pointer can be subtracted from another pointer: • unsigned int offset = q – p; // divided by sizeof(q) TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.13 3 2.14 Pointers and structs Why do we need pointers in C? § struct my_complex { int re, im; } c, *p; p = &c; § Defining recursive data structures (lists, trees ...) – as in Java § Argument passing to functions • simulates reference parameters – missing in C (not C++) > void foo ( int *p ) { *p = 17; } Call: foo ( &i ); § Arrays are pointers • Handle to access dynamically allocated arrays • A 2D array is an array of pointers to arrays: > int m[3][4]; // m[2] is a pointer to start of third row of m > hence, m is a pointer to a pointer to an int § For representing strings – missing in C as basic data type • char *s = ”hello”; // s points to char-array {’h’,’e’,’l’,’l’,’o’, 0 } § For dirty hacks (low-level manipulation of data) • p is a pointer to a struct § p->re is shorthand for (*p).re, or *(p + (offset of re) ) • • Example: as p points to c, &(p->re) is the same as &(c.re) Example: elem->next = NULL; p: 0xafb024 c: 0xafb024 c.re c.im TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.15 TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.16 Pointer type casting Pointers to functions (1) § Pointer types can be casted to other pointer types • int i = 1147114711; int *pi = &i; printf ( ”%f\n”, * ( (float *) pi ) ); // prints 894.325623 • All pointers have the same size (1 address word) • But no conversion of the pointed data! (cf. unions) § Function declaration • extern int f( float ); > Compare this to: • printf( ”%f\n”, (float) i ); Source of type unsafety, but often needed in low-level programming § Generic pointer type: void * • Pointer type is undefined • Always requires a pointer type cast before dereferencing TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.17 § Function call: f( x ) • f is actually a (constant) pointer to the first instruction of function f in program memory • Call f( x ) dereferences pointer f > push argument x; save PC and other reg’s; PC := f; § Function pointer variable • int (*pf)(float); // pf is a pointer to a function // that takes a float and returns an int • pf = f; // pf now contains start address of f • pf( x ); // or (*pf)(x) dereferencing (call): same effect as f(x) TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.18 3 Pointers to functions (2) Pointers to functions (3) § Most frequent use: generic functions § Most frequent use: generic functions § Example: Ordinary sort routine § Example: Generic sort routine • void bubble_sort( int arr[], int asize ) { int i, j; for (i=0; i<asize-1; i++) for (j=i+1; j<asize; j++) if ( arr[i] > arr[j] ) ... // interchange arr[i] and arr[j] } • void bubble_sort( int arr[], int asize, int (*cmp)(int,int) ) { int i, j; for (i=0; i<asize-1; i++) for (j=i+1; j<asize; j++) if ( cmp ( arr[i] , arr[j] ) ) ... // interchange arr[i] and arr[j] } • • Need to rewrite this for sorting in a different order? • • int gt ( int a, int b ) { if (a > b) return 1; else return 0; } Idea: Make bubble_sort generic in the compare function TDDI04, K. Arvidsson, IDA, Linköpings universitet. bubble_sort ( somearray, 100, gt ); bubble_sort ( otherarray, 200, lt ); TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.19 2.20 Storage classes in C (1) Storage classes in C (2) § Automatic variables • Local variables and formal parameters of a function • Exist once per call • Visible only within that function (and function call) • Space allocated automatically on the function’s stack frame • Live only as long as the function executes § Global variables • Declared and defined outside any function • Unless made globally visible by an extern declaration, visible only within this module (file scope) int x; // at top level – outside any function extern int y; // y seen from all modules; only declaration int y = 4; // only 1 definition of y for all modules seeing y • Space allocated automatically when the program is loaded int *foo ( void ) // function returning a pointer to an int. { int t = 3; // local variable return &t; // ?? t is deallocated on return from foo, // so its address should not make sense to the caller... } TDDI04, K. Arvidsson, IDA, Linköpings universitet. § Static variables • static int counter; • Allocated once for this module (i.e., not on the stack) even if declared within a function! • Value will survive function return: next call sees it TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.21 Dynamic allocation of memory in C 2.22 Compiling and Linking § malloc( N ) • • • • #include and returns a generic (void *) pointer to it; #include #include preprocess this pointer can be type-casted to the expected pointer type Example: abc.c icplx *p = (icplx *)malloc ( sizeof ( icplx )); § free( p ) • stdio.h glob.h xy.h allocates a block of N bytes on the heap deallocates heap memory block pointed to by p compile abc.o mymain.c compile def.c compile mymain.o def.o § Can be used e.g. for simulating dynamic arrays: • • Recall: arrays are pointers int *a = (int *) malloc ( k * sizeof( int ) ); TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.23 libc.a link a[3] = 17; C run-time library is linked with the user code a.out (executable) TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.24 4 Compiling C Programs Linking Multiple Modules (1) § Example: GNU C Compiler: gcc (Open Source) § One command calls preprocessor, compiler, assembler, linker § Compiler (-c) created an (object) module file (.o, .bin) § Single module: Compile and link (build executable): • gcc mymain.c executable: a.out • gcc –o myprog mymain.c rename executable § Multiple modules: Compile and link separately • • • gcc –c mymain.c gcc –c –o other.o other.c compiler only -> mymain.o compiles other.c -> other.o gcc other.o mymain.o call the linker, -> a.out § make (e.g. GNU gmake) • automatizes building process for several modules § Check the man pages! TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.25 Linking Multiple Modules (2) • • • • • • Binary format, e.g. COFF (UNIX), ELF (Linux) Non-executable (yet) Segments for code, global data, stack / heap space List of global symbols (e.g., functions, extern variables) Addresses in each segment start at 0 Relocation table: List of addresses/instructions that the linker must patch when changing the start address of the module § Static relocation (at compile/link time): Merge all object modules to a single object module, with consecutive addresses in each segment type TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.26 Background: How the Linker Works § Read all object modules to be linked (including library archive modules if necessary) § Merge the code, data, stack/heap segments of these into a single code, data, stack/heap segment § Resolve global symbols (e.g., global functions, variables): check for duplicate globals, undefined globals § Write the resulting object module, with a new relocation table § and mark it executable. § Variants of static linking: (need hardware support) • Dynamic linking (on demand at run time, as in Java) • Shared libraries TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.27 TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.28 There is much more to say... Sources of information § Type conversions and casting § Lesson and lab material § Bit-level operations § References and manual pages (man -s3c printf) § Operator precedence order § Books on C and C++ § Variadic functions (with a variable number of arguments, e.g. printf() ) • B. Kernighan, D. Ritchie: The C Programming Language, 2nd ed., Prentice Hall, 1988. Covers ANSI-C. § C standard library • Bilting, Ulf; Skansholm, Jan: Vägen till C, Studentlitteratur, 2000. • And many other good books... Visit the library!! § C preprocessor macros § I/O in C and C++ § Assignment semantics TDDI04, K. Arvidsson, IDA, Linköpings universitet. § www.google.com or other internet sources (but take care to judge the source, both good and bad exist) 2.29 TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.30 5 End of C A Short History of C++ § C++ developed in the early 1980’s by Bjarne Stroustroup at Bell Labs, starting from ”C with Classes” • OOP layer (classes, objects, inheritance, polymorphism) grafted on top of C • Includes ANSI-C (and thereby all its low-level features) • • More complex than Java or C# Caution: Similar syntax to Java but different semantics § ANSI/ISO standardized C++ 1997 § Standard Template Library (STL) • TDDI04, K. Arvidsson, IDA, Linköpings universitet. TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.31 Differences for C++ class Counter { public: Counter(); // constructor has same name as the class Counter( int ); // another constructor: C++ is polymorphic ~Counter(); // destructor – Tilde class name. No parameters. private: class My_Counter { public: int x; #include ”My_ClassDef.hh” void set ( int ); int My_Counter::get ( void ) { int get ( void ); return counter; int incr( void ); } private: // other methods defined in other files ... My_Counter c; // definition int counter; void main( void ) { c.set( 17 ); } }; 2.32 C++ Constructors and Destructors (1) § Header files usually contain the class declarations. § Module source files usually contain implementations (definitions) of class member functions § In-line definition of member functions is possible, but no coupling between file names and class implementations is enforced – member functions may be defined anywhere, using the scope resolution operator :: TDDI04, K. Arvidsson, IDA, Linköpings universitet. standardized set of generic abstract data types in C++ }; Counter a; // definition; calls the first constructor automatically Counter b(17 ); // calls the second constructor automatically // Global variables reside in module, cannot be destructed. TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.33 2.34 C++ Constructors and Destructors (2) C++ Constructors and Destructors (3) Counter *func0 ( void ) { // Intention: function returning instance of Counter (”factory”) Counter a; // allocated on stack – an automatic variable return &a; // ?? Destructor called for a upon return, } // stack frame deallocated -> stale address in a Counter *func0 ( void ) { // Intention: function returning instance of Counter (”factory”) Counter a; // allocated on stack – an automatic variable return &a; // ?? Destructor called for a upon return, } // stack frame deallocated -> stale address in a Solution 1: Implicit copying on return: Counter func1 ( void ) Solution 2: Allocate the object instead on the heap: { Counter a; // allocated on stack – an automatic variable return a; // Destructor called for a upon return, Counter *func2 ( void ) { Counter *pa; pa = new Counter(); return pa; // but a is copied to the caller via return before that } Call: Counter b = func1(); TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.35 // copy return value to b // new returns a pointer to the object // (as in Java) } TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.36 6 C++ Constructors and Destructors (4) C++ Assignment Semantics § C++ has no garbage collection. § Assignment of objects in Java copies the object references: § Explicit deallocation of heap-allocated objects to avoid memory leaks X a = * fn_allocating_and_returning_a_heap_object(); Y *b = fn_allocating_and_returning_a_heap_object(); Z *c = new Z(); ... (use a, b, c) delete &a; // as free(), but also calls destructor ~X() delete b; 13 Counter b = a; 28 § Assignment of objects in C++ copies the object attributes: Counter a; 13 Counter b = a; 13 (hence, &b != &a) § Java objects are like C-pointers to (heap-allocated) structs. delete c; TDDI04, K. Arvidsson, IDA, Linköpings universitet. Counter a; § C++ objects are like C-structs. 2.37 TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.38 C / C++: There is much more to say... § Type conversions and casting § Bit-level operations § Operator precedence order § Variadic functions (with a variable number of arguments, e.g. printf() ) § C standard library § C preprocessor macros § I/O in C and C++ § C++ reference parameters § C++ operator overloading § C++ multiple implementation inheritance § C++ exceptions § C++ generic types (templates) § STL ... TDDI04, K. Arvidsson, IDA, Linköpings universitet. 2.39 7