您的位置:首页 > 其它

ldd3学习之二:构造和运行模块

2017-03-29 10:48 218 查看
1.设置测试系统:
①设置一套内核源码树,比如/usr/src/linux-2.6.x,参考http://www.kernel.org/
eg:uname -r  --->2.6.32-27-generic
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.27.tar.gz
②直接用发行版的内核源码包,比如/lib/modules/$(shell uname -r),包含内核目标链接文件。
2.hello world模块

#include <linux/init.h>

#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)

{

    printk(KERN_ALERT"hello,world.\n");

    return 0;

}

static void hello_exit(void)

{

    printk(KERN_ALERT"Goodbye,cruel world.\n");

}

module_init(hello_init);

module_exit(hello_exit);

 Makefile文件

#如果已定义KERNELRELEASE,则说明是从内核构造系统调用的

#因此可利用其内建语句

ifneq ($(KERNELRELEASE),)

    obj-m := hello.o

#否则,是直接从命令行调用的,这是要调用内核构造系统

else

    KERNELDIR ?= /lib/modules/$(shell uname -r)/build

    PWD := $(shell pwd)

default:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

make编译,然后用insmod安装,用dmesg可以在终端看到输出信息,或者输出到某个日志文件里比如/var/log/messages.
linux的模块并不复杂,真正的困难在于理解设备并最大化其性能
3.内核模块的特点。
①模块仅仅被链接到内核,因此能调用的函数仅仅是由内核导出的那些函数,不存在任何可链接的函数库。
②内核函数不支持浮点运算。
③Unix使用两个级别,内核态和用户态。当处理器有多个级别时,使用最高级别和最低级别。
④每当应用程序执行系统调用或者被硬件中断挂起时,Unix从用户空间切换到内核空间。
⑤系统调用的代码运行在进程上下文,可以访问进程所有数据。而处理硬件中断的内核代码和进程是异步的,与任一个特定进程无关。
⑥一个驱动程序要执行两类任务:模块中的某些函数作为系统调用的一部分执行(实现用户API),而其他函数则负责中断处理。
⑦内核具有非常小的栈,可能只有4K大小页。我们自己的函数必须和整个内核空间调用链一同共享这个栈,如果需要大的结构,应该在调用时动态分配。
4.内核中的并发
linux2.6中内核代码已经是可抢占的。
①编写内核代码时,时刻铭记:同一时刻,可能会有许多事情正在发生。
②linux内核代码(包括驱动代码)必须是可重入的。
5.当前进程current
内核代码可通过访问全局项current来获得当前进程,current在中定义,是一个指向struct task_struct的指针。
在2.6中,current不再是一个全局变量,指向task_stuct结构的指针隐藏在内核栈中,current是一个可以获得这个结构的宏,包含即可引用。

#include <linux/sched.h>

printk(KERN_INFO"The process is \"%s\" (pid %i)\n",current->comm,current->pid);

6.编译和装载
对hello world模块,Makefile只要一行就可以了:obj-m := hello.o
如果要构造的模块名module.ko由两个源文件生成,file1.c,file2.c,则:

obj-m := module.o

module.o-objs := file1.o file2.o

装载:sudo insmod hello.ko
查看:lsmod
卸载:sudo rmmod hello
7.内核符号表
公共内核符号表中包含了所有的全局内核项(函数和变量)的地址,模块被装载后,它所导出的任何符号都会变成内核符号表的一部分。
模块层叠技术在复杂项目中非常有用,modprobe是处理层叠技术的一个使用工具,功能类似insmod.通过层叠技术,可以将模块划分为多个层,通过简化每个层,可缩短开发时间。
8.hello world模块代码分析

#include <linux/init.h>    //指定初始化和清除函数

#include <linux/module.h>  //包含可装载模块需要的大量符号和函数的定义

//所有模块代码中都包含这两行

MODULE_LICENSE("Dual BSD/GPL");//制定许可证,一般用"GPL"或者"Dual BSD/GPL"

static int __init hello_init(void)     //__init表示初始化函数执行完之后就释放内存

{

    printk(KERN_ALERT"hello,world.\n");

    return 0;

}

static void __exit hello_exit(void) //__exit表示在卸载是执行,编译器把这类函数放在特殊的ELF段中

{

    printk(KERN_ALERT"Goodbye,cruel world.\n");

}

module_init(hello_init);

module_exit(hello_exit);//

9.初始化过程中的错误处理

如果注册设施时遇到任何错误,首先判断模块是否可以继续初始化,通常,在某个注册失败后可以通过降低功能来继续运行。因此,只要可能,模块应该继续向前并尽可能提供功能。

