linux 内核及其相关内容

1·内核模块

 Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:

(1)直接编译进Linux内核,随同Linux启动时加载;

(2)编译成一个可加载和删除的模块,使用insmod加载(modprobe和insmod命类似,但依赖于相关的配置文件),rmmod删除。这种方式控制了内核的大小,而模块  一旦被插入内核,它就和内核其他部分一样。

下面我们给出一个内核模块的例子:

  #include <linux/module.h> //所有模块都需要的头文件

  #include <linux/init.h>

  // init&exit相关宏MODULE_LICENSE("GPL");

  static int __init hello_init (void)

  {

    printk("Hello module init\n");

     return 0;

  }

  static void __exit hello_exit (void)

  {

    printk("Hello module exit\n");

    return 0;

  }

  module_init(hello_init);

  module_exit(hello_exit);

分析上述程序,发现一个Linux内核模块需包含模块初始化和模块卸载函数,前者在insmod的时候运行,后者在rmmod的时候运行。初始化与卸载函数必须在宏module_init和module_exit使用前定义,否则会出现编译错误。

程序中的MODULE_LICENSE("GPL")用于声明模块的许可证。如果要把上述程序编译为一个运行时加载和删除的模块,则编译命令为:gcc –D__KERNEL__ -DMODULE –DLINUX –I /usr/local/src/linux2.4/include -c –o hello.o hello.c

   由此可见,Linux内核模块的编译需要给gcc指示–D__KERNEL__ -DMODULE –DLINUX参数。-I选项跟着Linux内核源代码中Include目录的路径。

  下列命令将可加载hello模块:

  insmod ./hello.o

  下列命令完成相反过程:

  rmmod hello 如果要将其直接编译入Linux内核,则需要将源代码文件拷贝入Linux内核源代码的相应路径里,并修改Makefile。

内核编程的一些基本知识:

  内存在Linux内核模式下,我们不能使用用户态的malloc()和free()函数申请和释放内存。进行内核编程时,最常用的内存申请和释放函数为在include/linux/kernel.h文件中声明的kmalloc()和kfree(),其原型为:

  void *kmalloc(unsigned int len, int priority);

  void kfree(void *__ptr);

  kmalloc的priority参数通常设置为GFP_KERNEL,如果在中断服务程序里申请内存则要用GFP_ATOMIC参数,因为用GFP_KERNEL

参数可能会引起睡眠,不能用于非进程上下文中(在中断中是不允许睡眠的)。由于内核态和用户态使用不同的内存定义,所以二者之间不能直接访问对方的内存。而应该使用Linux中的用户和内核态内存交互函数(这些函数在include/asm/uaccess.h中被声明):

  unsigned long copy_from_user(void *to, const void *from, unsigned long n);

  unsigned long copy_to_user (void * to, void * from, unsigned long len);

copy_from_user、copy_to_user函数返回不能被复制的字节数,因此,如果完全复制成功,返回值为0。include/asm/uaccess.h中定义的put_user和get_user用于内核空间和用户空间的单值交互(如char、int、long)。

输出

在内核编程中,我们不能使用用户态C库函数中的printf()函数输出信息,而只能使用printk()。但是,内核中printk()函数的设计目的并不是为了和用户交流,它实际上是内核的一种日志机制,用来记录下日志信息或者给出警告提示。每个printk都会有个优先级,内核一共有8个优先级,它们都有对应的宏定义。如果未指定优先级,内核会选择默认的优先级DEFAULT_MESSAGE_LOGLEVEL。如果优先级数字比int console_loglevel变量小的话,消息就会打印到控制台上。如果syslogd和klogd守护进程在运行的话,则不管是否向控制台输出,消息都会被追加进/var/log/messages文件。klogd 只处理内核消息,syslogd 处理其他系统消息,比如应用程序。

模块参数

  内核下,include/linux/module.h中定义的宏MODULE_PARM(var,type) 用于向模块传递命令参数。var为接受参数变量,type为采取如下格式的字符串[min[-max]]{b,h,i,l,s}。min及max用于表示当参数为数组类型时,允许输入的数组元素的个数范围;b:byte;h:short;i:int;l:long;s:string。

