1 / 20

编写 Linux 下的设备驱动程序

编写 Linux 下的设备驱动程序. What we have learned?. 用 module 实现设备驱动程序 init_module, cleanup_module 设备也是文件;设备由主设备号、次设备号唯一标识 mknod /dev/status c <major_num> 0 登记 / 注销设备 register_chrdev, unregister_chrdev struct file_operations (include/linux/fs.h) 实现 file_operations 结构中指定的操作.

kateb
Download Presentation

编写 Linux 下的设备驱动程序

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 编写Linux下的设备驱动程序

  2. What we have learned? • 用module实现设备驱动程序 • init_module, cleanup_module • 设备也是文件;设备由主设备号、次设备号唯一标识 • mknod /dev/status c <major_num> 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. <linux/fs.h>: int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); int unregister_chrdev(unsigned int major, const char *name);

  5. <asm/uaccess.h>: 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. <linux/fs.h>: 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. <linux/fs.h>: 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 <linux/ioport.h>: 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) <asm/io.h>: • 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) • <linux/sched.h><linux/wait.h> • 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

More Related