文章目录
- 链表
- 循环双向链表
- 哈希链表
- 其他链表
- 汇编
- 内联汇编
- 扩展内联汇编
- makefile
链表
链表是linux内核中关键的数据结构。在第二次课中,重点介绍了循环双向链表和哈希链表。这两种链表都在传统的双向链表的基础之上进行了针对效率的优化。(ps:这部分可以通过看插入链表、删除链表中节点的具体实现来加深理解)
循环双向链表
linux内核中的链表节点中只包含指针,数据被存在节点之外的空间,通过偏移来获取数据。(ps:在结构体之外再套一个结构体)
哈希链表
哈希链表是双向非循环链表,head和node的结构不同,head里有1个指针,node里面有2个指针,并且两个指针一个是一级指针(next),一个是二级指针(prev)。
这种设计的优点在于:
- 节省空间:head设计只有1个指针,空间使用减少一半
- 提高效率:判断是否为head节点,只需要查看pprev指针
其他链表
降序优先排序的双向链表: 二重索引
无锁单链表
汇编
Linux大部分代码是c语言编写,但依旧有少量代码用汇编语言编写,原因是:
- 提高效率
- 与硬件交互
- 与cpu交互
用c语言写的代码可以通过3种方法看其汇编代码:
gcc -S [file_name].c # method 1
gcc -c [file_name].c # method 2
objdump -d [file_name].o
gdb + disassemble # method 3
汇编指令语法见:汇编语言–x86汇编指令集大全
内联汇编
内联汇编只可以对全局变量进行操作。
#include <stdio.h> // asm.c
int a, b, c;
int main() {
a = 1, b = 2;
asm volatile (
"movl a, %eax\n\t" // 将a放入eax寄存器
"addl b, %eax\n\t" // 将b的值加到eax寄存器中
"movl %eax, c\n\t" // 将eax寄存器的值加到c中
);
printf("c:%d\n",c);
}
扩展内联汇编
扩展内联汇编可以对局部变量进行操作,其基本格式为:
asm volatile (
"assembly code"
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
)
#include <stdio.h> //asm_2.c
int main() {
int a = 1, b = 2, c = 0;
asm volatile (
"movl %0, %%eax\n\t"
"movl %1, %%ebx\n\t"
"addl %%eax, %%ebx\n\t"
"movl %%ebx, %2\n\t"
:"+g"(a), "+g"(b) // input operand
:"+g"(c) // output operand
);
printf("c:%d\n",c);
printf("a:%d\n",a);
printf("b:%d\n",b);
return 0;
}
clobbered registers会影响最终结果:
#include<stdio.h>
int main() {
int data1 = 10;
int result = 20;
asm (
"movl %1, %%eax\n\t"
"addl %%eax, %0"
:"=r"(result)
:"r"(data1), "0"(result)
// :"%eax" 此行不注释result=30,注释后result=20
);
printf("the result is:%d\n",result);
return 0;
}
makefile
在软件开发中,Make 是一种构建自动化工具,它通过读取指定如何派生目标程序的称为 Makefile 的文件,从源代码自动构建可执行程序和库。 尽管集成开发环境和特定于语言的编译器功能也可用于管理构建过程,但 Make 仍被广泛使用,尤其是在 Unix 和类 Unix 操作系统中。
Make 可用于管理任何项目,除了构建程序之外,只要其他文件发生变化,某些文件需要从其他文件自动更新。
makefile包括4种语句:
- 宏
- 规则
- 变量定义
- 其他元素
一个简单的makefile例子:项目包括2个c++文件:processing.cpp
和gui.cpp
文件,那么makefile可以写成:
gcc -c processing.cpp -o processing.o # 单独编译processing.cpp
gcc -c gui.cpp -o gui.o # 单独编译gui.cpp
gcc processing.o gui.o -o my_program # 联合编译processing.o和gui.o
可以发现编译一个2个文件的项目,已经涉及到了3行命令行来进行编译。可以预想的是,当项目规模扩大时,编译的指令也会变得异常复杂,并且一旦更新其中一个文件,需要重新编译的时候,所涉及到需要重新运行的编译指令所面临的情况也是千奇百怪。因此,我们需要makefile来对编译的指令进行一个封装,简化用户编译时的工作量。
to be continued