Download presentation
Presentation is loading. Please wait.
Published byAshlie Warner Modified over 9 years ago
1
编写 Linux 下的设备驱动程序
2
What we have learned? 用 module 实现设备驱动程序 init_module, cleanup_module 设备也是文件;设备由主设备号、次设备号唯 一标识 mknod /dev/status c 0 登记 / 注销设备 register_chrdev, unregister_chrdev struct file_operations (include/linux/fs.h) 实现 file_operations 结构中指定的操作
3
What we have learned? (cont ’ d) 拷贝数据 to/from 用户空间 copy_to_user, copy_from_user 使用计数 (usage count) 每个 module 保留一个 usage count 宏: MOD_INC_USE_COUNT, MOD_DEC_USE_COUNT, MOD_IN_USE
4
: int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); int unregister_chrdev(unsigned int major, const char *name);
5
: unsigned long copy_to_user(void *to, const void *from, unsigned long count); unsigned long copy_from_user(void *to, const void *from, unsigned long count);
6
: struct file_operations { int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); … };
7
: struct file 的几个关键字段 mode_t f_mode; loff_t f_pos; unsigned int f_flags; struct file_operations *f_op; void *private_data; struct dentry *f_dentry;
8
What are we still to learn? Timing Hardware management I/O ports & I/O memory Interrupt handling
9
Programming I/O Two types of instructions can support I/O: special-purpose I/O instructions; memory-mapped load/store instructions. Intel x86 provides in, out instructions. Most other CPUs use memory-mapped I/O. I/O instructions do not preclude memory- mapped I/O.
10
Using I/O ports : int check_region(unsigned long start, unsigned long len); struct resource *request_region(unsigned long start, unsigned long len, char *name); void release_region(unsigned long start, unsigned long len);
11
Using I/O ports (cont ’ d) : Read/write 8-bit ports (byte width): unsigned intb(unsigned port); unsigned outb(unsigned char byte, unsigned port); Read/write 16-bit ports (word width): unsigned intw(unsigned port); unsigned outw(unsigned short word, unsigned port); Read/write 32-bit ports: unsigned intl(unsigned port); unsigned outl(unsigned longword, unsigned port);
12
Interrupt handling Installing an interrupt handler Implementing a handler
13
Installing an Interrupt Handler request_irq, free_irq 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); 调用时机
14
Implementing a handler static void sample_interrupt(int irq, void *dev_id, struct pt_regs *regs); irq: interrupt number dev_id: client data (private data used by the driver) regs: (rarely used) a snapshot of the processor ’ s context before the processor entered interrupt code
15
Implementing a handler (cont ’ d) 等待队列 (wait queue) wait_queue_head_t 类型 init_waitqueue_head interruptible_sleep_on wake_up_interruptible
16
Code examples void short_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct timeval tv; int written; do_gettimeofday(&tv); /* Write a 16-byte record. Assume PAGE_SIZE is a multiple of 16 */ written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec)); short_incr_bp(&short_head, written); wake_up_interruptible(&short_queue); }
17
Code examples (cont ’ d) ssize_t short_i_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) { int count0; while (short_head == short_tail) { interruptible_sleep_on(&short_queue); if (signal_pending (current)) /* a signal arrived */ return -ERESTARTSYS; /* tell the fs layer to handle it */ } count0 = short_head - short_tail; if (count0 < 0) /* wrapped */ count0 = short_buffer + PAGE_SIZE - short_tail; if (count0 < count) count = count0; if (copy_to_user(buf, (char *)short_tail, count)) return -EFAULT; short_incr_bp (&short_tail, count); return count; }
18
Bottom-Half (BH) Processing 中断处理程序尽量短小 top half: 实际响应中断的例程 bottom half: 被 top half 调度,并在稍后更 安全的时候运行的例程 将任务延迟到以后处理 task queue tasklet 内核定时器
19
Race condition 解决办法: 使用循环缓冲区并避免共享变量; 使用自旋锁 (spinlock) 强制实行互斥访问 使用原子操作递增或递减锁变量 尽量不要在中断处理程序中将信号量用于互 斥
20
Source codes study A touch screen driver /usr/src/linux/drivers/char/au1000_ts.c
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.