Presentation is loading. Please wait.

Presentation is loading. Please wait.

编写 Linux 下的设备驱动程序. What we have learned? 用 module 实现设备驱动程序 init_module, cleanup_module 设备也是文件;设备由主设备号、次设备号唯 一标识 mknod /dev/status c 0 登记 / 注销设备 register_chrdev,

Similar presentations


Presentation on theme: "编写 Linux 下的设备驱动程序. What we have learned? 用 module 实现设备驱动程序 init_module, cleanup_module 设备也是文件;设备由主设备号、次设备号唯 一标识 mknod /dev/status c 0 登记 / 注销设备 register_chrdev,"— Presentation transcript:

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


Download ppt "编写 Linux 下的设备驱动程序. What we have learned? 用 module 实现设备驱动程序 init_module, cleanup_module 设备也是文件;设备由主设备号、次设备号唯 一标识 mknod /dev/status c 0 登记 / 注销设备 register_chrdev,"

Similar presentations


Ads by Google