若发生的特定类型错误之后无法继续装载模块,则出错之前的任何注册工作都要撤销(未撤销,内核可能不稳定)。

一个典型的错误处理模板

int __init my_init_function(void)

{

    int err;

    err = register_this(ptr1,"skull");

    if (err)

        goto fail_this;

    err = register_that(ptr2,"skull");

    if (err)

        goto fail_that;

    err = register_those(ptr3,"skull");

    if (err)

        goto fail_those

    return 0; // success

fail_those: unregister_that(ptr2,"skull");

fail_that:unreister_this(ptr1,"skull");

fail_this: return err;

}

清除函数撤销所有设施

void __exit my_cleanup_function(void)

{

    unregister_those(ptr3,"skull");

    unregister_that(ptr2,"skull");

    unregister_this(ptr1"skull");

    return;

}

一个典型的清除函数模板

struct something * item1;

struct something * item2;

void my_cleanup(void)

{

    if (item1)

        release_thing(item1);

    if (item2)

        release_thing2(item2);

    if (stuff_ok)

        unregister_stuff();

    return;

}

int __init my_init(void)

{

    int err = -ENOMEM;

    item1 = allocate_thing(arg);

    item2 = allocate_thing2(arg2);

    if (!item1||!item2)

        goto fail;

    err = register_stuff(item1,item2);

    if (!err)

        stuff_ok = 1;

    else goto fail;

    retrun 0;

fail:

    my_cleanup();

    return err;

}

这种方式的初始化能够很好地扩展到对大量设施的支持。

模块装载竞争:在用来支持某个设施的所有内部初始化完成之前,不要注册任何设施。

10.模块参数

内核允许对驱动程序指定参数,而这些参数可在装载驱动程序模块时改变。

static char *whom = "world";

static int howmany = 10;

module_param(howmany,int ,S_IRUGO);

module_param(whom,charp,S_IRUGO);

module_param(name,type,num,perm);

name--数组名字

type--数组元素类型

num--数组个数

perm--访问许可值
insmod hello.ko whom=yuyunbo howmany=5

模块装载器会拒绝接受超过数组大小的值

本章新符号总结(函数,变量,宏等)insmod,modprobe,rmmod,lsmod,dmesg用来装载模块到正运行的内核和移除模块的用户空间工具
#include module_init(init_function);
module_exit(cleanup_function);
用于指定模块的初始化和清除函数的宏。
__init,__initdata,__exit,__exitdata
仅用于模块初始化或清除阶段的函数(__init和_exit)和数据(__initdta和__exitdata)标记。
#include
最重要的头文件之一,该文件包含驱动程序使用的大部分内核API的定义,包括睡眠函数以及各种变量声明。
struct task_struct *current;
当前进程
current->pid
current->com
当前进程的进程ID和命令名。
obj-m
由内核构造系统使用的makefile的符号,用来确定当前目录中应构造那些模块
/sys/module是sysfs目录层次结构中包含当前已装载模块信息的目录
/proc/modules是早期的用法,在单个文件中包含模块名称,每个模块内存总量以及引用计数等。
vermagic.o内核源代码目录中的一个目标文件,描述了模块的构造环境。
#include
必须的头文件,它必须包含在模块源代码中。
#include 包含说构造内核版本信息的头文件。
LINUX_VERSION_CODE整数宏,用在处理版本以来的预处理条件语句中。
EXPORT_SYMBOL (symbol);导出单个符号到内核的宏
EXPORT_SYMBOL_GPL(symbol);仅用于GPL许可证下的模块
MODULE_AUTHOR(author);
MODULE_DESCRIPTION(desctiption);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
在目标文件中添加关于模块的文档信息。
module_init(init_function);
module_exit(exit_function);
声明模块初始化和清除函数的宏
#include
module_param(variable,type,perm);
用来创建函数模块的宏,在装载模块时调整参数
#include
int printk(const char * fmt,...);
函数printf的内核代码


<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>

阅读(959) | 评论(0) | 转发(3) |

0
上一篇:ldd3学习之一:设备驱动简介

下一篇:修改ubuntu10.10的对话框图标居右

相关热门文章
QEMU源码分析系列(四)...

Python 包管理工具解惑

c++防止隐藏的拷贝构造...

APP开发报价单,如何计算APP报...

APP开发流程,你知道多少...

linux 常见服务端口

xmanager 2.0 for linux配置

【ROOTFS搭建】busybox的httpd...

openwrt中luci学习笔记

什么是shell

linux dhcp peizhi roc

关于Unix文件的软链接

求教这个命令什么意思,我是新...

sed -e "/grep/d" 是什么意思...

谁能够帮我解决LINUX 2.6 10...

给主人留下些什么吧!~~

评论热议
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: