驱动day1 概念+内核模块编程+内核消息打印函数printk函数的使用

1 驱动相关概念

驱动day1 概念+内核模块编程+内核消息打印函数printk函数的使用_第1张图片

2 内核模块编程

驱动day1 概念+内核模块编程+内核消息打印函数printk函数的使用_第2张图片

内核模块编写实例代码+注释

#include 
#include 

//入口函数,安装内核模块时执行
static int __init mycdev_init(void)
{
    //static 修饰当前函数只能在本文件使用
    //int 函数的返回值类型,如果函数规定返回值但是没有加返回值,编译会报错
    //mycdev_init函数名,可以自己起名字
    //void表示函数无参数,当没有参数时void一定要加,不然报错
    //__init的作用是用来告诉编译器当前代码保存在.init.text段中
    //#define __init        __section(".init.text")  
    //linux内核也会有自己的链接脚本  vmlinux.lds,这个链接脚本里规定了不同的内容在
    //内存中的什么位置
    return 0;
}
//出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{
    //#define __exit        __section(".exit.text")
    //__exit指定出口函数保存在.exit.text段中

}
//用于声明入口函数
module_init(mycdev_init);
//用于声明出口函数
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

内核模块编译(外部编译Makefile)

#保存UBUNTU内核源码路径
KERNELDIR := /lib/modules/$(shell uname -r)/build
#KERBELDIR保存开发板内核源码路径
#KERNELDIR := /home/ubuntu/linux-5.10.61/
#PWD保存当前内核模块的路径
PWD := $(shell pwd)
all:
#make modules是模块化编译命令
#make -C $(KERNLEDIR) 执行make之前先切换到KERNELDIR对应的路径
#M=$(PWD)表示进行模块化编译的路径是PWD保存的路径
    make -C $(KERNELDIR) M=$(PWD) modules
clean:
#编译清除
    make -C $(KERNELDIR) M=$(PWD) clean
#将obj-m保存的文件单独链接为内核模块
obj-m :=  demo.o

通用版本的Makefile

modname ?= demo
arch ?= arm
ifeq ($(arch),arm)  #通过命令行传过来的架构决定怎么编译
#KERBELDIR保存开发板内核源码路径
KERNELDIR := /home/ubuntu/linux-5.10.61/
else
#保存UBUNTU内核源码路径
KERNELDIR := /lib/modules/$(shell uname -r)/build
endif

#PWD保存当前内核模块的路径
PWD := $(shell pwd)
all:
#make modules是模块化编译命令
#make -C $(KERNLEDIR) 执行make之前先切换到KERNELDIR对应的路径
#M=$(PWD)表示进行模块化编译的路径是PWD保存的路径
    make -C $(KERNELDIR) M=$(PWD) modules
clean:
#编译清除
    make -C $(KERNELDIR) M=$(PWD) clean
#将obj-m保存的文件单独链接为内核模块
obj-m :=  $(modname).o

3 内核消息打印函数printk函数的使用

驱动day1 概念+内核模块编程+内核消息打印函数printk函数的使用_第3张图片

代码示例

#include 
#include 

// 入口函数,安装内核模块时执行
static int __init mycdev_init(void)
{
    // static 修饰当前函数只能在本文件使用
    // int 函数的返回值类型,如果函数规定返回值但是没有加返回值,编译会报错
    // mycdev_init函数名,可以自己起名字
    // void表示函数无参数,当没有参数时void一定要加,不然报错
    //__init的作用是用来告诉编译器当前代码保存在.init.text段中
    // #define __init       __section(".init.text")
    // linux内核也会有自己的链接脚本  vmlinux.lds,这个链接脚本里规定了不同的内容在
    // 内存中的什么位置
    printk(KERN_ERR "hello world\n");
    int a=10;
    printk(KERN_ERR "%d\n",a);
    return 0;
}
// 出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{
    // #define __exit       __section(".exit.text")
    //__exit指定出口函数保存在.exit.text段中
}
// 用于声明入口函数
module_init(mycdev_init);
// 用于声明出口函数
module_exit(mycdev_exit);
// 声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

你可能感兴趣的:(驱动开发,java,前端,linux)