---头文件
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/error.h>
- #include <linux/mm.h>
- #include <linux/sched.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
---设备号的申请
- static int mem_major = MEMDEV_MAJOR;
- int result;
- dev_t devno = MKDEV(mem_major, 0);
- if (mem_major)
- result = register_chrdev_region(devno, 1, "chrdev");
- else
- {
- //该处的chrdev的名字显示在/proc/devices里面,跟/dev中的设备节点木有关系,他们通过主设备号关联
- result = alloc_chrdev_region(&devno, 0, 1, "chrdev");
- mem_major = MAJOR(devno);
- printk("Major-->%d\n", mem_major);
- }
- if (result < 0)
- return result;
---利用private
- /* 对于存在多个次设备的情况下filp->private_data就能发挥特殊作用 */
- int mem_open(struct inode *inode, struct file *filp)
- {
- struct mem_dev *dev;
- int num = MINOR(inode->i_rdev);//或者num = iminor(inode);
- if (num >= MEMDEV_NR_DEVS)
- return -ENODEV;
- dev = &mem_devp[num];
- filp->private_data = dev;
- }
---设备的初始化、注册和注销
- struct cdev cdev;
- cdev_init(&cdev, &mem_fops);
- cdev.owner = THIS_MODULE;
- //cdev.ops = &mem_fops;
- //或者用下面的代码
- struct cdev *cdev = cdev_alloc();
- cdev->ops = &mem_fops;
- cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
- cdev_del(&cdev);
- unregister_chrdev_region(MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
---创建、注销设备文件
- //手动创建设备节点
- mknod filename type major minor
- //自动生成设备节点
- //2.6.12
- #ifdef CONFIG_DEVFS_FS
- devfs_mk_cdev(devno, S_IFCHR|S_IRUGO|S_IWUSR, "globalmem");
- #endif
- //2.6.32
- struct class *my_class;
- my_class = class_create(THIS_MODULE, "my_class");
- if (IS_ERR(my_class))
- return -1;
- device_create(my_class, NULL, MKDEV(globalmem_major, 0), NULL, "globalmemdev");
- //自动注销设备节点
- device_destroy(my_class, MKDEV(globalmem_major, 0));
- class_destroy(my_class);
--poll模板
- static unsigned int xxx_poll(struct file *filp, poll_tabel *wait)
- {
- unsigned int mask = 0;
- struct xxx_dev *dev = filp->private_data;
- poll_wait(filp, &dev->r_wait, wait);
- poll_wait(filp, &dev->w_wait, wait);
- if (...)
- {
- mask |= POLLIN | POLLRDNORM;
- }
- if (xxx)
- {
- mask |= POLLOUT | POLLWRNORM;
- }
- ...
- return mask;
- }
--应用层select
需要注意的是:读写集都要添加(否则,可能会有问题),根据需要选择while语句里面的if分支。
- fd_set rfds, wfds;
- while(1)
- {
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_SET(fd, &rfds);
- FD_SET(fd, &wfds);
- select(fd + 1, &rfds, &wfds, NULL, NULL);
- if (FD_ISSET(fd, &rfds))
- {
- if (size = read(fd, buf_r, 10) < 10)
- {
- xxx;
- }
- else
- xxx;
- }
- if (FD_ISSET(fd, &wfds))
- {
- }
- }
---tasklet和工作队列
- //tasklet
- void xxx_do_tasklet(unsigned long);
- DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);
- /*中断底半部*/
- void xxx_do_tasklet(unsigned long)
- {
- }
- /*中断顶半部*/
- irqreturn_t xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
- {
- ...
- tasklet_schedule(&xxx_tasklet);
- ...
- }
- //工作队列
- struct work_struct xxx_wq;
- void xxx_do_work(unsigned long);
- /*中断底半部*/
- void xxx_do_work(unsigned long)
- {
- }
- /*中断顶半部*/
- irqreturn_t xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
- {
- ...
- schedule_work(&xxx_wq);
- ...
- }
- int __init xxx_init(void)
- {
- ...
- INIT_WORK(&xxx_wq, (void(*)(void*))xxx_do_work, NULL);
- ...
- }
阅读(1020) | 评论(0) | 转发(0) |