LINUX Device Drivers: Partha

You might also like

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 20

LINUX Device Drivers

Partha
Kernel
• The central component of
operating system

• The bridge between applications


and the hardware

• 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.
Monolithic Kernel
• All OS services run along with the
main kernel thread, thus also
residing in the same memory
area.

• This approach provides rich and


powerful hardware access and
increases the speed of the system

• The main disadvantages are the


dependencies between system
components and the fact that
large kernels can become very
difficult to maintain.
Micro Kernel
• 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.

• 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.
LINUX Kernel
• LINUX Kernel is monolithic with the capability
of dynamically loading modules
System Call Interface
Assembly Code for • Each call within the libc library is
Executing System Calls generally a syscallX macro, where
2X+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.

• 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.
An Example
• read(fd,buffer,size) corresponds to a system call with three arguments. So this will
be expanded by the _syscall3 macro. A statement
static inline syscall3(int,read,int,fd,char *,buf,off_t,len)
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.

• 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 "zero". 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.
Interrupt
• 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.
• 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:
User/kernel space

• 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.
Characteristics of Kernel
• No conventional C library.
Has its own Kernel version
of C library.
• Doesn’t support floating
points
• No memory protection
• LINUX kernel (scheduler) is
preemptive
LINUX Kernel Versioning
Version number is x.y.z
• X – major version number
• Y – minor version number (even is stable/production, odd
is unstable/developer version)
• Z – release number
Device Drivers
• Softwares that interface hardwares with the OS
• Depending on data transmission there are three
types
o Char device – byte transmission (keyboard)
o Block device – block transmission (hard disk)
o Network device – packet transmission (router, bridge)
• Implemented in two ways
o Statically loadable – automatically loaded with the OS
image at the boot time
o Dynamically loadable – added to kernel space on demand
Compiling Driver Programs
• Cant compile in the conventional way using
CC. Need to write makefile to include special
files.
• Makefile priority –
1. makefile
2. Makefile
3. gnu_makefile
• To use the customized makefile use
make –f my_make_file
Programming Drivers
• Programs are called modules
• Like a main(), in driver programs the entry point is
init_module() and exit is cleanup_module()
• After compiling a .ko file is generated
• Using the utility insmod you can load your module
in the kernel
• Insmod is the runtime linker which
– Allocates memory
– Uses .ko to generate an executable
– Adds executable to the kernel space
Programming Drivers II
• Using macros we can rename the entry/exit
points
– module_init(my_entry)
– Module_exit(my_exit)
Module Documentation
• Using macros we can document
Passing parameters to module
• Using macros we can pass
Passing parameters to module
• Process and threads are same in LINUX
• In UNIX they are different
• In any program we can use
struct task_struct *current to see the
process info i.e. current->pid
Registration of modules
• In init_module(), use
register_chrdev(major number,”name”,&fops)
It returns 0 on success and negative on failure
• Use register_blkdev for block device
• Declaration struct file_operations fops. fops contains all the driver function
mapping to file functions (open, close, read, write)
• These major numbers are reserved for dynamic modules
– 60-63 | 120-127 | 240-254
• 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
• Minor number is used for different devices for the same driver
• Network device is treated as socket
• We can start a virtual device using mknod command
mknod LED c 254 0
• 12 bits for major number and 20 bits for minor number
File System Information in LINUX

• 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.

You might also like