1 / 36

Character Device Driver ( Pre req : Multi tasking, threading)

Character Device Driver ( Pre req : Multi tasking, threading). Dr A Sahu Dept of Comp Sc & Engg . IIT Guwahati. Outline. Character Device Driver Characteristics and functionality Basic IO functions Multi tasking (pre requisite to do this) Examples Drivers (in detail)

gita
Download Presentation

Character Device Driver ( Pre req : Multi tasking, threading)

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. Character Device Driver ( Pre req: Multi tasking, threading) Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati

  2. Outline • Character Device Driver • Characteristics and functionality • Basic IO functions • Multi tasking (pre requisite to do this) • Examples Drivers (in detail) • ADC, Printer, Tape drive

  3. Linux Char Vs block $cd /dev/block/ $ ls –l rwxrwxrwx 1 root root 7 2010-08-12 21:32 1:0 -> ../ram0 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 1:1 -> ../ram1 … lrwxrwxrwx 1 root root 8 2010-08-12 21:32 1:15 -> ../ram15 lrwxrwxrwx 1 root root 6 2010-08-13 03:02 11:0 -> ../sr0 lrwxrwxrwx 1 root root 8 2010-08-13 03:02 7:0 -> ../loop0 lrwxrwxrwx 1 root root 8 2010-08-13 03:02 7:1 -> ../loop1 …. rwxrwxrwx 1 root root 8 2010-08-13 03:02 7:7 -> ../loop7 lrwxrwxrwx 1 root root 6 2010-08-13 03:02 8:0 -> ../sda lrwxrwxrwx 1 root root 7 2010-08-13 03:02 8:1 -> ../sda1 …. lrwxrwxrwx 1 root root 7 2010-08-13 03:02 8:5 -> ../sda5 # Formats, mounts, and sets permissions on my 16MB ramdisk $/bin/mount /dev/ram0 /mnt/rd Mount –o loop CD.iso /mnt/cdrom

  4. Linux Char Vs block $cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root 8 2010-08-13 03:02 10:144 -> ../nvram lrwxrwxrwx 1 root root 15 2010-08-12 21:32 10:223 -> ../input/uinput lrwxrwxrwx 1 root root 9 2010-08-13 03:02 10:227 -> ../mcelog lrwxrwxrwx 1 root root 7 2010-08-13 03:02 10:228 -> ../hpet lrwxrwxrwx 1 root root 7 2010-08-12 21:33 10:229 -> ../fuse lrwxrwxrwx 1 root root 11 2010-08-13 03:02 10:231 -> ../snapshot lrwxrwxrwx 1 root root 6 2010-08-12 21:32 10:232 -> ../kvm lrwxrwxrwx 1 root root 13 2010-08-12 21:32 10:57 -> ../vboxnetctl lrwxrwxrwx 1 root root 10 2010-08-12 21:32 10:58 -> ../vboxdrv lrwxrwxrwx 1 root root 21 2010-08-13 03:02 10:59 -> ../network_throughput lrwxrwxrwx 1 root root 18 2010-08-13 03:02 10:60 -> ../network_latency lrwxrwxrwx 1 root root 18 2010-08-13 03:02 10:61 -> ../cpu_dma_latency lrwxrwxrwx 1 root root 17 2010-08-13 03:02 10:62 -> ../mapper/control lrwxrwxrwx 1 root root 14 2010-08-13 03:02 10:63 -> ../vga_arbiter

  5. Linux Char Vs block $cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root 6 2010-08-13 03:02 1:1 -> ../mem lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:11 -> ../kmsg lrwxrwxrwx 1 root root 9 2010-08-13 03:02 1:12 -> ../oldmem lrwxrwxrwx 1 root root 15 2010-10-06 22:42 116:10 -> ../snd/pcmC1D0c lrwxrwxrwx 1 root root 16 2010-10-06 22:42 116:11 -> ../snd/controlC1 lrwxrwxrwx 1 root root 12 2010-08-12 21:32 116:2 -> ../snd/timer lrwxrwxrwx 1 root root 10 2010-08-12 21:32 116:3 -> ../snd/seq lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:4 -> ../snd/pcmC0D1p lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:5 -> ../snd/pcmC0D0p lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:6 -> ../snd/pcmC0D0c lrwxrwxrwx 1 root root 13 2010-08-12 21:32 116:7 -> ../snd/hwC0D3 lrwxrwxrwx 1 root root 16 2010-08-12 21:32 116:8 -> ../snd/controlC0 lrwxrwxrwx 1 root root 15 2010-10-06 22:42 116:9 -> ../snd/pcmC1D0p lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:3 -> ../null lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:32 -> ../input/mouse0 lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:33 -> ../input/mouse1 lrwxrwxrwx 1 root root 13 2010-08-13 03:02 13:63 -> ../input/mice

  6. Linux Char Vs block $cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:64 -> ../input/event0 lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:65 -> ../input/event1 lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:66 -> ../input/event2 rwxrwxrwx 1 root root 13 2010-08-13 03:02 162:0 -> ../raw/rawctl lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:7 -> ../full lrwxrwxrwx 1 root root 9 2010-08-13 03:02 1:8 -> ../random lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:0 -> ../bus/usb/001/001 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:128 -> ../bus/usb/002/001 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:256 -> ../bus/usb/003/001 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:384 -> ../bus/usb/004/001 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:512 -> ../bus/usb/005/001 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:513 -> ../bus/usb/005/002 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:640 -> ../bus/usb/006/001 lrwxrwxrwx 1 root root 18 2010-10-06 22:42 189:649 -> ../bus/usb/006/010 lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:768 -> ../bus/usb/007/001 lrwxrwxrwx 1 root root 10 2010-08-13 03:02 1:9 -> ../urandom lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:0 -> ../cpu/0/msr lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:1 -> ../cpu/1/msr lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:2 -> ../cpu/2/msr lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:0 -> ../cpu/0/cpuid lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:1 -> ../cpu/1/cpuid lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:2 -> ../cpu/2/cpuid

  7. Linux Char Vs block $cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root 6 2010-08-13 03:02 21:0 -> ../sg0 lrwxrwxrwx 1 root root 6 2010-08-13 03:02 21:1 -> ../sg1 lrwxrwxrwx 1 root root 12 2010-08-13 03:02 226:0 -> ../dri/card0 lrwxrwxrwx 1 root root 17 2010-08-13 03:02 226:64 -> ../dri/controlD64 lrwxrwxrwx 1 root root 10 2010-08-13 03:02 250:0 -> ../hidraw0 lrwxrwxrwx 1 root root 10 2010-10-06 22:42 250:1 -> ../hidraw1 lrwxrwxrwx 1 root root 10 2010-08-13 03:02 251:0 -> ../usbmon0 … lrwxrwxrwx 1 root root 10 2010-08-13 03:02 251:7 -> ../usbmon7 lrwxrwxrwx 1 root root 14 2010-08-13 03:02 252:0 -> ../bsg/0:0:0:0 lrwxrwxrwx 1 root root 7 2010-08-13 03:02 254:0 -> ../rtc0 lrwxrwxrwx 1 root root 6 2010-08-13 03:02 29:0 -> ../fb0 lrwxrwxrwx 1 root root 7 2010-08-13 03:02 4:0 -> ../tty0 … lrwxrwxrwx 1 root root 8 2010-08-13 03:02 4:38 -> ../tty38 lrwxrwxrwx 1 root root 10 2010-08-13 03:02 5:1 -> ../console lrwxrwxrwx 1 root root 7 2010-08-13 03:02 5:2 -> ../ptmx lrwxrwxrwx 1 root root 6 2010-08-13 03:02 7:0 -> ../vcs .. lrwxrwxrwx 1 root root 7 2010-08-13 03:02 7:1 -> ../vcs6 lrwxrwxrwx 1 root root 7 2010-08-13 03:02 7:128 -> ../vcsa.. lrwxrwxrwx 1 root root 8 2010-08-12 21:32 7:134 -> ../vcsa6 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:2 -> ../vcs2 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:3 -> ../vcs3 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:4 -> ../vcs4 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:5 -> ../vcs5 lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:6 -> ../vcs6 lrwxrwxrwx 1 root root 11 2010-08-12 21:32 99:0 -> ../parport0

  8. Basic char-driver components Device-driver LKM layout module’s ‘payload’ is a collection of callback-functions having prescribed prototypes function function function AND a ‘package’ of function-pointers fops . . . the usual pair of module-administration functions init registers the ‘fops’ exit unregisters the ‘fops’

  9. Character Device Drivers • Character device drivers normally perform I/O in a byte stream. • Examples of devices using character drivers include tape drives and serial ports. • Character device drivers can also provide additional interfaces not present in block drivers, • I/O control (ioctl) commands • memory mapping • device polling.

  10. Standard File-I/O functions intopen( char *pathname, int flags, … ); intread( intfd, void *buf, size_t count ); intwrite( intfd, void *buf, size_t count ); intlseek( intfd, loff_t offset, int whence ); intclose( intfd ); (and other less-often-used file-I/O functions) root# mknod /dev/cmos c 70 0 Read /dev/cmos as a FILE

  11. Multi-tasking • Modern operating systems allow multiple users to share a computer’s resources • Users are allowed to run multiple tasks • The OS kernel must protect each task from interference by other tasks, while allowing every task to take its turn using some of the processor’s available time

  12. Stacks and task-descriptors • To manage multitasking, the OS needs to use a data-structure which can keep track of every task’s progress and usage of the computer’s available resources (physical memory, open files, pending signals, etc.) • Such a data-structure is called a ‘process descriptor’ – every active task needs one • Every task needs its own ‘private’ stack

  13. What’s on a program’s stack? Upon entering ‘main()’: • A program’s exit-address is on user stack • Command-line arguments on user stack • Environment variables are on user stack During execution of ‘main()’: • Function parameters and return-addresses • Storage locations for ‘automatic’ variables

  14. Entering the kernel… A user process enters ‘kernel-mode’: • when it decides to execute a system-call • when it is ‘interrupted’ (e.g. by the timer) • when ‘exceptions’ occur (e.g. divide by 0)

  15. Switching to a different stack • Entering kernel-mode involves not only a ‘privilege-level transition’ (from level 3 to level 0), but also a stack-area ‘switch’ • This is necessary for robustness: e.g., user-mode stack might be exhausted • This is desirable for security: e.g, privileged data might be accessible

  16. What’s on the kernel stack? Upon entering kernel-mode: • task’s registers are saved on kernel stack (e.g., address of task’s user-mode stack) During execution of kernel functions: • Function parameters and return-addresses • Storage locations for ‘automatic’ variables

  17. Supporting structures • So every task, in addition to having its own code and data, will also have a stack-area that is located in user-space, plus another stack-area that is located in kernel-space • Each task also has a process-descriptor which is accessible only in kernel-space

  18. A task’s virtual-memory layout process descriptor and kernel-mode stack User space Kernel space Privilege-level 0 User-mode stack-area Privilege-level 3 Shared runtime-libraries Task’s code and data

  19. The Linux process descriptor pagedir[] task_struct state mm_struct Each process descriptor contains many fields and some are pointers to other kernel structures which may themselves include fields that point to structures *stack flags *pgd *mm user_struct exit_code *user files_struct pid *files signal_struct *parent *signal

  20. Something new in 2.6 • Linux uses part of a task’s kernel-stack • page-frame to store ‘thread information’ • The thread-info includes a pointer to the task’s process-descriptor data-structure Task’s kernel-stack structtask_struct 8-KB Task’s process-descriptor Task’s thread-info page-frame aligned

  21. Tasks have ’states’ From kernel-header: <linux/sched.h> • #define TASK_RUNNING 0 • #define TASK_INTERRUPTIBLE 1 • #define TASK_UNINTERRUPTIBLE 2 • #define TASK_STOPPED 4 • #define TASK_TRACED 8 • #define TASK_NONINTERACTIVE 64 • #define TASK_DEAD 128

  22. Fields in a process-descriptor struct task_struct { volatile long state; void *stack; unsigned long flags; struct mm_struct *mm; struct thread_struct *thread; pid_t pid; char comm[16]; /* plus many other fields */ };

  23. Finding a task’s ‘thread-info’ • During a task’s execution in kernel-mode, it’s very quick to find that task’s thread-info object • Just use two assembly-language instructions: movl $0xFFFFF000, %eax andl %esp, %eax Ok, now %eax = the thread-info’s base-address There’s a macro that implements this computation

  24. Finding task-related kernel-data • Use a macro ‘task_thread_info( task )’ to get a pointer to the ‘thread_info’ structure: struct thread_info *info = task_thread_info( task ); • Then one more step gets you back to the address of the task’s process-descriptor: struct task_struct *task = info->task;

  25. The kernel’s ‘task-list’ • Kernel keeps a list of process descriptors • A ‘doubly-linked’ circular list is used • The ‘init_task’ serves as a fixed header • Other tasks inserted/deleted dynamically • Tasks have forward & backward pointers, implemented as fields in the ‘tasks’ field • To go forward: task = next_task( task ); • To go backward: task = prev_task( task );

  26. Doubly-linked circular list next_task init_task (pid=0) newest task … prev_task

  27. Maybe a big /proc file… • We can’t know ahead of time how many tasks are active in our system – this will depend on many varying factors, such as who else is logged in, which commands have been issued, whether we’re using text-mode console or graphical desktop • So it’s perfectly possible our pseudo-file might ‘overflow’ its kernel-supplied buffer!

  28. How to avoid buffer-overflow • Our module’s ‘get_info()’ callback-function has four parameter-values passed to it by the kernel: • char *buf - address of a small kernel buffer • char **start - address of a pointer variable • off_t offset - current offset of file-pointer • int buflen - size of the kernel buffer • The initial conditions are: offset == 0 and *start == NULL • Kernel’s behavior will vary if we modify *start

  29. Normal case • We expect the ‘/proc’ file to deliver a small amount of text-data (not more than would fit in the kernel-supplied buffer (e.g., 3KB) • So we make no change to ‘*start’ • Then kernel will deliver the data it finds in the buffer it had supplied to ‘get_info()’ • The kernel will not call ‘get_info()’ again (unless our file is closed and reopened)

  30. Alternative case • Our ‘get_info()’ function modifies the value of the (initially NULL) ‘*start’ pointer – for example, maybe assigning it the address of some buffer we’ve allocated, or even assigning the address of the kernel-buffer: *start = buf; • In this case, the kernel will again call our module’s ‘get_info()’ function, provided we returned a nonzero function-value before!

  31. The benefit • Knowing about this alternative option, we can design our ‘get_info()’ function so that it delivers a big amount of data in several small-size chunks, never overflowing the size-limitations on the kernel’s buffer • We just need to think carefully about the differing senarios under which ‘get_info()’ will be repeatedly called

  32. First pass • The value of ‘offset’ will be zero • We set *start to a buffer-address where we place a positive number of data-bytes • Kernel delivers those bytes to the ‘reader’, taking them from the *start address, then advances the file-pointer by that amount • Kernel calls our ‘get_info()’ again, but with a non-zero ‘offset’ value this time!

  33. Final time • When our ‘get_info()’ function has finally finished delivering all the desired data to the file’s ‘reader’, and still we receive yet another ‘get_info()’ call, then we simply return a function-value equal to zero, telling the kernel that the data has been exhausted -- and so not to call again!

  34. Our implementation structtask_struct *task; // ‘global’ variables’ values remembered intmy_get_info( char *buf, char **start, off_t offset, intbuflen ) { intlen = 0; if ( offset == 0 ) // our first time through this function { task = &init_task; // start of circular linked-list } else if ( task == &init_task ) return 0; // our final pass // put some data into the kernel-supplied buffer len += sprintf( buf+len, “pid=%d \n”, task->pid ); *start = buf; // tell kernel where to find data, and to call again task = next_task( task ); // advance to next node of circular list return len; // and tell kernel how far to advance }

  35. ‘Kernel threads’ • Some tasks don’t have a page-directory of their own – because they don’t need one • They only execute code, and access data, that resides in the kernel’s address space • They can just ‘borrow’ the page-directory that belongs to another task • These ‘kernel thread’ tasks will store the NULL-pointer value (i.e., zero) in the ‘mm’ field of their ‘task_struct’ descriptor (mm:mem map)

  36. Thanks

More Related