Linux内核期末复习
1、P22-25
2、P36、P165
call指令的作用:
将当前 CS:EIP
的值压入栈顶,CS:EIP
指向别调用的函数的入口地址。
ret指令的作用:
从栈顶弹出原来保存在这里的 CS:EIP
的值,放入 CS:EIP
中。
进程切换时用什么函数
schedule()
_switch_to_函数如何理解 怎么实现
简易实现:
// 定义进程控制块(PCB)结构体
struct pcb {
// 进程ID等信息
int pid;
// 寄存器状态等上下文信息
// 这里假设只保存了通用寄存器eax和ebx
int eax;
int ebx;
};
// 全局变量,当前运行的进程
struct pcb *current_process;
// 简化版的_switch_to_函数
void _switch_to_(struct pcb *next_process) {
// 保存当前进程的寄存器状态
current_process->eax = eax;
current_process->ebx = ebx;
// 加载下一个进程的寄存器状态
eax = next_process->eax;
ebx = next_process->ebx;
// 将当前进程更新为下一个进程
current_process = next_process;
}
3、gcc、gdb命令
gdb
堆栈汇编典型示例:
反汇编指令:
objdump [options] <file>
4、内嵌汇编(10号系统调用)
#include <stdio.h>
int main() {
long result;
long syscall_number = 10; // 10号系统调用的编号
long arg1 = 1; // 参数1
long arg2 = 2; // 参数2
asm volatile (
"mov %1, %%rax\n\t" // 将系统调用号存入寄存器rax
"mov %2, %%rdi\n\t" // 将参数1存入寄存器rdi
"mov %3, %%rsi\n\t" // 将参数2存入寄存器rsi
"syscall\n\t" // 进行系统调用
"mov %%rax, %0\n\t" // 将返回值存入变量result
: "=r" (result) // 输出操作数:返回值存入result
: "r" (syscall_number), "r" (arg1), "r" (arg2) // 输入操作数:系统调用号、参数1、参数2
: "%rax", "%rdi", "%rsi" // 受影响的寄存器
);
printf("Result: %ld\n", result);
return 0;
}
5、fork()系统调用
0、1、2号进程
fork()内核机制
fork()通过clone()进入内核态,clone()调用do_fork(),创建一个新的进程,并复制当前进程的所有上下文信息(包括程序代码、数据、堆栈、文件描述符等)到新进程中,将子进程设为就绪状态,放入调度器,当在适当的时候被调度时,内核会给子进程分配唯一的PID,更新子进程的资源使用情况,接下来,内核会更新子进程的页表,使得子进程拥有自己的虚拟地址空间,并与父进程共享物理内存页(使用写时复制机制),子进程从fork()位置开始执行。
写时复制:
-
在
fork()
调用时,父进程的所有内存页都被标记为"只读"。 -
当父进程或子进程试图修改一个共享的内存页时,操作系统内核会接收到一个页面错误(Page Fault)异常。
-
在页面错误处理程序中,内核会为子进程分配一个新的物理内存页,并将父进程的内容复制到新的内存页中。
-
然后,内核更新子进程的页表,将修改后的内存页映射到子进程的虚拟地址空间中。
为什么fork()子进程返回到ret_from_fork后
为了保证子进程在正确的位置开始执行,可以正常返回用户态,而不是继续执行父进程的代码。
execve函数
int execve(const char *filename, char *const argv[], char *const envp[]);
其中,argv[]
是一个以NULL结尾的字符串数组,用于传递命令行参数给新程序。每个字符串元素都是一个命令行参数,第一个元素通常是可执行文件的名称。
envp[]
是一个以NULL结尾的字符串数组,用于传递环境变量给新程序。每个字符串元素都是一个环境变量,形如"key=value"的格式。
#include <unistd.h>
int main() {
char *const argv[] = { "program", "arg1", "arg2", NULL };
char *const envp[] = { "VAR1=value1", "VAR2=value2", NULL };
execve("/path/to/program", argv, envp);
// execve函数执行成功后,下面的代码不会被执行到,
// 因为进程已经被替换为新程序。
// 如果execve函数执行失败,会返回-1,并根据errno设置相应的错误码。
return 0;
}
6、ELF
怎么映射到内存:
使用execve系统调用
符号表、重定位
7、
8、
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器