我的第一个字符设备驱动程序-First_drv

时间:2023-01-03 22:54:51
/*驱动程序*/
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<asm/uaccess.h>
#include<asm/irq.h>
#include<asm/io.h>
#include<linux/device.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
static struct class *firstdrv_class;
static struct device *firstdrv_class_dev;
static int first_drv_open(struct inode *inode,struct file *file)
{
printk("first_drv_open\n");
return 0;
}

static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t count,loff_t * ppos)
{
printk("first_drv_write\n");
return 0;
}
/*顶一个file_operation结构*/
static struct file_operations first_drv_fops = {
.owner=THIS_MODULE,/*这是一个宏,推向编译模块时自动创建的_this_module变量*/
.open=first_drv_open,
.write=first_drv_write,
};

int major;
/*驱动入口函数*/
int first_drv_init(void)
{
major=register_chrdev(0,"first_drv",&first_drv_fops);/*卸载驱动程序,告诉内核*/
firstdrv_class=class_create(THIS_MODULE,"firstdrv");
if(IS_ERR(firstdrv_class))
{
return PTR_ERR(firstdrv_class);
}
firstdrv_class_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"xyz");
if(unlikely(IS_ERR(firstdrv_class_dev)))
return PTR_ERR(firstdrv_class_dev);

return 0;
}

void first_drv_exit(void)
{
unregister_chrdev(121,"first_drv");

device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);

}
/*声明入口函数*/
module_init(first_drv_init);
module_exit(first_drv_exit);

#Mkefile文件
KERN_DIR=/work/system/linux-2.6.32.2



all:

make -C $(KERN_DIR) M=`pwd` modules



clean:

make -C $(KERN_DIR) m=`pwd` modules clean



obj-m+=First_drv.o


/*测试代码*/
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main(int argc,char **argv)
{
int fd;
int val=1;
fd=open("/dev/xyz",O_RDWR);
if(fd<0)
printf("can't open!\n");
write(fd,&val,4);
return 0;
}

期间碰到的问题:
1、FATAL: modpost: GPL-incompatible module First_drv.ko uses GPL-only symbol 'device_create'
解决方法:在头文件之后加上,加在其他位置无效


MODULE_LICENSE("GPL");
2、 implicit declaration of function 'class_device_create'
解决方法:本次试验所用内核为linux-2.6.32.2,已不支持此函数,改为device_create 头文件为:Device.h
3、./test: line 2: : not found
./test: line 2: 4: not found
./test: line 2:  not found
./test: line 2: ELF!$: not found
./test: line 1: syntax error: word unexpected (expecting ")")
解决方法:用错编译链,一定要用arm-linux-gcc   而不是gcc    即:arm-linux-gcc -o test test.c
现翻译下代码:
首先,实现设备的open.write,read等程序,接着为这些方法找宿主,实现一个file_operation结构,此结构相当于一个一级容器,里面实现了open等方法,接着为这个容器生成驱动模块,也就是register_chrdev函数,第一个参数为主设备号,如果为零,则内核为其分配主设备号,即主设备号大于0,第二个参数为设备名,可以自行定义,第三个参数就是上面那个实现了open等操作方法的容器。接着创建类,通过类建立设备(不大懂,现在只是照抄),最后声明驱动入口函数,为了完整驱动卸载函数也声明下啦 完毕!感谢韦东山老师!