完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、基本知识 Linux设备驱动分为:字符设备、块设备和网络设备。原理图如下: 二、示例 示例主要转载自博客园的博客,见上。只是我采用的的Linux内核版本比那篇博文的新,有小许改动,粘贴代码如下: 内核版本: ry@ubuntu:/$ uname -a Linux ubuntu 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux 文件:hello_mod.c [cpp] view plain copy print?
/* * ===================================================================================== * * Filename: hello.c * * Description: hello_mod * * Version: 1.0 * Created: 01/28/2011 05:07:55 PM * Revision: none * Compiler: gcc * * Author: Tishion (shion), tishion@163.com * Company: LIM * * ===================================================================================== */ MODULE_AUTHOR("Tishion"); MODULE_DESCRIPTION("Hello_mod driver by tishion"); static struct class * hello_class; static struct cdev hello_cdev; static dev_t devnum = 0; static char * modname = "hello_mod"; static char * devicename = "hello"; static char * classname = "hello_class"; static int open_count = 0; static struct semaphore sem; static DEFINE_SPINLOCK(spin); static char * inbuffer = NULL; static char * outbuffer = NULL; static lang_t langtype; static int hello_mod_open(struct inode , struct file ); static int hello_mod_release(struct inode , struct file ); static ssize_t hello_mod_read(struct file , char , size_t, loff_t *); static ssize_t hello_mod_write(struct file , const char , size_t, loff_t *); static long hello_mod_ioctl(struct file *, unsigned int, unsigned long); struct file_operations hello_mod_fops = { .owner = THIS_MODULE, .open = hello_mod_open, .read = hello_mod_read, .write = hello_mod_write, .unlocked_ioctl = hello_mod_ioctl, .release = hello_mod_release, }; static int hello_mod_open(struct inode *inode, struct file *pfile) { printk("+hello_mod_open()!/n"); spin_lock(&spin); if(open_count) { spin_unlock(&spin); return -EBUSY; } open_count++; spin_unlock(&spin); printk("-hello_mod_open()!/n"); return 0; } static int hello_mod_release(struct inode *inode, struct file *pfile) { printk("+hello_mod_release()!/n"); open_count--; printk("-hello_mod_release()!/n"); return 0; } static ssize_t hello_mod_read(struct file *pfile, char *user_buf, size_t len, loff_t *off) { printk("+hello_mod_read()!/n"); if(down_interruptible(&sem)){ return -ERESTARTSYS; }memset(outbuffer, 0, OUT_BUF_LEN);printk(" +switch()/n");switch(langtype){ case english: printk(" >in case: english/n"); sprintf(outbuffer, "Hello! %s.", inbuffer); break; case chinese: printk(" >in case: chinese/n"); sprintf(outbuffer, "你好! %s.", inbuffer); break; case pinyin: printk(" >in case: pinyin/n"); sprintf(outbuffer, "ni hao! %s.", inbuffer); break; default: printk(" >in case: default/n"); break;}printk(" -switch()/n");if(copy_to_user(user_buf, outbuffer, len)){ up(&sem); return -EFAULT;}up(&sem);printk("-hello_mod_read()!/n");return 0;} static ssize_t hello_mod_write(struct file *pfile, const char *user_buf, size_t len, loff_t *off) { printk(“+hello_mod_write()!/n”); if(down_interruptible(&sem)) { return -ERESTARTSYS; } if(len > IN_BUF_LEN) { printk(“Out of input buffer/n”); return -ERESTARTSYS; } if(copy_from_user(inbuffer, user_buf, len)) { up(&sem); return -EFAULT; } up(&sem); printk(“-hello_mod_write()!/n”); return 0; } static long hello_mod_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) { int err = 0; printk(“+hello_mod_ioctl()!/n”); printk(” +switch()/n”); switch(cmd) { case HELLO_IOCTL_RESETLANG: printk(” >in case: HELLO_IOCTL_RESETLANG/n”); langtype = english; break; case HELLO_IOCTL_GETLANG: printk(” >in case: HELLO_IOCTL_GETLANG/n”); err = copy_to_user((int *)arg, &langtype, sizeof(int)); break; case HELLO_IOCTL_SETLANG: printk(” >in case: HELLO_IOCTL_SETLANG/n”); err = copy_from_user(&langtype,(int *)arg, sizeof(int)); break; default: printk(” >in case: default/n”); err = ENOTSUPP; break; } printk(” -switch()/n”); printk(“-hello_mod_ioctl()!/n”); return err; } static int __init hello_mod_init(void) { int result; printk(“+hello_mod_init()!/n”); devnum = MKDEV(MAJOR_NUM, MINOR_NUM); result = register_chrdev_region(devnum, 1, modname); if(result < 0){ printk("hello_mod : can't get major number!/n"); return result;} cdev_init(&hello_cdev, &hello_mod_fops);hello_cdev.owner = THIS_MODULE;hello_cdev.ops = &hello_mod_fops;result = cdev_add(&hello_cdev, devnum, 1);if(result) printk("Failed at cdev_add()");hello_class = class_create(THIS_MODULE, classname);if(IS_ERR(hello_class)){ printk("Failed at class_create().Please exec [mknod] before operate the device/n");}else{ device_create(hello_class, NULL, devnum,NULL, devicename);}open_count = 0;langtype = english;inbuffer = (char *)kmalloc(IN_BUF_LEN, GFP_KERNEL);outbuffer = (char *)kmalloc(OUT_BUF_LEN, GFP_KERNEL);sema_init(&sem, 1);printk("-hello_mod_init()!/n");return 0;} static void __exit hello_mod_exit(void) { printk(“+hello_mod_exit!/n”); kfree(inbuffer); kfree(outbuffer); cdev_del(&hello_cdev); device_destroy(hello_class, devnum); class_destroy(hello_class); unregister_chrdev_region(devnum, 1); printk(“-hello_mod_exit!/n”); return ; } module_init(hello_mod_init); module_exit(hello_mod_exit); MODULE_LICENSE(“GPL”); 头文件:hello_mod_ioctl.h [cpp] view plain copy print?
/* * ===================================================================================== * * Filename: hello_mod_ioctl.h * * Description: define the cmd supported by hello_mod * * Version: 1.0 * Created: 06/19/2011 10:24:20 PM * Revision: none * Compiler: gcc * * Author: Tishion (shion), tishion@163.com * Company: LIM * * ===================================================================================== */#ifndef __HELLO_MOD_IOCTL_H__#define __HELLO_MOD_IOCTL_H__#define HELLO_MAGIC 12#define HELLO_IOCTL_RESETLANG _IO(HELLO_MAGIC,0) //set langtype = english#define HELLO_IOCTL_GETLANG _IOR(HELLO_MAGIC,1,int) //get langtype#define HELLO_IOCTL_SETLANG _IOW(HELLO_MAGIC,2,int) //set langtypetypedef enum _lang_t{ english, chinese, pinyin}lang_t;#endif Makefile文件:(注意:Makefile的’M’要大写) [cpp] view plain copy print?
#**********************************************# Makefile linux 2.6 Module # This makefile is written for Ubuntu 10.10# It may not perfomance without erros on the# other version or distributions.#**********************************************# BY:tishion# Mail:tishion@163.com# 2011/06/19#**********************************************obj-m += hello_mod.oCURRENT_PATH := (shellpwd)LINUXKERNEL:=(shellpwd)LINUXKERNEL:=(shell uname -r)LINUX_KERNEL_PATH := /usr/src/linux-headers-(LINUXKERNEL)all:make−C(LINUXKERNEL)all:make−C(LINUX_KERNEL_PATH) M=(CURRENTPATH)modulesclean:make−C(CURRENTPATH)modulesclean:make−C(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) cleaninstall: insmod hello_mod.kounistall: rmmod hello_mod 以上三个文件即为驱动代码另外,再给一个应用层测试代码,并共用驱动的头文件 hello_mod_test.c文件: [cpp] view plain copy print?
/* * ===================================================================================== * * Filename: hell_mod_test.c * * Description: hell_mod test app * * Version: 1.0 * Created: 06/20/2011 01:44:11 AM * Revision: none * Compiler: gcc * * Author: Tishion (shion), tishion@163.com * Company: LIM * * ===================================================================================== */#include { char outbuf[512]; char * myname = “tishion”; lang_t langtype = english; int fd = open(“/dev/hello”, O_RDWR, S_IRUSR|S_IWUSR); if(fd != -1) { write(fd, myname, strlen(myname)+1); langtype = chinese; ioctl(fd, HELLO_IOCTL_SETLANG, &langtype); read(fd, outbuf, 512); printf(“langtype=chinese:%s/n”, outbuf); memset(outbuf, 0, 512); langtype = pinyin; ioctl(fd, HELLO_IOCTL_SETLANG, &langtype); read(fd, outbuf, 512); printf(“langtype=pinyin:%s/n”, outbuf); memset(outbuf, 0, 512); ioctl(fd, HELLO_IOCTL_RESETLANG, &langtype); read(fd, outbuf, 512); printf(“langtype=english:%s/n”, outbuf); } else { perror(“Failed at open():”); } return 0; } 最后,安装原博客编译和查看结果。 需要注意的是,需要到“/var/log/”目录下着“syslog”文件。
|
|
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4866 浏览 0 评论
87350 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4670 浏览 2 评论
3562 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2449 浏览 0 评论
1945浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1315浏览 1评论
1219浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1288浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1206浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 07:22 , Processed in 1.024334 second(s), Total 73, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号