进程和程序
学号265,原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
1.task_struct结构体
linux内核中对进程信息的管理存放在task_stuct结构体中,结构体中主要有标识符、状态、优先级、进程相关的指针等关键信息,下面对这些主要内容进行分析。
1.1 进程状态:
state就是描述进程状态的成员,其可能的取值和对应的状态在sched.h中有具体的定义,总的来说其值<0代表不在运行状态,=0代表正在运行,>0代表停止状态。
1.2 进程标识符:
1.3 进程相关指针:
1.4 优先级:
prio保存动态优先级,static_prio保存静态优先级,normal_prio的值取决于静态优先级和调度策略,rt_priority保存实时优先级。
1.5 调度策略
调度策略在内核中主要有五种,其可能取值的定义在include/uapi/linux/sched.h中。
2.do_fork和进程创建
fork,vfork,clone三者的实现函数都指向了do_fork,区别只是传入的参数不同,do_fork函数声明如下:
其函数体主要执行流程如下:
调用copy_process为子进程复制出一份进程信息;
调用wake_up_new_task将子进程加入调度器,为之分配cpu;
在copy_process中创建新的task_struct指针,然后复制当前进程的task_struct,再对其中的一些值进行修改。
3.gdb跟踪fork
首先更新Linuxkernel文件夹中的menu,然后将test_fork.c覆盖test.c,再修改Makefile文件,使得虚拟机运行后先stop,以便使用gdb进行调试。
然后打开新的终端,打开gdb对qemu中的系统程序进行调试,在sys_clone,do_fork,copy_process三个函数设置断点:
然后输入c进行程序跟踪,跟踪过程如下:
可以看到fork确实如上面分析的流程,首先调用系统函数sys_clone,然后sys_clone调用do_fork,do_fork接着调用copy_process。
4.编译和链接
4.1 编译的过程:
编译需要经过预处理、编译、汇编、链接四个过程:
预处理:主要处理宏定义、条件编译指令、头文件包含指令,预处理完成的基本上是对源程序的替代工作;
编译:将代码转换为汇编代码;
汇编:将汇编代码转为机器码,在Linux上一般为ELF目标文件;
链接:将生成的目标文件与系统库文件进行链接,最终生成可执行文件。
4.2 链接:
链接分为静态链接、载入时动态链接、运行时动态链接:
静态链接:在编译链接阶段就将需要库函数和目标文件合并生成可执行文件,该方法生成的可执行文件实行速度快,但可能会导致可执行文件过大;
载入时动态链接:在编译前已知需要调用到哪些库,编译时在目标文件中保留所需的链接信息,程序执行时通过链接信息加载对应代码到程序执行空间中;
运行时动态链接:编译前不知道会调用哪些库,当程序运行时需要调用到某些库时,使用特定API来加载所需库。
5.进程调度的时机
进程调度的时机一般为:
进程执行结束;
当前进程的时间片用完;
发生中断、异常;
因此schedule()函数的调用时机一般也应该在这些情况被调用,schedule()函数的功能是选择下一个进程进执行。
Last updated