Linux内核驱动模块学习

Linux内核编程(一) —— 内核模块加载 如果我们需要修改内核,该怎么做呢?我们需要将代码以模块的方式添加到内核中去运行。本文就介绍最简单的模块编写和加载方法。 我们还是从最简单的hello模块介绍。 step 1:创建一个目录hello step 2:在hello中编写hello.c如下: #include #include #include MODULE_LICENSE("Dual BSD/GP 阅读详情

.ko文件格式

.ko文件在是elf(Excutable and Link Format)格式,是一种可重定位的目标文件。在编译驱动模块时,我们在makefile中用obj-m=xxx.o来指定生成内核驱动模块文件,即.ko文件。
在这里插入图片描述

模块加载过程

首先insmod会通过文件系统将ko读到用户空间的一块内存中, 然后执行系统调用sys_init_module()解析模组,这时,内核在vmalloc区分配与ko文件大小相同的内存来暂存ko文件, 暂存好之后解析ko文件,将文件中的各个section分配到init 段和core 段,在modules区为init段和core段分配内存, 并把对应的section copy到modules区最终的运行地址,经过relocate函数地址等操作后,就可以执行ko的init操作了, 这样一个ko的加载流程就结束了。 同时,init段会被释放掉,仅留下core段来运行。

内核模块加载过程

输入指令rmmod,最终在系统内核中需要调用sys_delete_module进行实现。具体过程如下:先从用户空间传入需要卸载的模块名称,根据名称找到要卸载的模块指针, 确保我们要卸载的模块没有被其他模块依赖,然后找到模块本身的exit函数实现卸载。

内核导出符号

在Linux内核中,符号是指模块中使用EVPORT_SYMBOL声明的函数和变量。当模块被装入内核后,它所到处的符号都会被记录在内核符号表中,在使用insmod加载模块后,模块就被连接到内核,因此可以访问内核的公用符号。内核导出符号被称为模块层叠技术,当其他模块想要从这个模块使用某些资源时,就可以考虑使用导出符号为其提供服务,如此一来,我们可以将模块分为多个层,通过简化每一层来实现复杂的项目。modprobe是一个处理层叠模块的工具,它的功能相当于多次使用insmod, 除了装入指定模块外还同时装入指定模块所依赖的其他模块。导出符号使用下面的宏

EXPORT_SYMBOL(NAME)
EXPORT_SYMBOL_GPL(NAME)

__init、__initdata等宏定义

__init用来修饰函数,__initdata用于修饰变量。带有__init的修饰符,表示将该函数放到可执行文件的__init节区中,该节区中的内容只能用于模块的初始化阶段,初始化阶段执行完毕之后,这部分的内容就会被释放掉,所以我个人认为这是一种很好的节约系统内存的方式。__exit,表示将该函数放在可执行文件的__exit节区, 当执行完模块卸载阶段之后,就会自动释放该区域的空间。__exit用于修饰函数,__exitdata用于修饰变量。 宏定义module_exit用于告诉内核,当卸载模块时,需要调用哪个函数。
__init、__initdata宏定义(位于内核源码/linux/init.h)

#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)

module_init宏定义

#define module_init(x) __initcall(x);

module_exit宏定义

#define module_exit(x) __exitcall(x);

__exit、__exitdata宏定义

