课程设计──LINUX字符驱动
2010-11-24 16:29
176 查看
转自: http://www.cnblogs.com/melorain/articles/842903.html 别人博客上摘来的,我写不出来,先学习下
课程设计──LINUX字符驱动
dev.c 代码
use.c 测试驱动代码
ac.sh 和 wa.sh,挂载和卸载驱动的shell
#!/bin/bash
insmod dev.ko
mknod /dev/lala c 253 0
chmod 777 /dev/lala
mknod /dev/lala2 c 253 1
chmod 777 /dev/lala2
#!/bin/bash
rm /dev/lala
rm /dev/lala2
rmmod dev
课程设计──LINUX字符驱动
dev.c 代码
#ifndef __KERNEL__ #define __KERNEL__ #endif #ifndef MODULE #define MODULE #endif //#include <linux/config.h> #include <linux/proc_fs.h> #include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/seq_file.h> #include <linux/ioctl.h> #include <linux/fcntl.h> #include <linux/poll.h> #include <asm/uaccess.h> #include <asm/system.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <asm/uaccess.h> #include <linux/kernel.h> #include <linux/slab.h> MODULE_LICENSE("GPL"); // 常量定义 #define BUFFERLENS 1024*1024; // 函数申明 ssize_t chuan_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); ssize_t chuan_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); int chuan_open(struct inode *inode, struct file *filp); int chuan_release(struct inode *inode, struct file *filp); // 初始化字符设备驱动的file_operations结构体 // 很奇怪的语法…… struct file_operations chuan_fops = { .owner = THIS_MODULE, .read = chuan_read, .write = chuan_write, .open = chuan_open, .release = chuan_release, }; // 主力结构————表示设备结构 struct chuan_dev { char * rer; unsigned int buffersize;// 缓冲区大小 unsigned int len;// 缓冲区已有长度 unsigned int start;// 起始数据偏移量 struct semaphore sem;// 信号量,用于互斥访问 struct cdev cdev;// 字符型设备结构 }; // 全局变量 struct chuan_dev chuan_device; dev_t dev_no = 0; // 初始化 int chuan_init(void) { int err=0; // 初始化cdev cdev_init(&chuan_device.cdev, &chuan_fops); chuan_device.cdev.owner = THIS_MODULE; chuan_device.cdev.ops = &chuan_fops; // 动态分配一个设备号 alloc_chrdev_region(&dev_no, 0, 1, "Rer'sPersonalDevices v1.11"); // 字符设备注册 err = cdev_add(&chuan_device.cdev, dev_no, 1); if (err){ printk(KERN_NOTICE "Error %d adding device/n", err); return -1; } else{ // 初始化互斥信号量 init_MUTEX(&chuan_device.sem); //printk("互斥信号量初始化成功/n"); printk(KERN_NOTICE "Device Initilize success./n"); return 0; /* succeed */ } } // 注销 void chuan_exit(void) { unregister_chrdev_region(dev_no, 1); cdev_del(&chuan_device.cdev); } // 打开 int chuan_open(struct inode *inode, struct file *filp) { struct chuan_dev *mydev; // 高级技巧,,我不是很明白 mydev = container_of(inode->i_cdev,struct chuan_dev,cdev); // 将private_data保存chuan_dev指针 filp->private_data = mydev; // 信号量,如果已经无资源了,就不打开 if (down_interruptible(&mydev->sem)) return -ERESTARTSYS; up(&mydev->sem); if(!mydev->rer){ // 如果缓冲区是空的,那么分配1k的内容给它 //printk("缓冲区还是空的./n"); mydev->rer = (char *)kmalloc(1024, GFP_KERNEL); memset(mydev->rer, 0, 1024); // 初始化参数 mydev->buffersize = 1024; mydev->len = mydev->start = 0; } else{ //printk("缓冲区已经有东西了.现将其初始化/n"); } return 0; } // 关闭 int chuan_release(struct inode *inode, struct file *filp) { return 0; } // 读取 ssize_t chuan_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { // int i; struct chuan_dev *mydev; //printk("读取/n"); // 读取数据 mydev = filp->private_data; // 信号量,如果已经无资源了,就不打开 if (down_interruptible(&mydev->sem)) return -ERESTARTSYS; /* printk("缓冲区数据量长度: %d/n",mydev->len); printk("缓冲区起始位置: %d/n",mydev->start); for(i=0;i<mydev->len+mydev->start;++i) printk("缓冲区: %d values %c/n",i,*(mydev->rer+i)); */ if(mydev->len>0){ if(count > mydev->len-mydev->start) count = mydev->len-mydev->start; if(copy_to_user(buf,mydev->rer+mydev->start,count)){ printk("拷贝失败./n"); } else{ mydev->start += count; if(mydev->start>=mydev->buffersize){ mydev->start = 0; mydev->len = 0; } printk("拷贝成功./n"); printk("start = %d/n",mydev->start); printk("len = %d/n",mydev->len); } } else{ printk("缓冲区还没有东西,,无法进行读取./n"); goto end; } end: // 将访问信号释放 up(&mydev->sem); return 0; } // 写入 ssize_t chuan_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct chuan_dev *mydev; // 写入数据 mydev = filp->private_data; // 信号量,如果已经无资源了,就不打开 if (down_interruptible(&mydev->sem)) return -ERESTARTSYS; if(!mydev->rer){ //printk(KERN_NOTICE "写入过程,《, 空的。./n"); } else{ //printk(KERN_NOTICE "写入过程, 已经有东西了。./n"); // 向缓冲区中写数据 if(mydev->start+mydev->len+count > mydev->buffersize){ // 如果预感到要溢出,那么就从头写 并且舍弃已有数据(这样很不好) memset(mydev->rer, 0, mydev->buffersize); if(count > mydev->buffersize) count = mydev->buffersize; mydev->start = mydev->len = 0; } if(copy_from_user(mydev->rer+mydev->len,buf,count)){ printk(KERN_NOTICE "写入失败./n"); } else{ mydev->len += count; printk(KERN_NOTICE "写入成功,当前缓冲区的大小为: %d./n",mydev->len); } } up(&mydev->sem); return 0; } module_init(chuan_init); module_exit(chuan_exit);
use.c 测试驱动代码
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> main() { int testdev; int i; char buf[10]; char redbuf[10]; // 先打开/dev/lala(从设备号为0),进行写入操作 testdev = open("/dev/lala",O_RDWR); if ( testdev == -1 ){ printf("Cann't open file /n"); }else{ printf("Open file Success./n"); for(i=0;i<10;++i) buf[i] = i+'a'; write(testdev,buf,10); write(testdev,buf,10); printf("写入设备成功/dev/lala/n"); memset(buf,0,10); read(testdev,redbuf,5); printf("读取设备成功/dev/lala/n"); for (i = 0; i < 5;i++) printf("收到数据: %c/n",redbuf[i]); printf("/n"); memset(buf,0,10); read(testdev,redbuf,5); printf("读取设备成功/dev/lala/n"); for (i = 0; i < 5;i++) printf("收到数据: %c/n",redbuf[i]); printf("/n"); close(testdev); } }
ac.sh 和 wa.sh,挂载和卸载驱动的shell
#!/bin/bash
insmod dev.ko
mknod /dev/lala c 253 0
chmod 777 /dev/lala
mknod /dev/lala2 c 253 1
chmod 777 /dev/lala2
#!/bin/bash
rm /dev/lala
rm /dev/lala2
rmmod dev
相关文章推荐
- 基于mini6410的linux驱动学习总结(四 设计字符设备驱动程序)
- Linux字符设备驱动之register_chrdev_region()系列
- linux字符驱动之poll机制GPIO状态监测驱动
- 【设计分享】Vmware虚拟机下,linux驱动及应用层实例
- Linux设备驱动之字符设备(一)
- Linux字符设备驱动之异步通知
- linux驱动学习--第十一天:第六章 Linux 字符设备驱动(一) 之 Linux 字符设备驱动结构
- linux字符驱动之初见
- 操作系统课程设计--Linux平台哲学家问题
- linux字符驱动与块驱动开发教程系列
- Linux字符设备驱动简介
- Linux设备驱动--简单字符设备驱动程序
- linux字符驱动之查询按键
- Linux驱动设计ioctl函数的cmd参数不能为2
- linux字符驱动之异步通知按键驱动
- Linux字符设备驱动-globalmem驱动编译加载遇到的问题及解决办法
- Linux USB设备驱动程序设计 和 USB下载线驱动设计
- linux字符驱动之中断按键 .
- 如何编写一个Linux字符设备驱动?
- linux字符驱动学习实践1(简单控制LED灯)