Comprehensive Overview of Linux Device Drivers: Architecture, Implementation, and Practical Examples
This report provides an in-depth exploration of Linux device drivers, covering essential concepts such as kernel space vs user space, task management, and synchronization mechanisms like mutexes and semaphores. It details the implementation process of device drivers, including driver initialization, operations, and handling interrupts. The report also discusses advanced topics such as softirqs, scheduling policies, and the intricacies of driver development in embedded Linux environments. Ideal for students and professionals seeking a robust understanding of Linux system programming.
Comprehensive Overview of Linux Device Drivers: Architecture, Implementation, and Practical Examples
E N D
Presentation Transcript
Linux Driver Overview 報告人: 陸述人 http://www.ntut.edu.tw/~s4599001
Operating System Linux • Operating system • Kernel space/User space • MMU • mutex/semaphore/interrupt • Task structure • ptrace/mmu/signal/task relation /process id • file/timer/semaphores/misc • Main algorithm • Signal handing • Interrupt • Tasklets • Bottom haves • Software interrupt –max 32 • Void open_sorftirq(int nr, void (*action) (structure softirq_action *, void *data) • Raise_softirq() • Scheduler • SCHED_FIFO/SCHED_RR/SCHED_OTHER
Mutex • Definition • In computer programming, a mutex is a program object that allows multiple program threads to share the same resource, such as file access, but not simultaneously. • Andrea Steinbach and Angelika Schofer, as a master's thesis at Rheinische Friedrich-Wilhelms University.
Semaphore • Definition • A semaphore is a protected variable (or abstract data type) and constitutes the classic method for restricting access to shared resources (e.g. storage) in a multiprogramming environment. • Sample • Dining philosophers problem • do not prevent all deadlocks • invented by Edsger Dijkstra and first used in the THE operating system
Semaphore Programming P(Semaphore s) { await s > 0 then s = s-1; /* must be atomic once s > 0 is detected */ } V(Semaphore s) { s = s+1; /* must be atomic */ } Init(Semaphore s, Integer v) { s = v; }
Operating System in Linux -3 • Driver: • Modprobe/Insmod/rmmod/lsmod • Built in kernel
Driver implementation in Linux • Driver specifications • Char drivers • Console • Serial port • Block drivers • DMA transfer • Network interfaces • IO port / IO memory
Driver implementation in Linux • Interrupt • int request_irq(unsigned int irq,void (*handler)(int, void *, struct pt_regs *),unsigned long flags,const char *dev_name,void *dev_id); • void free_irq(unsigned int irq, void *dev_id);
Writing Linux Device DriverHeader files #include <linux/kernel.h> #include <linux/module.h> #include <linux/version.h> #include <linux/config.h> #include <linux/init.h> #include <linux/types.h> #include <linux/fs.h>
Writing Linux Device DriverInitialize register (clear) static int test_open(struct inode *inodePtr, struct file *fp) { printk( "Enter open routine.\n" ); return 0; } static int test_release(struct inode *inodePtr, struct file *fp) { MOD_DEC_USE_COUNT; printk( "Enter test_release\n" ); return 0; }
Writing Linux Device DriverOperation static ssize_t test_read(struct file *fp, char *buf, size_t len, loff_t *offset) { printk( "Enter test_read\n" ); return len; } static ssize_t test_write(struct file *fp, char *buf, size_t len, loff_t *offset) { printk( "Enter test_write\n" ); return len; }
Writing Linux Device DriverMapping struct file_operations test_fops = { read: test_read, write: test_write, open: test_open, release: test_release, ioctl: test_ioctl, };
Writing Linux Device Driver static int test_ioctl(struct inode *inodePtr, struct file *fp, unsigned int cmd, unsigned long arg) { switch( cmd ){ default: break; } return 0; }
Entry point Exit point Writing Linux Device DriverEntry point V.S. Exit point int test_init_module(void) { register_chrdev( 100, testName, &test_fops ); printk( "Init test module\n" ); return 0; } void test_cleanup_module(void) { unregister_chrdev( 100, testName ); printk( "UnInit test\n" ); } module_init ( test_init_module ); module_exit ( test_cleanup_module );
Create Environment • Compiler • gcc -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4.22/include -c -O -Wall drv.c -o drv.o • Make node • mknod /dev/test c 100 0 • Check node crw-rw-rw- 1 root dialout 4, 64 Jun 30 11:19 test crw-rw-rw- 1 root dialout 4, 65 Aug 16 00:00 ttyS1
Writing Application int main(int argc, char *argv[]) { int fd; char buf[256] = "Hello World!!"; fd = open( "/dev/test”, O_RDWR ); if ( fd == -1 ) { printf( "Open drv driver fail.[Application]\n“ ); return -1; } write( fd, buf, 6 ); close( fd ); return 0; }
Implementation in Embedded Linux • NOMMU (arm as example) • Uclinux(ww.uclinux.org) • MMU • http://www.arm.linux.org.uk/ • Other version • http://www.linux.org/
Implementation in Embedded Linux • The driver in embedded linux • Most implement in setting registers • The different in mmu/nommu • mmu • The same except less support • nommu • Almost no difference about address in user space /kernel sapce
Recommended Books && web sites • Linux Document Project • http://www.tldp.org • Advacend linux programming • http://www.advancedlinuxprogramming.com/alp-folder • Linux device drivers • http://www.xml.com/ldd/chapter/book/ • LINUX 核心程式設計 • Linux kernel programming M Beck • Understanding the LINUX KERNEL • Bovet & Cesati • Linux server hacks 駭客一百招 • Others—In the disk
Introduce to source navigator • http://sourcenav.sourceforge.net/
Define in <linux/kernel.h> struct file_operations { struct module *owner; ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); };