linux字符设备驱动框架
myxx_driver.c
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/uaccess.h>
static int myxx_open (struct inode * inode, struct file * file)
{
printk(" device open\n");
return 0;
}
static int myxx_release (struct inode * inode, struct file * file){
printk(" device release\n");
return 0;
}
ssize_t myxx_read (struct inode * inode, struct file * file){
printk(" device read\n");
return 0;
}
ssize_t myxx_write (struct inode * inode, struct file * file){
printk(" device write\n");
return 0;
}
static struct file_operations myxx_fop = {
.owner = THIS_MODULE,
.open = chr_open,
.release = chr_release,
.read = chr_read,
.write = chr_write,
};
static struct cdev *myxx_cdev;
static struct class *myxx_class;
static dev_t device;
/* 驱动模块的入口函数 */
static int myxx_init(void){
if (device){
/* 静态申请设备号 */
register_chrdev_region(device,1,"myxx_dev");
}else{
/* 动态申请设备号 */
alloc_chrdev_region(&device,0, 1,"myxx_dev");
}
/* 申请空间 */
my_chr_cdev = cdev_alloc();
/* 注册字符设备驱动 */
cdev_init(myxx_cdev,&myxx_fop);
cdev_add(myxx_cdev, device, 1);
/* 创建设备节点 */
chr_class = class_create(THIS_MODULE, "myxx_dev");
class_device_create(myxx_class, NULL, device, NULL,"myxx_dev");
return 0;
}
/* 驱动模块的退出函数 */
static void myxx_exit(void){
/* 删除设备节点 */
class_device_destroy(myxx_class, device);
class_destroy(myxx_class);
/* 注销字符设备驱动 */
cdev_del(myxx_cdev);
/* 释放空间 */
cdev_put(myxx_cdev);
/* 释放设备号和相应的设备名 */
unregister_chrdev_region(device, 1);
}
/* 这个宏将 myxx_init 函数修饰为模块的入口函数 */
module_init(myxx_init);
/* 这个宏将 myxx_exit 函数修饰为模块的退出函数 */
module_exit(myxx_exit);
/* 遵循GPL协议 */
MODULE_LICENSE("GPL");
makefile
#内核源码树路径
KERN_DIR = ~/work/kernel
#目标文件
obj-m += myxx_driver.o
all:
make -C $(KERN_DIR) M=pwd
modules
clean:
make -C $(KERN_DIR) M=pwd
modules clean
test_myxx.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int buf;
int main(int argc, char** argv)
{
int fd;
if((fd = open("/dev/myxx_dev",O_RDWR))<0){
printf("open device failed\n");
return -1;
}
/* 将数据写到驱动程序,再读出来验证 */
int i = 10;
write(fd,&i,sizeof(i));
read(fd,&buf,sizeof(buf));
printf("read the data is:%d\n",buf);
sleep(1);
close(fd);
return 0;
}
编译驱动
make ARCH=arm CROSSFILE=arm-linux-gcc
生成 myxx.ko
编译应用程序
arm-linux-gcc main.c -o test_myxx
将ko文件和应用程序复制到嵌入式机器上
加载驱动
insmod myxx.ko
执行应用程序
./test_myxx
其他指令
查看内核中已插入的模块
lsmod
卸载模块
rmmod xxx
查看模块的描述信息
modinfo xxx.ko