驱动程序-字符驱动
来源:互联网 发布:数据帧的长度计算公式 编辑:程序博客网 时间:2024/05/20 01:35
参考http://www.kerneltravel.net/?p=334
一、编写内核文件chardev.c
/*chardev.c*/#include <linux/kernel.h>#include <linux/fs.h> /*for file-f_op*/#include <linux/module.h>#include <asm/uaccess.h> /*for copy_to_user()*/#include <linux/cdev.h> /*for cdev ,cdev_init,cdev_add....*/MODULE_LICENSE("GPL");MODULE_AUTHOR("Helight");#define DP_MAJOR 248 /*the major number of the chardev*/#define DP_MINOR 0 /*the minor number of the chardev*/ static int char_read(struct file *filp,char __user *buffer,size_t,loff_t *); /*the read operation of the chardev----read the data from kernel*/ static int char_open(struct inode *,struct file *); /*open the chardev*/ static int char_write(struct file *filp,const char __user *buffer,size_t ,loff_t*); /*write data to kernel*/ static int char_release(struct inode *,struct file *); /*release the chardev*/ static int chropen; /*the chardev open or not*/ struct cdev *chardev; /*define a char device*/ static int len; static const struct file_operations char_ops = { .read = char_read, .write = char_write, .open = char_open, .release = char_release, }; static int __init char_init(void) { dev_t dev; printk(KERN_ALERT"Initing......\n"); dev=MKDEV(DP_MAJOR,DP_MINOR); chardev = cdev_alloc( ); if(chardev==NULL){ return -1; } if(register_chrdev_region(dev,10,"chardev")){ printk(KERN_ALERT"Register char dev error\n"); return -1; } chropen=0; len=0; cdev_init(chardev,&char_ops); if(cdev_add(chardev,dev,1)) { printk(KERN_ALERT"Add char dev error\n"); } return 0; } static int char_open(struct inode *inode,struct file *file) { if(chropen==0) chropen++; else{ printk(KERN_ALERT"Another process open the char device\n"); return -1; } try_module_get(THIS_MODULE); return 0; } static int char_release(struct inode *inode,struct file *file) { chropen--; module_put(THIS_MODULE); return 0; } static int char_read(struct file *filp,char __user *buffer,size_t length,loff_t *offset) { if(!copy_to_user(buffer,"hello world!",length)) { return 0; }else { if(!copy_to_user(buffer,"hello world!",strlen("hello world!"))) { return 0; } } return -1; } static int char_write(struct file *filp,const char __user *buffer,size_t length,loff_t *offset) { return 0; } static void __exit module_close(void) { len=0; printk(KERN_ALERT"Unloading..........\n"); unregister_chrdev_region(MKDEV(DP_MAJOR,DP_MINOR),10); cdev_del(chardev); } module_init(char_init); module_exit(module_close);
注意 DP_MAJOR 248 和 DP_MINOR 0 两个对应的设备号可以根据冲突情况修改,使用命令 ls -l /dev 可以查看到各种设备号分配情况。
二、编写测试文件Makefile
obj-m += chardev.o#generate the pathCURRENT_PATH:=$(shell pwd)#the current kernel version numberLINUX_KERNEL:=$(shell uname -r)#the absolute path#LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)#这里的内核路径注意根据实际情况修改,确保内核路径指向正确,以下是centos的路径#LINUX_KERNEL_PATH:=/usr/src/kernels/2.6.32-573.22.1.el6.i686LINUX_KERNEL_PATH:=/usr/src/kernels/2.6.18-194.el5-i686#complie objectall:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules#cleanclean:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
#注意make前面必须有tab字符,否则编译会出现make: Nothing to be done for `all'.
三、编写测试文件main.c
/*main.c*/#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h> int main(void) { int testdev; int i,rf=0; char buf[15]; memset(buf, 0, sizeof(buf)); testdev = open("/dev/chardev0",O_RDWR); if ( testdev == -1 ) { perror("open\n"); exit(0); } rf=read(testdev,buf,12); if(rf<0) perror("read error\n"); printf("R:%s\n",buf); close(testdev); return 0; }
四、测试
[root@stu106 chardev]# make
make -C /usr/src/kernels/2.6.18-194.el5-i686 M=/root/Desktop/chardev modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-194.el5-i686'
CC [M] /root/Desktop/chardev/chardev.o
Building modules, stage 2.
MODPOST
CC /root/Desktop/chardev/chardev.mod.o
LD [M] /root/Desktop/chardev/chardev.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-194.el5-i686'
[root@stu106 chardev]# insmod chardev.ko
加载内核
[root@stu106 chardev]# mknod /dev/chardev0 c 248 0
创建字符设备
[root@stu106 chardev]# chmod 666 /dev/chardev0
修改权限
[root@stu106 chardev]# gcc -o chardev_test main.c
[root@stu106 chardev]# ./chardev_test
R:hello world!
最后出现R:hello world!表示读取成功。
- 驱动程序-字符驱动
- 字符设备驱动----LED驱动程序
- 字符设备驱动--LED驱动程序
- 浅谈linux驱动之-字符设备驱动程序
- OK6410之ADC驱动程序 字符设备驱动
- Linux驱动程序开发 004- 字符设备驱动
- Linux设备驱动--简单字符设备驱动程序
- 【内核&驱动】字符设备驱动程序【1】
- 【内核&驱动】字符设备驱动程序【2】
- 【内核&驱动】字符设备驱动程序【3】
- 字符型设备驱动程序--gpio 驱动实例
- Linux驱动程序开发 - 字符设备驱动
- Linux设备驱动--字符设备驱动程序1
- Linux设备驱动--字符设备驱动程序2
- Linux字符驱动-验证globalmem驱动程序
- ARM内核驱动-设备驱动之字符驱动程序学习
- 10.字符设备驱动模型(1)-使用字符驱动程序
- Linux字符设备驱动程序开发(1)-使用字符设备驱动
- OpenCV_(3):编程辅助函数
- caffe 命令行解析
- 剑指offer-字符串
- Favicon.ico
- 先验概率和后验概率
- 驱动程序-字符驱动
- 【Unity闲谈】如何把写好的插件卖到AssetStore
- 分布式文件系统—FastDFS
- C++ no debugging symbol found
- Hibernate——搭建
- opencv 解决vs2013 opencv3.0 0xC000007b运行错误问题
- 米老师经典语录————再造生命力
- 一道关于多态题目的解析
- 图解Linux命令之--enable命令