驱动程序-字符驱动

来源:互联网 发布:数据帧的长度计算公式 编辑:程序博客网 时间: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!表示读取成功。



0 0
原创粉丝点击