Presentation is loading. Please wait.

Presentation is loading. Please wait.

Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Character Device Driver – Characteristics and functionality – Basic IO functions Multi tasking (pre requisite.

Similar presentations


Presentation on theme: "Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Character Device Driver – Characteristics and functionality – Basic IO functions Multi tasking (pre requisite."— Presentation transcript:

1 Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati

2 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 $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 Mount –o loop CD.iso /mnt/cdrom # Formats, mounts, and sets permissions on my 16MB ramdisk $/bin/mount /dev/ram0 /mnt/rd

4 $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 $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 $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 $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 init exit fops function... Device-driver LKM layout registers the ‘fops’ unregisters the ‘fops’ module’s ‘payload’ is a collection of callback-functions having prescribed prototypes AND a ‘package’ of function-pointers the usual pair of module-administration functions

9 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 int open( char *pathname, int flags, … ); int read( int fd, void *buf, size_t count ); int write( int fd, void *buf, size_t count ); int lseek( int fd, loff_t offset, int whence ); int close( int fd ); (and other less-often-used file-I/O functions) root# mknod /dev/cmos c 70 0 Read /dev/cmos as a FILE root# mknod /dev/cmos c 70 0 Read /dev/cmos as a FILE

11 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 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 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 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 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 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 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 User space Kernel space User-mode stack-area Task’s code and data Privilege-level 0 Privilege-level 3 process descriptor and kernel-mode stack Shared runtime-libraries

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

20 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 Task’s thread-info page-frame aligned Task’s process-descriptor Task’s process-descriptor struct task_struct 8-KB

21 From kernel-header: #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE1 #define TASK_UNINTERRUPTIBLE2 #define TASK_STOPPED4 #define TASK_TRACED8 #define TASK_NONINTERACTIVE64 #define TASK_DEAD128

22 struct task_struct { volatile longstate; void*stack; unsigned longflags; struct mm_struct*mm; struct thread_struct*thread; pid_tpid; charcomm[16]; /* plus many other fields */ };

23 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 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 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 init_task (pid=0) init_task (pid=0) newest task newest task … next_task prev_task

27 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 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_toffset - current offset of file-pointer intbuflen - size of the kernel buffer The initial conditions are: offset == 0 and *start == NULL Kernel’s behavior will vary if we modify *start

29 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 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 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 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 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 struct task_struct *task;// ‘global’ variables’ values remembered int my_get_info( char *buf, char **start, off_t offset, int buflen ) { 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 returnlen;// and tell kernel how far to advance } struct task_struct *task;// ‘global’ variables’ values remembered int my_get_info( char *buf, char **start, off_t offset, int buflen ) { 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 returnlen;// and tell kernel how far to advance }

35 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


Download ppt "Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Character Device Driver – Characteristics and functionality – Basic IO functions Multi tasking (pre requisite."

Similar presentations


Ads by Google