LINUX Device Drivers


Published on

some notes prepared for LINUX device driver test

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

LINUX Device Drivers

  1. 1. LINUX Device Drivers Partha
  2. 2. Kernel <ul><li>The central component of operating system </li></ul><ul><li>The bridge between applications and the hardware </li></ul><ul><li>Manages the system's resources providing the lowest-level abstraction layer (especially processors and I/O devices) and makes these facilities available through inter-process communication mechanisms and system calls. </li></ul>
  3. 3. Monolithic Kernel <ul><li>All OS services run along with the main kernel thread, thus also residing in the same memory area. </li></ul><ul><li>This approach provides rich and powerful hardware access and increases the speed of the system </li></ul><ul><li>The main disadvantages are the dependencies between system components and the fact that large kernels can become very difficult to maintain. </li></ul>
  4. 4. Micro Kernel <ul><li>Consists of defining a simple abstraction over the hardware, with a set of system calls to implement minimal OS services such as memory management etc. Other services, including those normally provided by the kernel such as networking, are implemented in user-space programs, referred to as servers. </li></ul><ul><li>Easier to maintain, but the large number of system calls and context switches might slow down the system because they typically generate more overhead than plain function calls. </li></ul>
  5. 5. LINUX Kernel <ul><li>LINUX Kernel is monolithic with the capability of dynamically loading modules </li></ul>
  6. 6. System Call Interface <ul><li>Each call within the libc library is generally a syscall X macro, where 2 X+2 is the number of parameters used by the actual routine. Each syscall macro expands to an assembly routine which sets up the calling stack frame and calls _system_call() through an interrupt, via the instruction int $0x80 which is used to transfer control to the kernel. </li></ul>Assembly Code for Executing System Calls <ul><li>Since the system call interface is exclusively register-parametered, six parameters at most can be used with a single system call. %eax is the syscall number; %ebx , %ecx , %edx , %esi , %edi and %ebp are the six generic registers used as param0-5; and %esp cannot be used because it's overwritten by the kernel when it enters ring 0 (i.e., kernel mode). In case more parameters are needed, some structure can be placed wherever you want within your address space and pointed to from a register (not the instruction pointer, nor the stack pointer; the kernel-space functions use the stack for parameters and local variables). This case is extremely rare, though; most system calls have either no parameters or only one. </li></ul>
  7. 7. An Example <ul><li>read(fd,buffer,size) corresponds to a system call with three arguments. So this will be expanded by the _syscall3 macro. A statement </li></ul><ul><li>static inline syscall3(int,read,int,fd,char *,buf,off_t,len) </li></ul><ul><li>has been added in the header file for the macro expansion to take place. After the expansion the system call number will be in register 'zero' and the argument to the system call will be in the general purpose registers of the processor. Also the macro will call the int 0x80 instruction after loading the registers. So the kernel mode is initiated and kernel will execute on behalf of the process initiated by the system call. </li></ul><ul><li>The int 0x80 instruction will call the system call handler. Each system call will have a routine or program defined in the kernel. Address of each of these routine are stored in the in array named sys_call_table (code in the file /usr/src/linux-/arch/i386/kernel/entry.S ).The path name has to be filled accordingly for different kernel version. The system call handler will call the service routine corresponding to the system call, by looking at the system call number loaded in the register &quot;zero&quot;. So the service routine corresponding to the read system call will be executed. After executing the service routing the control comes back to the system call handler and it will then give control back to the user process, also the mode of operation is changed to user mode. </li></ul>
  8. 8. Interrupt <ul><li>Vector 0x80 is used to transfer control to the kernel. This interrupt vector is initialized during system startup, along with other important vectors such as the system clock vector. </li></ul><ul><li>The startup_32() code found in /usr/src/linux/boot/head.S starts everything off by calling setup_idt() . This routine sets up an IDT (Interrupt Descriptor Table) with 256 entries. No interrupt entry points are actually loaded by this routine, as that is done only after paging has been enabled and the kernel has been moved to 0xC0000000. An IDT has 256 entries, each 4 bytes long, for a total of 1024 bytes. When start_kernel() (found in /usr/src/linux/init/main.c) is called it invokes trap_init() (found in /usr/src/linux/kernel/traps.c). trap_init() sets up the IDT via the macro set_trap_gate() (found in /usr/include/asm/system.h). trap_init() initializes the interrupt descriptor table as shown here: </li></ul>
  9. 9. User/kernel space <ul><li>User space is that portion of system memory in which user processes run. This contrasts with kernel space, which is that portion of memory in which the kernel executes and provides its services. Kernel space is where the kernel (i.e., the core of the operating system) executes (i.e., runs) and provides its services. </li></ul>
  10. 10. Characteristics of Kernel <ul><li>No conventional C library. Has its own Kernel version of C library. </li></ul><ul><li>Doesn’t support floating points </li></ul><ul><li>No memory protection </li></ul><ul><li>LINUX kernel (scheduler) is preemptive </li></ul>
  11. 11. LINUX Kernel Versioning <ul><li>Version number is x.y.z </li></ul><ul><li>X – major version number </li></ul><ul><li>Y – minor version number (even is stable/production, odd is unstable/developer version) </li></ul><ul><li>Z – release number </li></ul>
  12. 12. Device Drivers <ul><li>Softwares that interface hardwares with the OS </li></ul><ul><li>Depending on data transmission there are three types </li></ul><ul><ul><li>Char device – byte transmission (keyboard) </li></ul></ul><ul><ul><li>Block device – block transmission (hard disk) </li></ul></ul><ul><ul><li>Network device – packet transmission (router, bridge) </li></ul></ul><ul><li>Implemented in two ways </li></ul><ul><ul><li>Statically loadable – automatically loaded with the OS image at the boot time </li></ul></ul><ul><ul><li>Dynamically loadable – added to kernel space on demand </li></ul></ul>
  13. 13. Compiling Driver Programs <ul><li>Cant compile in the conventional way using CC. Need to write makefile to include special files. </li></ul><ul><li>Makefile priority – </li></ul><ul><ul><li>makefile </li></ul></ul><ul><ul><li>Makefile </li></ul></ul><ul><ul><li>gnu_makefile </li></ul></ul><ul><li>To use the customized makefile use </li></ul><ul><li>make –f my_make_file </li></ul>
  14. 14. Programming Drivers <ul><li>Programs are called modules </li></ul><ul><li>Like a main(), in driver programs the entry point is init_module() and exit is cleanup_module() </li></ul><ul><li>After compiling a .ko file is generated </li></ul><ul><li>Using the utility insmod you can load your module in the kernel </li></ul><ul><li>Insmod is the runtime linker which </li></ul><ul><ul><li>Allocates memory </li></ul></ul><ul><ul><li>Uses .ko to generate an executable </li></ul></ul><ul><ul><li>Adds executable to the kernel space </li></ul></ul>
  15. 15. Programming Drivers II <ul><li>Using macros we can rename the entry/exit points </li></ul><ul><ul><li>module_init( my_entry ) </li></ul></ul><ul><ul><li>Module_exit( my_exit ) </li></ul></ul>
  16. 16. Module Documentation <ul><li>Using macros we can document </li></ul>
  17. 17. Passing parameters to module <ul><li>Using macros we can pass </li></ul>
  18. 18. Passing parameters to module <ul><li>Process and threads are same in LINUX </li></ul><ul><li>In UNIX they are different </li></ul><ul><li>In any program we can use </li></ul><ul><li>struct task_struct *current to see the process info i.e. current->pid </li></ul>
  19. 19. Registration of modules <ul><li>In init_module(), use </li></ul><ul><li>register_chrdev(major number,”name”,&fops) </li></ul><ul><li>It returns 0 on success and negative on failure </li></ul><ul><li>Use register_blkdev for block device </li></ul><ul><li>Declaration struct file_operations fops. f ops contains all the driver function mapping to file functions (open, close, read, write) </li></ul><ul><li>These major numbers are reserved for dynamic modules </li></ul><ul><ul><li>60-63 | 120-127 | 240-254 </li></ul></ul><ul><li>register function can also be used for a dynamic registration (set first argument zero) in which case the returned positive number is the major number or negative on failure </li></ul><ul><li>Minor number is used for different devices for the same driver </li></ul><ul><li>Network device is treated as socket </li></ul><ul><li>We can start a virtual device using mknod command </li></ul><ul><li>mknod LED c 254 0 </li></ul><ul><li>12 bits for major number and 20 bits for minor number </li></ul>
  20. 20. File System Information in LINUX <ul><li>Every open file has an integer  file descriptor  value that the operating system uses as an index to a  1024-entry  file descriptor table located in the  u (user) area  for the process. The per-process file descriptor table references a  system file table,  which is located in kernel space. In turn, the  system file table  maps to a  System Inode table  that contains a reference to a more complete internal description of the file. </li></ul>