Scientific Visualization Using imagery to aid humans in understanding a complicated phenomenon An example from our class • • • • • • Student asked about ‘task_union’ objects “Can stack overwrite process descriptor?” Maybe we ought to be worried about this If descriptor gets corrupted, then: crash! System protects against users crashing But can’t protect if kernel code crashes! One picture is worth 1000 words • • • • • • • ‘modules’ let us study a running kernel We could look at a ‘task_union’ object But there are several design-issues How much ‘data’ will fit on one screen? How can we make ‘data’ understandable? How can we make a picture be ‘esthetic’? How much effort are we willing to devote? Doing data amalgamation • • • • • • • Size of a ‘task_union’ is 8KB Size of standard text screen is 2000 chars Not enough display-space for these bytes Idea: use a coarser subdivision of the data Subdivide a ‘task_union’ into quadwords Each quadword is 8-bytes in size So total number of quadwords is 1024 Screen layout • Standard text screen: 25 rows, 80 columns • Arrange 1K quadwords: 16 lines, 64 cells • Enough room left for a title and a legend title legend data Module’s design • • • • • Build a ‘/proc’ module Can use a ‘wizard’ for Rapid Development’ Our ‘proc_read()’ function needs two parts 1) prepare the selected data-amalgation 2) draw screen display: title, data, legend The ‘amalgamation’ step • Use an array of byte-size elements: • unsigned char glyph[ NR_CELLS ]; • Define manifest constants: #define GRANULARITY 8 #define SZ sizeof( union task_union ) #define NR_CELLS (SZ/GRANULARITY) Location of ‘task_union’ object • We can use value of ‘current’ macro: char *cp = (char*)current; (This creates pointer to the object’s base) An amalgamation algorithm int i, j; for ( i = 0; i < NR_CELLS; i++) { unsigned char total = 0; for (j = 0; j < GRANULARITY; j++) total |= cp[ i * GRANULARITY + j ]; glyph[ i ] = ( total ) ? ‘+’ : ‘-’; } Algorithm rationale • ‘clean’ memory will show up as ‘-’ • ‘dirty’ memory will show up as ‘+’ • But this won’t show areas we care about! • We want to see the ‘process descriptor’ • And we want to see the kernel stack A ‘secondary’ algorithm • Mark descriptor cells with letter ‘D’ • And mark stack cells with letter ‘S’ • But which are these cells in ‘glyth[]’ array? Glyphs for descriptor and stack • Process descriptor starts at offset zero • Descriptor’s ‘size’ tell where it ends int d_top = sizeof( struct task_struct )/8; for (i = 0; i < NR_CELLS; i++) if ( i < d_top ) glyph[ i ] = ‘D’; • Stack-area ends where task_union ends • But where does stack-area start? Reading cpu’s ESP register • • • • For IA-32 architectures, ESP = stacktop Need assembly language to read registers Here’s how to write it for gcc: Declare a memory-variable: unsigned long tos; Copy ESP register-value into variable ‘tos’: asm(“ movl %%esp, %0 “ : “=m” (tos) ); ‘kernel stack’ glyphs Task kernel-stack begins at address in ‘tos’ int s_org = ( tos / GRANULARITY ); for ( i = 0; i < NR_CELLS; i++) if ( i >= s_org ) glyph[ I ] = ‘S’; Drawing the screen display • • • • • Use ‘len’ variable to count output bytes Initialize ‘len’ to zero Draw to area whose address is in ‘buf’ Use ‘sprintf()’ function to draw into ‘buf’ Increment ‘len’ as more bytes are drawn: len += sprintf( buf+len, “\nMy Title\n” ); Use loop to draw data-glyphs Show 64 glyphs per line: for (i = 0; i < NR_CELLS; i++) { if ( ( i % 64 ) == 0 ) len += sprintf( buf+len, “\n” ); len += sprintf( buf+len, “%c”, glyph[ i ] ); } Understanding and Esthetics • • • • Picture looks ‘upside down’ Shows descriptor higher than stack Also doesn’t show where data is located Can we draw it so that: it’s easier to understand? it displays more information? it is prettier to look at? The visualization ‘demo’ • Module ‘visual.c’ is on our course website • Compile module using command $ make visual.o • Install module using command $ /sbin/insmod visual.o • Show ‘task_union’ object using command $ cat /proc/visual Project #2 • • • • • Write a Linux character device-driver Driver’s device-file will be: /dev/physmem Will allow programs to ‘read’ physical ram For safety: device should be ‘read-only’ Programs can treat ram as ordinary file ‘Physical’ versus ‘Virtual’ • Linux maps physical memory to top 1-GB • Physical memory starts from 0x00000000 • Kernel ‘sees’ it as starting at 0xC0000000 High_memory Virtual address space Physical RAM 4GB