|
驱动:- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/errno.h>
- #include <linux/mm.h>//内存管理头文件,含有页面大小定义和一些页面释放函数原型
- #include <linux/sched.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <asm/io.h>//I/O头文件,以宏的嵌入汇编程序形式定义对I/O端口操作的函数。
- #include <asm/system.h>//系统头文件,定义了设置或修改描述符/中断门等的嵌入式汇编宏。
- #include <asm/uaccess.h>//包含了copy_to_user、copy_from_user等内核访问用户进程内存地址的函数定义
- #include <linux/slab.h>//包含了kcalloc、kzalloc内存分配函数的定义。
- #include <linux/poll.h>
- //--------------platform_device------------
- #include <linux/platform_device.h>
- //-------------class_create,device_create------
- #include <linux/device.h>
- /*用udev机制自动添加设备节点*/
- struct class *globalfifo_class;
- #define GLOBALFIFO_SIZE 0x1000 /*全局内存最大4K字节*/
- #define MEM_CLEAR 0x1 /*清0全局内存*/
- #define GLOBALFIFO_MAJOR 0 /*预设的globalfifo的主设备号*/
- #define DEVICE_NAME "globalfifo"
- static int globalfifo_major = GLOBALFIFO_MAJOR;
- /*globalfifo设备结构体*/
- struct globalfifo_dev
- {
- struct cdev cdev; /*cdev结构体*/
- unsigned char mem[GLOBALFIFO_SIZE]; /*全局内存*/
- unsigned int current_len;/*fifo 有效数据长度*/
- struct semaphore sem;/*并发控制用的信号量*/
- wait_queue_head_t r_wait;/*阻塞读用的等待队列头*/
- wait_queue_head_t w_wait;/*阻塞写用的等待队列头*/
- struct fasync_struct *async_queue;/*异步结构体指针*/
- };
- struct globalfifo_dev *globalfifo_devp; /*设备结构体指针*/
- /*文件打开函数*/
- int globalfifo_open(struct inode *inode, struct file *filp)
- {
- /*将设备结构体指针赋值给文件私有数据指针*/
- struct globalfifo_dev *dev;
- dev=container_of(inode->i_cdev,struct globalfifo_dev,cdev);//通过结构体成员的指针找到对应结构体的指针
- filp->private_data = dev;
- return 0;
- }
- /* ioctl设备控制函数 */
- static int globalfifo_ioctl(struct inode *inodep, struct file *filp, unsigned
- int cmd, unsigned long arg)
- {
- struct globalfifo_dev *dev = filp->private_data;/*获得设备结构体指针*/
- switch (cmd)
- {
- case MEM_CLEAR:
- if(down_interruptible(&dev->sem))/*获取信号量*/
- return -ERESTARTSYS;
-
- memset(dev->mem, 0, GLOBALFIFO_SIZE); //mem数组名,即空间首地址
- up(&dev->sem);
- printk(KERN_INFO "globalfifo is set to zero\n");
- break;
- default:
- return - EINVAL;
- }
- return 0;
- }
- /*读函数*/
- static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t size,
- loff_t *ppos)
- {
-
- int ret = 0;
- struct globalfifo_dev *dev = filp->private_data; /*获得设备结构体指针*/
- DECLARE_WAITQUEUE(wait,current);/*define wait queue*/
- if(down_interruptible(&dev->sem))/*获得信号量*/
- {
- return -ERESTARTSYS;
- }
- add_wait_queue(&dev->r_wait,&wait);/*进入读等待队列头*/
-
- /*等待fifo非空并检测用户空间是否要求非阻塞访问*/
- while(dev->current_len==0)
- {
- if(filp->f_flags &O_NONBLOCK)
- {
- ret = -EAGAIN;
- goto out;
- }
- __set_current_state(TASK_INTERRUPTIBLE);/*改变进程状态为睡眠*/
- /*********************************************************/
- up(&dev->sem);/*释放信号量,防止死锁*/
- /*********************************************************/
- schedule();/*调度其他进程执行,开始睡眠*/
-
- if(signal_pending(current))/*如果是因为信号唤醒*/
- {
- ret = -ERESTARTSYS;/*重新执行系统调用*/
- goto out2;
- } else
- if(down_interruptible(&dev->sem))
- {
- return -ERESTARTSYS;
- }
- }
-
- /*内核空间->用户空间*/
- if(size>dev->current_len)
- size=dev->current_len;
- if (copy_to_user(buf,dev->mem,size))
- {
- ret = - EFAULT; /* Bad address */
- goto out;
- }
- else
- {
- memcpy(dev->mem,dev->mem+size,size);/*fifo数据前移*/
- dev->current_len -=size;/*有效数据长度减少*/
- printk(KERN_INFO"read %d bytes(s),current_len:%d \n",size,dev->current_len);
-
- wake_up_interruptible(&dev->w_wait);/*唤醒写等待队列*/
- ret= size;
- }
- out:
- up(&dev->sem);/*释放信号量*/
- out2:
- remove_wait_queue(&dev->r_wait,&wait);
- __set_current_state(TASK_RUNNING);
- return ret;
- }
- /*写函数*/
- static ssize_t globalfifo_write(struct file *filp, const char __user *buf,
- size_t size, loff_t *ppos)
- {
- int ret = 0;
- struct globalfifo_dev *dev = filp->private_data; /*获得设备结构体指针*/
- DECLARE_WAITQUEUE(wait,current);/*define wait queue*/
- if(down_interruptible(&dev->sem))/*获得信号量*/
- {
- return -ERESTARTSYS;
- }
- add_wait_queue(&dev->w_wait,&wait);/*进入写等待队列*/
-
- /*等待fifo非满并检测用户空间是否要求非阻塞访问*/
- while(dev->current_len==GLOBALFIFO_SIZE)
- {
- if(filp->f_flags &O_NONBLOCK)
- {
- ret = -EAGAIN;
- goto out;
- }
- __set_current_state(TASK_INTERRUPTIBLE);/*改变进程状态为睡眠*/
- up(&dev->sem);/*释放信号量,防止死锁*/
- schedule();/*调度其他进程执行,开始睡眠*/
-
- if(signal_pending(current))
- {
- ret = -ERESTARTSYS;
- goto out2;
- } else
- if(down_interruptible(&dev->sem))
- {
- return -ERESTARTSYS;
- }
- }
-
- /*内核空间<-用户空间*/
- if(size>GLOBALFIFO_SIZE-dev->current_len)
- size=GLOBALFIFO_SIZE-dev->current_len;
- if (copy_from_user(dev->mem+dev->current_len,buf,size))
- {
- ret = - EFAULT; /* Bad address */
- goto out;
- }
- else
- {
- dev->current_len +=size;/*有效数据长度减少*/
- printk(KERN_INFO"write %d bytes(s),current_len:%d \n",size,dev->current_len);
-
- wake_up_interruptible(&dev->r_wait);/*唤醒读等待队列*/
- /*产生异步读信号*/
- if(dev->async_queue)
- kill_fasync(&dev->async_queue,SIGIO,POLL_IN);
-
- ret= size;
- }
- out:
- up(&dev->sem);/*释放信号量*/
- out2:
- remove_wait_queue(&dev->w_wait,&wait);
- __set_current_state(TASK_RUNNING);
- return ret;
- }
- static unsigned int globalfifo_poll(struct file *filp,poll_table *wait)
- {
- unsigned int mask=0;
- struct globalfifo_dev *dev=filp->private_data;
- if(down_interruptible(&dev->sem))
- {
- return -ERESTARTSYS;
- }
- poll_wait(filp,&dev->w_wait,wait);/*将对应的等待队列头添加到poll_table*/
- poll_wait(filp,&dev->w_wait,wait);
- /*fifo非空*/
- if(dev->current_len!=0)
- mask |=POLLIN|POLLRDNORM;/*标示数据可获得*/
- /*fifo非满*/
- if(dev->current_len!=GLOBALFIFO_SIZE)
- mask |=POLLOUT|POLLWRNORM;/*标示数据可获得*/
- up(&dev->sem);
- return mask;
- }
- static int globalfifo_fasync(int fd,struct file *filp,int mode)
- {
- struct globalfifo_dev *dev =filp->private_data;
- return fasync_helper(fd,filp,mode,&dev->async_queue);
- }
- /*文件释放函数*/
- int globalfifo_release(struct inode *inode, struct file *filp)
- {
- /*将文件从异步通知列表里删除*/
- globalfifo_fasync(-1,filp,0);
- return 0;
- }
- /*文件操作结构体*/
- static const struct file_operations globalfifo_fops =
- {
- .owner = THIS_MODULE,
- .read = globalfifo_read,
- .write = globalfifo_write,
- .ioctl = globalfifo_ioctl,
- .open = globalfifo_open,
- .release = globalfifo_release,
- .poll = globalfifo_poll,
- .fasync=globalfifo_fasync,
- };
- /*初始化并注册cdev*/
- static void globalfifo_setup_cdev(struct globalfifo_dev *dev, int index)
- {
- int err, devno = MKDEV(globalfifo_major, index);
- cdev_init(&dev->cdev, &globalfifo_fops);
- dev->cdev.owner = THIS_MODULE;
- dev->cdev.ops = &globalfifo_fops;
- err = cdev_add(&dev->cdev, devno, 1);
- if (err)
- printk(KERN_NOTICE "Error %d ", err);
- }
- static int __devinit globalfifo_probe(struct platform_device *pdev)
- {
- printk("in the globalfifo_probe!!\n");
- int result;
- dev_t devno = MKDEV(globalfifo_major, 0);
-
- /* 申请设备号*/
- if (globalfifo_major)
- result = register_chrdev_region(devno, 1, DEVICE_NAME);
- else /* 动态申请设备号 */
- {
- result = alloc_chrdev_region(&devno, 0, 1,DEVICE_NAME);
- globalfifo_major = MAJOR(devno);
- }
- if (result < 0)
- return result;
-
- /* 动态申请设备结构体的内存*/
- globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev), GFP_KERNEL);//kmalloc()内核空间;malloc()用户空间。返回起始地址
- if (!globalfifo_devp) /*申请失败*/
- {
- result = - ENOMEM;
- goto fail_malloc;
- }
- memset(globalfifo_devp, 0, sizeof(struct globalfifo_dev));//把此内存空间清零
-
- globalfifo_setup_cdev(globalfifo_devp, 0);//注册设备
-
- /*udev机制可以自动添加设备节点,只需要添加xxx_class这个类,以及device_create()*/
- globalfifo_class = class_create(THIS_MODULE, "globalfifo_class");/*在sys目录下创建xx_class这个类,/sys/class/~*/
- device_create(globalfifo_class, NULL, globalfifo_devp->cdev.dev, DEVICE_NAME, DEVICE_NAME);/*自动创建设备/dev/$DEVICE_NAME*/
-
- init_MUTEX(&globalfifo_devp->sem);/*初始化信号量*/
- init_waitqueue_head(&globalfifo_devp->r_wait);/*初始化读写等待队列*/
- init_waitqueue_head(&globalfifo_devp->w_wait);
-
- printk("globalfifo driver installed!\n");
- printk("globalfifo_major is:%d\n",globalfifo_major);
- printk("the device name is %s\n",DEVICE_NAME);
-
- return 0;
-
- fail_malloc: unregister_chrdev_region(devno, 1);
- return result;
- }
- static int __devexit globalfifo_remove(struct platform_device *pdev)
- {
- printk("in the globalfifo_remove!!\n");
- device_destroy(globalfifo_class, globalfifo_devp->cdev.dev);
- class_destroy(globalfifo_class);
-
- cdev_del(&globalfifo_devp->cdev); /*注销cdev*/
- kfree(globalfifo_devp); /*释放设备结构体内存*/
- unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1); /*释放设备号*/
- printk("globalfifo driver uninstalled!\n");
- return 0;
- }
- static struct platform_driver globalfifo_device_driver={
- .probe=globalfifo_probe,
- .remove=globalfifo_remove,
- .driver={
- .name=DEVICE_NAME,
- .owner=THIS_MODULE,
- },
- };
- /*设备驱动模块加载函数*/
- static int __init globalfifo_init(void)
- {
- return platform_driver_register(&globalfifo_device_driver);
- }
- /*模块卸载函数*/
- static void __exit globalfifo_exit(void)
- {
- platform_driver_unregister(&globalfifo_device_driver);
- }
- MODULE_AUTHOR("mhb@SEU");
- MODULE_LICENSE("Dual BSD/GPL");
- module_param(globalfifo_major, int, S_IRUGO);
- module_init(globalfifo_init);
- module_exit(globalfifo_exit);
复制代码 测试程序:- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <signal.h>
- void input_handler(int signum)
- {
- printf("signum is ;%d\n",signum);
- }
- int main()
- {
- int fd,oflags;
- fd=open("/dev/globalfifo",O_RDWR,S_IRUSR|S_IWUSR);
- if(fd != -1) {
- /*启动信号驱动机制*/
- signal(SIGIO,input_handler);/*让input_handler 处理SIGIO信号*/
- fcntl(fd,F_SETOWN,getpid());
- oflags=fcntl(fd,F_GETFL);
- fcntl(fd,F_SETFL,oflags|FASYNC);
- while(1)
- {
- sleep(100);
- }
- } else
- {
- printf("device open failed!\n");
- }
- return 0;
- }
复制代码 |
|