#define __exit __section(.exit.text) __exitused __cold notrace
#define __exitdata __section(.exit.data)
Linux kernel __init和core_initcall分析 Linux kernel __init分析 下面内容都是以kernel 4.14版本分析;通常linux驱动定义为如下: static int __init gpiolib_dev_init(void) { ... 阅读详情

相关推荐

static_init、全局_init重复使用,初始化问题

全局_init(初始化)例子及解析 /* ** 验证全局变量重复赋值时,是否只初始化一次,类似静态局部变量 */ #include<stdio.h>   int g_a; void func(void);   int main(void) { func(); printf("g_a = %d.\n", g_a); func(); printf("g_a = ...

schwable的博客 1262

内核模块初始化函数static int __init init_func() 和退出函数 static void _exit exit_func() _init 和_exit 的理解

模块中初始化函数有的前面有个_init有什么作用。 在内核代码iclude/linux/init.h  中有这样的定义 #define __init  __section(.init.text) __cold notrace #define __initdata __section(.init.data) #define __initconst __section(.init.rodata

hyfcomeon的专栏 5805

分享一下x64位驱动源码

最近一直在学习x64位的内核编程 之前对内核一无所知的我 因为某些原因 不得不学习一下内核编程 现在分享一下我学习的时后源码 如果有用到的自己下载 一个是64位的全局禁止进程运行 一个是64位的进程保护 都是用的回调函数 不得不说 内核实在太强大 另外附上e的加载驱动源码

内核模块初始化函数static int __init init_func() 和退出函数 static void _exit exit_func() _init 和_exit 的理解

模块中初始化函数有的前面有个_init有什么作用。 在内核代码iclude/linux/init.h 中有这样的定义 #define __init __section(.init.text) __cold notrace #define __initdata __section(.init.data) #define __initconst __section(.init.rodata) #...

chillinght的博客 1305

零基础Linux内核驱动学习(一):编写最简单Linux内核模块HelloWorld,编译通过

文章目录准备工作什么是内核模块编写hello.c编写Makefile相关指令测试结果模块加载模块卸载 准备工作 在进行以下操作前,首先我准备了一台电脑,并且安装了虚拟机,系统是Ubuntu16.04。如果是开发板,那么需要安装交叉编译器,但是目前我只在虚拟机的Ubuntu16.04系统里完成驱动模块的加载和卸载,实现了一个最最简单的内核模块,并且通过这个最简单的驱动学习最基本的概念。 什么是内核模块 模块是可以根据实际需要可以动态加载和卸载到内核中的代码。它们扩展了内核的功能,而无需重启系统,就可以进行模

weixin_46373574的博客 655

4.17 嵌入式学习Linux驱动驱动编译成内核模块

基础知识:

TheAnswerisy的博客 187

嵌入式学习Linux驱动 内核模块加载命令

TheAnswerisy的博客 112

Linux内核驱动学习(一)编写最简单Linux内核模块HelloWorld

文章目录准备工作什么是内核模块编写 hello.c模块编译相关指令测试结果模块加载模块卸载 准备工作 在进行以下操作前,首先我准备了一台电脑,并且安装了虚拟机,系统是Ubuntu16.04。如果是开发板,那么需要安装交叉编译器,但是目前我只在虚拟机的Ubuntu16.04系统里完成驱动模块的加载和卸载,实现了一个最最简单的驱动模块,并且通过这个最简单的驱动学习最基本的概念。 什么是内核模块 模块...

一名热爱技术的工程师的博客。分享技术干货,记录美好生活。永远相信美好的事情即将发生。 8750

Linux驱动学习Linux内核模块

Linux内核中,导出符号表实质上就是导出函数表,也就是让该文件中的函数能被其它文件引用。

GS8FG的博客 266

linux内核驱动学习--构造和运行模块

linux设备驱动–构造和运行模块 目录linux设备驱动–构造和运行模块Hello World模块模块链接到内核用户空间和内核空间当前进程其他一些细节装载和卸载模块版本依赖内核符号表预备知识 Hello World模块 下面这段代码是完整的 "hello world"模块 #include<linux/init.h> #include<linux/module.h> static int hello_init(void) { printk(KERN_ALERT"Hello

baitang886的博客 1544

Linux内核学习:动手写一个字符驱动模块

目录 1 字符驱动设备 2 编写驱动并测试 2.1 实验目的及操作步骤 2.2简单的字节驱动模块 2.3 编译字节驱动模块 2.4插入到QEMU上的Linux内核中 2.5 写用户层测试代码测试插入的内核模块 1 字符驱动设备 字符设备是以字节为单位的I/O传输,这种字符流的传输率通常比较低,常见的字符设备有鼠标、键盘、触摸屏等。 2 编写驱动并测试 可以先不去管代码具体...

Henry_Fordham——一个姓雪的程序员小哥哥 990

Linux内核驱动学习---编写最简单Linux内核模块HelloWorld

以下内容来源于 https://blog.csdn.net/lihaoweiV/article/details/6602261 https://blog.csdn.net/sh21_/article/details/60878812 https://blog.csdn.net/u010632165/article/details/86541941 https://blog.csdn.net/FallingU/article/details/76166194 什么是内核模块 模块是可以根据实际需要可以动态加

weixin_46048542的博客 1726

LINUX驱动学习(1) —— 内核模块驱动框架编写

LINUX驱动学习(1) —— 内核模块驱动框架编写 前言 编写目的:从零入门;熟悉内核驱动开发方式;编译一个内核驱动框架。也是记录自己的学习过程,有哪里理解不到位的地方,还请大神指正。 编译环境:ubutun 20.04 Linux版本:linux-3.0.35 命令介绍: make menuconfig 配置内核命令 ;需要安装 ncurses 才可以使用。 ARCH=arm 指定ARM体系结构 CROSS_COMPILE=arm-none-linux-gnueabi- 指定交叉

308

Linux中__init、__exit 、__devinit等初始化宏

转自http://blog.csdn.net/wealoong/article/details/7734087 linux下 container_of()宏的简要解析 ARRAY_SIZE 宏还是比较有意思的,其实是个c 的编程技巧,这个技巧很有用哦!可以在include/linux/kernel.h 中找到它的定义: #define ARRAY_SIZE(x) (siz

qingkongyeyue的博客 1万+

Linux 模块的初始化过程

内核模块gnu.linkonce.this_module section简介

小立仔 2359

module_init函数的功能,为什么module_init可以传入函数参数,这个函数为什么是static int __init 内核模块编译

这与内核模块开发有关 内核模块开发 Linux 内核管理着计算机的所有资源,为上层应用程序提供统一的编程接口( 系统调用 ),屏蔽底层设备的差异。由于不同用户物理设备以及对内核功能需求的差异性,需要一种类似插件的运行机制——编写插件实现所需功能,然后嵌入到内核中,与内核形成一个整体。 Linux内核模块 便是这样的插件。作为 Linux 内核的扩展手段,可以在运行时动态加载和卸载。那么,一个内核模块是怎么编写的呢?与普通程序编写有什么区别呢? 程序开发经常以 hello world 程序入门,因为这是最简单

nb_zsy的博客 949

static int __init goodix_ts_init(void) TP驱动加载函数——浅析

static int __init goodix_ts_init(void) //驱动加载函数 { s32 ret;   GTP_DEBUG_FUNC(); //出错提示, GTP_DEBUG_FUNC_ON=0时正确 GTP_INFO("GTP driver installing...."); //原样输出 /* 函数解析.note 创建工作队列,返回一个指针*/ goodix_w...

qq_41831724的博客 1047

实验三、进程管理

1、创建并运行内核线程 kthread.c: #include <linux/kthread.h> #include <linux/module.h> #include <linux/delay.h> ​ MODULE_LICENSE("GPL"); ​ #define BUF_SIZE 20 ​ static struct task_struct *myThread = NULL; ​ static int print(void *data) { whil

qq_46744173的博客 4195
上一篇: ubuntu搭载网络文件系统与linux开发板共享资源
下一篇: 算法
Junmengmeng7
博客等级 码龄6年 2粉丝 23原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值