Sholck

不积跬步,无以至千里.不积小流,无以成江海

0%

x86下系统调用

背景

经过之前的汇编实践-解析命令行参数学习,发现在进行系统调用时,不管是调用syscall(), 还是libc封装的系统调用,最终都是通过int $0x80(32位 i386)或者syscall(x86_64)进入内核态从而调用对应的底层实现,x86_32是通过一个0x80的软中断实现的,而x86_64是通过汇编指令syscall实现。

疑问:

  1. 0x80的软中断策略如何实现系统调用
  2. syscall汇编指令具体做了什么?(64bit)
阅读全文 »

linux-assembly入门学习

学习目的

  1. 应用:kernel底层有着大量的汇编语言,包括机器启动强相关的header.s 和原子性函数实现等内嵌汇编
  2. 需求:应用coredump,内核转储,内存分析都需要了解汇编才能更深入分析dump现场
  3. 提升:根据汇编分析寄存器变化,对堆栈分配,寻址方式等机器运行方式,了解架构机器真正运作的方式
阅读全文 »

cmpxchg kernel api

cmpxchg是一个内核x86经常用到的api,功能是用来比较和交换的,带着以下疑问研究此api

  1. 为什么需要设计成原子性的
  2. 如何实现原子性
阅读全文 »

模块接口分析

模块编译

在代码编译前宏展开时,需要进行条件编译,这需要gcc指定参数,而指定什么参数由Makefile来控制.
trace.c在编译时gcc中的参数中会带有 -D__KERNEL__, -DMODULE, -D__KBUILD_MODNAME=kmod_trace, 可以参考linux-likely学习,这用在之后的宏展开。

阅读全文 »

crash库的开源提交

背景

在学习crash分析kernel 5.17.0+ dump时,遇到一些问题

阅读全文 »

linux-通知链学习

实现

通知链notifier的实现为:A模块实现维护一个具备高优先级顺序的单向节点链表notifier,每一个节点有对应的函数指针和优先级。内核中的其他子系统模块B,C 如果对A中的事件感兴趣,那么需要向notifier上挂在一个子节点,并在此节点上注册回调。当事件发生时,遍历notifier上所有节点,并通过回调通知模块B,C,然后根据事件进行对应的处理。

阅读全文 »

gdb调试linux内核&驱动模块

在linux学习过程中,需要针对内核和动态模块进行调试,最常用的方法是gdb,但是linux gdb文档中描述的不够详细,在学习调试过程中碰到了不少坑并做如下记录。

阅读全文 »

linux-likely学习

背景

在日常的工作和学习中,经常发现likely和unlikely的使用,在通知链节点注册时,有如下函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static int notifier_chain_register(struct notifier_block **nl,                                                                                                                                                      
struct notifier_block *n)
{
while ((*nl) != NULL) {
if (unlikely((*nl) == n)) {
WARN(1, "notifier callback %ps already registered",
n->notifier_call);
return -EEXIST;
}
if (n->priority > (*nl)->priority)
break;
nl = &((*nl)->next);
}
n->next = *nl;
rcu_assign_pointer(*nl, n);
return 0;
}

这里通过遍历节点和插入节点地址对比,防止程序运行时重复插入通知链节点。当然,重复插入这种情况下是非常少见的,因此编译器针对此进行了性能优化。

阅读全文 »