第一个驱动
1.驱动
#include <linux/module.h>
int Hello_init(void){
return 0;
}
void Hello_exit(void){
}
module_init(Hello_init);//不想写这句可以直接把Hello_init换成init_module
module_exit(Hello_exit);//一开始写的是Hello_init这是错误的,module_exit()里面应该是一个退出函数
MODULE_LICENSE("GPL");//要符合gpl要求
ARCH = x86
CROSS_COMPILE =
KVERSION = $(shell uname -r)
KERN_DIR = /lib/modules/$(KVERSION)/build
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += Hello_drive.o
这个 Makefile
是用于构建一个 Linux 内核模块的。以下是对每一部分的解释:
-
变量定义:
ARCH = x86 CROSS_COMPILE = KVERSION = $(shell uname -r) KERN_DIR = /lib/modules/$(KVERSION)/build
ARCH = x86
:指定目标架构为 x86。CROSS_COMPILE
:交叉编译前缀,当前为空,表示不使用交叉编译。KVERSION = $(shell uname -r)
:使用uname -r
命令获取当前内核版本。KERN_DIR = /lib/modules/$(KVERSION)/build
:内核构建目录,通常是/lib/modules/当前内核版本/build
。
-
构建目标:
all: make -C $(KERN_DIR) M=`pwd` modules
all
目标:调用内核构建系统来编译模块。make -C $(KERN_DIR) M=
pwdmodules
:切换到内核构建目录,并在当前目录下构建模块。
-
清理目标:
clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order
clean
目标:清理构建生成的文件。make -C $(KERN_DIR) M=
pwdmodules clean
:调用内核构建系统来清理模块生成的文件。rm -rf modules.order
:删除modules.order
文件。
-
模块对象文件:
obj-m += hello_drv.o
obj-m += hello_drv.o
:指定要构建的模块对象文件hello_drv.o
。
这个 Makefile
的主要功能是通过调用内核构建系统来编译和清理一个名为 hello_drv
的内核模块。
2.装载驱动
sudo insmod Hello_drive.o
3.查看驱动
lsmod
cat /proc/devices //可以看到驱动主设备号
4.卸载驱动
sudo rmmod Hello_drive
5.查看内核信息(printk打印信息)
dmesg
6.source insigh 实用设置
source insight使用—tab补齐提示,大括号对齐
7.最后代码
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#define MIN(a, b) (a > b ? b : a)
/*确定主设备号*/
static int major = 0;
/*
**定义一个驱动存储
**存储数据供函数读取存储
*/
static char kernelChar[1024];
/*完善各个函数*/
static int HelloDriveOpen (struct inode *node, struct file *fie){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
static ssize_t HelloDriveRead(struct file *file, char __user *buf, size_t size, loff_t *offset){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
copy_to_user(buf, kernelChar, MIN(1024, size));
return MIN(1024, size);
}
static ssize_t HelloDriveWrite (struct file *file, const char __user *buf, size_t size, loff_t *offset){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
copy_from_user(kernelChar, buf, MIN(1024, size));
return MIN(1024, size);
}
static int HelloDriveRelease (struct inode *nide, struct file *file){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
/*确定驱动的file_operations*/
static const struct file_operations HelloDriveOps = {
.owner = THIS_MODULE,
.open = HelloDriveOpen,
.read = HelloDriveRead,
.write = HelloDriveWrite,
.release = HelloDriveRelease,
};
/*
**入口函数
**注册驱动
*/
static struct class *Hello_class;
static int __init HelloDrive_init(void){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
major = register_chrdev(0, "HelloDrive", &HelloDriveOps);//0自动分配主设备号,HelloDrive自己填
Hello_class = class_create(THIS_MODULE, "HelloDrive");
//long err = PTR_ERR(Hello_class);
if(IS_ERR(Hello_class)){
unregister_chrdev(major, "HelloDrive");
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
return -1;
}
device_create(Hello_class, NULL, MKDEV(major, 0), NULL, "HelloDrive");
return 0;
}
/*
**出口函数
**卸载驱动
*/
static void __exit HelloDrive_exit(void){
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
device_destroy(Hello_class, MKDEV(major, 0));
class_destroy(Hello_class);
unregister_chrdev(major, "HelloDrive");
}
module_init(HelloDrive_init);
module_exit(HelloDrive_exit);
MODULE_LICENSE("GPL");
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
if(argc < 2){
printf("usage: %s -w <string>\n", argv[0]);
printf(" %s -r\n", argv[0]);
return -1;
}
int fd;
int len;
char buf[1024];
fd = open("/dev/HelloDrive", O_RDWR);
if(fd == -1){
printf("can't open /dev/HelloDrive\n");
perror("open");
return -1;
}
if(!strcmp(argv[1], "-w") && argc == 3){
len = strlen(argv[2])+1;
len = len > 1024 ? 1024 : len;
write(fd, argv[2], len);
}
else{
read(fd, buf, 1024);
buf[1023] = '\0';
printf("read: %s\n", buf);
}
close(fd);
}