第一天字符驱动

第一个驱动

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 内核模块的。以下是对每一部分的解释:
  1. 变量定义

    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
  2. 构建目标

    all:
        make -C $(KERN_DIR) M=`pwd` modules 
    
    • all 目标:调用内核构建系统来编译模块。
    • make -C $(KERN_DIR) M=pwd modules:切换到内核构建目录,并在当前目录下构建模块。
  3. 清理目标

    clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
    
    • clean 目标:清理构建生成的文件。
    • make -C $(KERN_DIR) M=pwd modules clean:调用内核构建系统来清理模块生成的文件。
    • rm -rf modules.order:删除 modules.order 文件。
  4. 模块对象文件

    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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值