在装载内核模块时,用户可以向模块传递一些参数:insmod modname var=value 如果用户未指定参数,var将使用模块内定义的缺省值。

时间: 2024-10-17 22:15:05

linux 内核及其相关内容的相关文章

深入解析Linux内核及其相关架构的依赖关系

Linux kernel 成功的两个原因: 灵活的架构设计使得大量的志愿开发者能够很容易加入到开发过程中:每个子系统(尤其是那些需要改进的)都具备良好的可扩展性.正是这两个原因使得Linux kernel可以不断进化和改进. 一.Linux内核在整个计算机系统中的位置 分层结构的原则: the dependencies between subsystems are from the top down: layers pictured near the top depend on lower la

linux内核编译相关

参考:http://www.arm.linux.org.uk/docs/kerncomp.php 一. 内核编译1) linux 2.4make clean/make mrpropermake depmake zImagemake modules //编译模块2) linux 2.6make clean/make mrpropermake // 编译内核同时编译了模块3) 模块安装上述步骤完成后,模块分布在各个内核目录下,通过下面命令安装到具体目录下:make modules_install I

Linux内核阅读相关

一.likely()与unlikely()函数的意义 http://blog.chinaunix.net/uid-27665626-id-3506567.html

ARMv8 Linux内核异常处理过程分析

NOTE:为了方便大家阅读,制作了PDF版文档.下载请猛戳这里 老样子,为了赚点积分下载其它人的文件,下载以上资料须要资源分2分. 假设没有积分请留言全部文档,留下邮箱就可以. 看了Linaro提供的开源ARMv8 Linux内核源代码,发现ARMv8异常处理与ARMv7及之前的架构有所不同,简单分析. LinaroARMv8工程:http://www.linaro.org/engineering/engineering-projects/armv8 1.1 Linux内核异常处理相关文件 Li

linux内核参数注释与优化

转自:http://yangrong.blog.51cto.com/6945369/1321594 目录 1.linux内核参数注释 2.两种修改内核参数方法 3.内核优化参数生产配置 参数解释由网络上收集整理,常用优化参数对比了网上多个实际应用进行表格化整理,使查看更直观. 学习linux也有不少时间了,每次优化linux内核参数时,都是在网上拷贝而使用,甚至别人没有列出来的参数就不管了,难道我就不需要了吗? 参考文章: linux内核TCP相关参数解释 http://os.chinaunix

Linux内核分析期末总结 20135115臧文君

Linux内核分析期末总结 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.计算机是如何工作的 1.参考链接:http://www.cnblogs.com/CatherineZang/p/5218570.html 2.编译语句:gcc -S -o main.s main.c -m32 3.“三个法宝” (1)存储程序计算机工作模型,计算机系统最最基础性的逻辑结构:

linux内核并发基本概念

在讨论linux内核并发之前,我们先来分享一个情景. 字符数组array是一个内核全局数组,执行函数ArrayWrite_A的线程称为线程A,执行函数ArrayWrite_B的线程称为线程B.线程A和线程B均可访问全局数组array,ArrayWrite_A函数实现的功能是将数组成员依次从0递增赋值到9,ArrayWrite_B函数实现的功能是将数组成员全部赋值为1. 假设此时线程A运行到函数ArrayWrite_A,我们期望的结果是函数ArrayWrite_A执行完后,数组array中的成员应

(笔记)Linux内核中内存相关的操作函数

linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) 内核空间申请指定大小的内存区域,返回内核空间虚拟地址.在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间.有关buddy和slab,请参见<linux内核之内存管理.doc> gfp_t flags 的选项

Linux系统学习之路和常用命令及其他系统相关内容

Linux系统学习之路 目录 Linux系统学习之路[第一篇]:Linux目录和基础知识 Linux系统学习之路[第二篇]:文件操作,文件查看,find查找 Linux系统学习之路[第三篇]:grep,vim,压缩功能详解 Linux系统学习之路[第四篇]:mount,rpm,yum,yum组讲解 Linux系统学习之路[第五篇]:用户和用户组管理 Linux系统学习之路[第六篇]:权限管理 Linux系统学习之路[第七篇]:磁盘和文件管理 Linux系统学习之路[第八篇]:LVM逻辑卷和RAI