1 / 22

Using our device-drivers

Using our device-drivers. How can an application display the data in a device special file?. The ‘fileview.cpp’ application. Purpose: a tool for viewing arbitrary files Some files have ascii text Other files have binary data So display in both hexadecimal and ascii

sally
Download Presentation

Using our device-drivers

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Using our device-drivers How can an application display the data in a device special file?

  2. The ‘fileview.cpp’ application • Purpose: a tool for viewing arbitrary files • Some files have ascii text • Other files have binary data • So display in both hexadecimal and ascii • Some ascii characters are ‘control codes’ • Some bytes are not ascii characters at all • So show a substitute mark as necessary

  3. Easy file navigation • Files may be quite large • Can only fit small pieces on one screen • And only some parts may be of interest • Also some hex formats can be confusing • Need a way to find what we want to see • Need it to remain visible while we read it • Need flexibility to adjust display format

  4. The ‘curses’ library • Offers users an ‘interactive’ interface • Allows use of normal keyboard input • Allows use of a mouse • Allows use of ‘windows’ and ‘colors’ • Allows use cursor-keys for navigation • Allows use of ‘unbuffered’ keystrokes • Offers instant refresh of display screen

  5. Concept behind ‘curses’ • Works on screens, windows, subwindows • Maintains several internal data-structures • Two of these are ‘stdscr’ and ‘curscr’ • Both are ‘maps’ of your physical screen • Drawing is done to the ‘stdscr’ window • But it doesn’t show up immediately • ‘refresh()’: compares ‘stdscr’ to ‘curscr’ and then only copies the parts that are ‘new’

  6. Using ‘ncurses’ with Linux • #include <curses.h> • ‘initscr()’ initializes library data-structures • ‘noecho()’ turns off keystroke echoing • ‘raw()’ and ‘cbreak()’ set special behaviors • ‘refresh()’ updates the display screen • ‘endwin()’ restores normal tty-behavior

  7. The typical ‘curses’ program #include <unistd.h> #include <stdlib.h> #include <curses.h> int main( int argc, char **argv ) { initscr(); … endwin(); }

  8. Compiling ‘ncurses’ programs • Must use the ‘-l’ command-line switch: • Example: $ g++ fileview.cpp –lncurses –o fileview • This is lowercase ‘L’ (not uppercase ‘i’) • It means link with ‘libncurses.so’ library • Object libraries are in directory: ‘/usr/lib’

  9. Some frequent functions • ‘clear()’ • ‘move()’ • ‘printw()’ • ‘mvprintw()’ • ‘refresh()’ • ‘newwin()’ • ‘box()’

  10. Reference • Good introductory tutorial appears in: Richard Stones and Neil Matthew, “Beginning Linux Programming (2nd Ed.)” (WROX Press Ltd, 1999), Chapter 6.

  11. Unusual goal of ‘fileview.cpp’ • Wanted to look at VERY large device-files • Eample: /dev/hda • This device file represents the hard disk • Size of today’s hard disk could be 180GB! • So file-positions could not be of type ‘long’ • Linux introduces a 64-bit type: loff_t • Kernel offers ‘sys_llseek()’ system-call

  12. Linux uses ‘glibc’ C-library • The Gnu version of Standard C Library • ‘glibc’ implements system-call interfaces for the standard UNIX C functions, like open(), close(), read(), write(), and lseek() • But Gnu C Library omitted ‘llseek()’ • So can’t do seek-operations on big files!

  13. Calling ‘llseek()’ anyway • Programmers can call the kernel directly • Can bypass the ‘glibc’ Standard C Library • But need to obey system-call conventions • Transition from user-mode to kernel-mode • Requires use of a special CPU instruction • This instruction is ‘architecture-specific’ • For Pentium CPU: asm(“ int $0x80 “);

  14. Some ‘macros’ make it easier • #include <asm/unistd.h> • Calling ‘sys_llseek()’ requires 5 arguments • Arguments must go into CPU registers • ‘sys_call_table[ ]’ array-index goes in EAX • The macro to use is named ‘_syscall5’

  15. A programming ‘bug’ • Standard C ‘read()’ function returns ‘int’ • Meaning of the ‘read()’ return-value: retval > 0 : ‘retval’ bytes successfully read retval = 0 : end-of-file reached, so no data retval < 0 : some error prevented reading • Return-value wasn’t checked in ‘fileview’!

  16. Why wasn’t ‘bug’ found? • ‘fileview’ always tried to read 256 bytes • Never tried to read beyond ‘end-of-file’ • Never tried to read data that ‘wasn’t there’ • So no reason why retval wouldn’t be 256

  17. But project #3 is different • ‘ram.c’ must read ALL physical pages • ‘high memory’ pages not always ‘mapped’ • And pages are not ‘mapped’ contiguously • 256 bytes could cross a page-boundary • Starting address: 0x00000F80 • Ending address: 0x00001080 • So some ‘read()’ errors could easily occur

  18. How can ‘bug’ be fixed? • Several solutions are possible • Best to try minimizing the code-changes • Should focus on correct ‘fix’ for all drivers • Obey rules for driver ‘read()’ functions

  19. Some pseudo-code int my_read( int fd, char *cp, int count ) { int more = count; while ( more ) { int n = read( fd, cp, more ); if ( n <= 0 ) return n; cp += n; more -= n; } return count; }

  20. Recommendations • Consult “Linux Device Drivers” text • ‘read()’ method is described on page 80 • Do everything that’s actually necessary • But keep your code as simple as possible • During development: use ‘printk()’ output • For ‘release version’: omit ‘printk()’ output

  21. Exercise • Write a ‘hello world’ program in C • But don’t use ANY header-files!! • (i.e., bypass the Standard C Library) • How? • 1) setup static message-string • 2) setup registers with parameters • 3) use ‘int 0x80’ to enter the kernel

  22. ‘sys_write( int fd, void *msg, int n)’ • The system-call number is 4 • The STDOUT file-descriptor is 1 • The message-string address is $msg • The message-length (you count the bytes) • These 4 arguments go in CPU registers: EAX, EBX, ECX, EDX (in that order) • So your ‘main()’ needs only 5 instructions!

More Related