Linux内核 - Charles-Charmless/Charles-Charmless.github.io GitHub Wiki

Picture

概述

内核设计理念:机制和策略分离

参考文献

linux操作系统原理与应用

现代操作系统

linux内核的设计与实现

深入理解linux内核

linux设备驱动程序

内核编译

  1. 获取源码:链接

  2. 配置内核

    make config:遍历选择所要编译的内核特性
    make allyesconfig:配置所有可编译的内核特性
    make allnoconfig:并不是所有的都不编译,而是能选的都回答为NO、只有必须的都选择为yes。
    make menuconfig:这种就是打开一个文件窗口选择菜单,这个命令需要打开的窗口大于80字符的宽度,打开后就可以在里面选择要编译的项了
    下面两个是可以用鼠标点选择的、比较方便哦:
    make kconfig(KDE桌面环境下,并且安装了qt开发环境)
    make gconfig(Gnome桌面环境,并且安装gtk开发环境)
    menuconfig:使用这个命令的话、如果是新安装的系统就要安装gcc和ncurses-devel这两个包才可以打开、然后再里面选择就可以了、通这个方法也是用得比较多的:

    zimage和uimage区别:

    [!info] uImage和zImage的区别
    ​转自: https:// blog.
    https://zhuanlan.zhihu.com/p/46403145

内存寻址

asfaf

进程管理

内存管理

中断

系统调用

内核同步

文件系统

设备驱动

make config:遍历选择所要编译的内核特性
make allyesconfig:配置所有可编译的内核特性
make allnoconfig:并不是所有的都不编译,而是能选的都回答为NO、只有必须的都选择为yes。
make menuconfig:这种就是打开一个文件窗口选择菜单,这个命令需要打开的窗口大于80字符的宽度,打开后就可以在里面选择要编译的项了
下面两个是可以用鼠标点选择的、比较方便哦:
make kconfig(KDE桌面环境下,并且安装了qt开发环境)
make gconfig(Gnome桌面环境,并且安装gtk开发环境)
menuconfig:使用这个命令的话、如果是新安装的系统就要安装gcc和ncurses-devel这两个包才可以打开、然后再里面选择就可以了、通这个方法也是用得比较多的:

内核函数

函数名 描述 头文件
xxx_init() 模块的具体入口函数
xxx_exit() 模块的具体出口函数
module_init() 系统注册入口函数 linux/module.h
module_exit() 系统注销入口函数 linux/module.h
__init (编译修饰符)模块执行完成后回收内存空间
__exit
MODULE_LICENSE
printk() 内核输出函数(dmesg查看) linux/kernel.h
[[Wiki/Arm linux修炼之路/Linux内核/内核函数/Untitled Database/Untitled Untitled]]

Linux内核编程 modprobe depmod insmod rmmod modinfo

加载进内核的module /proc/modules

in kernel 2.4 内核开始函数

init_module()
#必须返回0,返回其他值表示内核没有初始化内核失败不会加载内核

内核结束函数

cleanup_module()

in later:

module_init()
module_exit()
MODULE_LICENSE("GPL");

hello world!程序

__init #标记初始化函数只能初始化一次不能在初始化之后再次调用
__exit #标记退出函数用于释放模块所分配的资源取消注册设备解除设备之间的连接等操作__initdata which works similarly to __init but for init variables rather than functions.
pr_debug  输出调试消息它是一个轻量级的调试宏

`dev_dbg`输出调试消息但它通常用于设备驱动程序中 还会输出一些与设备相关的信息如设备名和设备地址。
`dbg`、`dev_err`、`dev_info` 用于输出不同级别的调试信息如错误信息信息消息等)。

实验

链表实验

链表定义

\#include <linux/list.h>

struct list_head {
	struct list_head *next, *prev;
};

hello world!程序 hello.c

Makefile

输出

总结

Makefile反思

module_exit()

库文件问题

hello.c

\#include <linux/kernel.h>
\#include <linux/module.h>

static  int __init hello_init(void){
        printk("hello world!");
        return 0;
}


static void __exit hello_exit(void){
        printk("good bye, world");
}


module_init(hello_init);
module_exit(hello_exit);


MODULE_LICENSE("GPL");

Makefile

obj-m=hello.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/linux

all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

输出

[  +0.016418] hello world!
[  +0.004977] good bye, world

总结

Makefile反思

  • makefile文件其实主要的内容就是 make modules,其他都是指定库文件所在位置,
# Use make M=dir to specify directory of external module to build
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD take precedence
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifdef M
  ifeq ("$(origin M)", "command line")
    KBUILD_EXTMOD := $(M)
  endif
endif

module_exit()

\#include <linux/kernel.h>

## definition
\#define module_init(x) __initcall(x)
\#define module_exit(x) __exitcall(x)

typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);

\#define __initcall(fn)								\
	static initcall_t __initcall_#\#fn __init_call = fn
\#define __exitcall(fn)								\
	static exitcall_t __exitcall_#\#fn __exit_call = fn
  • 如果设置出口函数的返回值为int型变量,编译报错,显示返回值不匹配
/home/cd/Project/Kernel_Program/hello.c: In functionhello_exit’:
/home/cd/Project/Kernel_Program/hello.c:12:1: warning: no return statement in function returning non-void [-Wreturn-type]
   12 | }
      | ^
In file included from /home/cd/Project/Kernel_Program/hello.c:2:
/home/cd/Project/Kernel_Program/hello.c: In function__exittest’:
/home/cd/Project/Kernel_Program/hello.c:16:13: error: returningint (*)(void)’ from a function with incompatible return typeexitcall_t’ {akavoid (*)(void)’} [-Werror=incompatible-pointer-types]
   16 | module_exit(hello_exit);
      |             ^~~~~~~~~~
./include/linux/module.h:138:11: note: in definition of macromodule_exit138 |  { return exitfn; }     \
      |           ^~~~~~
/home/cd/Project/Kernel_Program/hello.c: At top level:
./include/linux/module.h:139:7: warning: ‘cleanup_modulealias between functions of incompatible typesvoid(void)’ andint(void)’ [-Wattribute-alias=]
  139 |  void cleanup_module(void) __copy(exitfn) __attribute__((alias(\#exitfn)));
      |       ^~~~~~~~~~~~~~
/home/cd/Project/Kernel_Program/hello.c:16:1: note: in expansion of macromodule_exit16 | module_exit(hello_exit);
      | ^~~~~~~~~~~
/home/cd/Project/Kernel_Program/hello.c:10:19: note: aliased declaration here
   10 | static int __exit hello_exit(void){
      |                   ^~~~~~~~~~
cc1: some warnings being treated as errors

库文件问题

  • 系统没有安装库文件,安装上即可 “ sudo pacman -S linux-headers”
⚠️ **GitHub.com Fallback** ⚠️