Linux 知识(2)
系列文章目录
Linux内核学习
Linux 知识(1)
Linux 知识(2)
文章目录
- 系列文章目录
- 内核帮助文档生成
- 内核启动参数
- 1、引导参数
- 2、__setup 宏
- Linux 目录介绍
- 1、boot 目录
- 2、/lib/modules
- 示例
- 3、sys 目录
- 设备模型
- 1、概述
- 2、uevent
- 3、字符设备注册相关接口
- kthread
- ioremap
- debugfs
内核帮助文档生成
内核 Doc 文档指南
sudo apt-get update
apt install python3-sphinx# 检查 Sphinx 依赖项
./scripts/sphinx-pre-instal
sudo apt-get install graphviz
sudo apt-get install imagemagick
# 安装GraphViz和ImageMagick包处理图片输出make htmldocs
# 生成的文档放在 Documentation/output 文件夹中
内核启动参数
Linux内核启动配置项
Linux操作系统内核启动参数详解
uboot如何向内核传递参数
内核启动参数详解配合代码分析
U-Boot与kernel之间的参数传递机制完全解析
uboot如何向内核传递参数
# 设置U-Boot环境变量
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/rootfs ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
# 保存环境变量
saveenv
# 启动内核
bootm 0x10000
1、引导参数
- root:指定根文件系统的位置。例如,root=/dev/sda1表示根文件系统在第一个 SATA 硬盘的第一个分区上。
- ro/rw:分别表示以只读或读写方式挂载根文件系统。通常在启动过程中先以只读方式挂载,在文件系统检查完成后切换为读写方式。
- init:设置内核执行的初始化进程名,如果该项没有设置,内核会按顺序尝试 /init , /sbin/init,/etc/init,/bin/init, /bin/sh,如果所有的都没找到,内核会抛出 kernel panic:的错误。
- console:指定控制台设备。例如,console=ttyS0,115200表示使用串口 0 作为控制台,波特率为 115200。
2、__setup 宏
Linux内核__setup 宏的作用及分析
static int __init root_dev_setup(char *line)
{strscpy(saved_root_name, line, sizeof(saved_root_name));return 1;
}__setup("root=", root_dev_setup);
底软驱动 | Linux内核中ioremap映射的透彻理解
为什么Linux操作寄存器要ioremap
mmap与ioremap
linux设备驱动程序——bus
设备驱动模型–bus_type详解
bus_register
bus_register: 工作就是完成 bus_type_private 的初始化。创建注册的这条总线需要的目录文件。
在这条总线目录下创建 /device /driver 目录
初始化这条总线上的设备链表:struct klist klist_devices;
初始化这条总线上的驱动链表:struct klist klist_drivers;
每次有一个新的设备注册到上面,都会去匹配右边的驱动,看是否能匹配上 。如果匹配成功,则将设备结构的 is_registerd 域置为 0。然后将设备添加到驱动的 p->klist_devices 域 。同理,每注册一个驱动,都会去匹配左边的设备,如果匹配成功,将则设备加到驱动的 p->klist_devices 域 ,再将设备的 is_registerd 置为 0 。
ls /sys/bus/
acpi container event_source mdev nvmem platform serio virtio
clockevents cpu hid memory pci pnp usb vmbus
clocksource dax i2c nd pci_express scsi vdpa workqueue
class_register:
class_register(&pcibus_class);
将会在 /sys/class 目录下产生一个 “pci_bus” 的目录。
ls /sys/class/
bdi devlink iommu misc phy ptp scsi_generic uio vtconsole
block drm ipvtap nd power_supply rtc scsi_host vc
bsg hidraw macvtap net ppp scsi_device thermal vfio
cuse input mem pci_bus pps scsi_disk tty virtio-ports
linux驱动开发-深入探索linux内核设备驱动模型
Linux 目录介绍
1、boot 目录
Linux中 /boot 目录介绍
Linux中/boot目录
- config-4.14.0-kali3-amd64
当前 Linux 系统的 kernel 配置文件,可以使用下面指令查看。
cat /boot/config-4.14.0-kali3-amd64 | mor
- initrd.img-4.14.0-kali3-amd64(cpio格式)
initrd 全名 initial ram disk,启动系统所需加载的虚拟磁盘。它是 vmlinuz 的映像文件。 - vmlinuz-4.14.0-kali3-amd64
linux 的正式内核。 - System.map-4.14.0-kali3-amd64
内核符号映射表,顾名思义就是将内核中的符号(也就是内核中的函数)和它的地址能联系起来的一个列表。 - grub
引导加载程序相关的文件。
2、/lib/modules
/lib/modules
目录通常包含了 Linux 内核的模块文件。这些模块可以在需要时动态加载到内核中。自动加载驱动程序通常意味着当某些事件发生时,系统会自动加载相应的内核模块。
在Linux系统中,可以使用 modprobe
命令来自动加载模块。modprobe 基于内核配置中的依赖关系和模块参数来决定是否自动加载模块。
如果你需要在系统启动时自动加载特定的内核模块,你可以编辑 /etc/modules-load.d目录下的配置文件或者在 /etc/modules 文件中直接添加模块名。
示例
例如,如果你想自动加载名为 mymodule 的模块,你可以执行以下步骤之一:
- 创建一个新的配置文件 /etc/modules-load.d/mymodule.conf 并在其中写入模块名:
mymodule
- 编辑 /etc/modules 文件,在文件末尾添加模块名:
mymodule
在系统下次启动时,这些模块将会自动通过 modprobe 或 insmod 加载。
系统启动后自动加载 modules
另外,你也可以通过 udev
规则来管理设备节点,在特定事件(如插入某个设备)发生时自动执行 modprobe
命令。
3、sys 目录
linux驱动开发-深入探索linux内核设备驱动模型
目录 | 意义 |
---|---|
block | 块设备 |
bus | 系统中的总线 |
class | 设备类型,比如输入设备 |
dev | 系统中已注册的设备节点的视图,有两个子目录 char 和 block 。 |
devices | 系统中所有设备拓扑结构视图 |
fireware | 固件 |
fs | 文件系统 |
kernel | 内核配置选项和状态信息 |
module | 模块 |
power | 系统的电源管理数据 |
设备模型
1、概述
linux设备驱动程序——bus
设备驱动模型–bus_type详解
bus_register
linux驱动开发-深入探索linux内核设备驱动模型
bus_register: 工作就是完成 bus_type_private 的初始化。创建注册的这条总线需要的目录文件。
在这条总线目录下创建 /device /driver 目录
初始化这条总线上的设备链表:struct klist klist_devices;
初始化这条总线上的驱动链表:struct klist klist_drivers;
每次有一个新的设备注册到上面,都会去匹配右边的驱动,看是否能匹配上 。如果匹配成功,则将设备结构的 is_registerd 域置为 0。然后将设备添加到驱动的 p->klist_devices 域 。同理,每注册一个驱动,都会去匹配左边的设备,如果匹配成功,将则设备加到驱动的 p->klist_devices 域 ,再将设备的 is_registerd 置为 0 。
ls /sys/bus/
acpi container event_source mdev nvmem platform serio virtio
clockevents cpu hid memory pci pnp usb vmbus
clocksource dax i2c nd pci_express scsi vdpa workqueue
class_register:
class_register(&pcibus_class);
将会在 /sys/class 目录下产生一个 “pci_bus” 的目录。
ls /sys/class/
bdi devlink iommu misc phy ptp scsi_generic uio vtconsole
block drm ipvtap nd power_supply rtc scsi_host vc
bsg hidraw macvtap net ppp scsi_device thermal vfio
cuse input mem pci_bus pps scsi_disk tty virtio-ports
2、uevent
Linux设备模型(四) - uevent应用:内核发送uevent,用户空间接收uevent
详解linux内核的uevent机制
linux驱动开发-深入探索linux内核设备驱动模型
3、字符设备注册相关接口
一文搞懂内核中cdev的各种注册函数
《Linux驱动:register_chrdev、alloc_chrdev_region、register_chrdev_region》
Linux 系统中主设备号和次设备号的范围如下:
1. 主设备号:主设备号占据 12 个位,范围从0到4095。主设备号用于区分设备的类别或类型,告诉操作系统应该使用哪个驱动程序来处理这类设备。例如,字符设备、块设备等都有固定的主设备号
2. 次设备号:次设备号占据20个位,范围从0到1048575。次设备号用于区分同一类设备中的不同实例或子设备。例如,同一个SCSI硬盘的不同分区会有相同的主设备号但不同的次设备号。
kthread
linux内核kthread_create
再探 kernel_threads-1
再探Kernel Threads -2
ioremap
底软驱动 | Linux内核中ioremap映射的透彻理解
为什么Linux操作寄存器要ioremap
mmap与ioremap
在将I/O内存资源的物理地址映射成核心虚地址后,理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。为了保证驱动程序的跨平台的可移植性,我们应该使用Linux中特定的函数来访问I/O内存资源,而不应该通过指向核心虚地址的指针来访问。如在x86平台上,读写I/O的函数如下所示:
#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))#define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))// =========================================
// 一个调试示例代码
static inline __attribute__((__gnu_inline__)) __attribute__((__unused__))
__attribute__((no_instrument_function)) unsigned int
readl(const volatile void *addr)
{unsigned int ret;asm volatile("mov""l"" %1,%0": "=r"(ret): "m"(*(volatile unsigned int *)addr): "memory");return ret;
}
debugfs
debugfs文件系统
Linux内核之debugfs_create_dir与debugfs_create_file实例与调用栈流程(三十二)
debugfs 文件系统一般挂在 /sys/kernel/debug
目录上。
debugfs的相关操作函数:
- 创建和销毁文件
debugfs_create_file(): 用于在 debugfs 中创建一个新的文件。
debugfs_create_u32(), debugfs_create_u64(): 用于创建一个包含 32 位或 64 位整数的文件。
debugfs_create_bool(): 用于创建一个布尔类型的文件。 - 创建目录
debugfs_create_dir(): 用于在 debugfs 中创建一个新的目录。 - 读写文件内容
simple_read_from_buffer(), simple_write_to_buffer(): 用于读取和写入文件的内容。 - 注册和注销
debugfs_create_regset32(), debugfs_create_regset64(): 用于创建一个寄存器集合,允许用户空间读写内核寄存器的值。
debugfs_remove(): 用于从 debugfs 中删除文件或目录。 - 其他
debugfs_create_blob(): 用于创建一个二进制数据的文件。
debugfs_create_symlink(): 用于创建一个符号链接。
☆
Ctrl + Alt + V