进程和程序

学号265,原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/

1.task_struct结构体

linux内核中对进程信息的管理存放在task_stuct结构体中,结构体中主要有标识符、状态、优先级、进程相关的指针等关键信息,下面对这些主要内容进行分析。

1.1 进程状态:

volatile long state;

state就是描述进程状态的成员,其可能的取值和对应的状态在sched.h中有具体的定义,总的来说其值<0代表不在运行状态,=0代表正在运行,>0代表停止状态。

1.2 进程标识符:

pid_t pid;  //进程标识符
pid_t tgid;  //线程组标识符

1.3 进程相关指针:

struct task_struct __rcu *real_parent; //父进程指针
struct task_struct __rcu *parent; //父进程指针

struct list_head children;	//子进程链表指针
struct list_head sibling;	//指向父进程的子进程链表的指针
struct task_struct *group_leader;	//指向进程组的首进程

1.4 优先级:

int prio, static_prio, normal_prio;
unsigned int rt_priority;

prio保存动态优先级,static_prio保存静态优先级,normal_prio的值取决于静态优先级和调度策略,rt_priority保存实时优先级。

1.5 调度策略

unsigned int policy;

调度策略在内核中主要有五种,其可能取值的定义在include/uapi/linux/sched.h中。

2.do_fork和进程创建

fork,vfork,clone三者的实现函数都指向了do_fork,区别只是传入的参数不同,do_fork函数声明如下:

long do_fork(unsigned long clone_flags,
	      unsigned long stack_start,
	      unsigned long stack_size,
	      int __user *parent_tidptr,
	      int __user *child_tidptr)

其函数体主要执行流程如下:

  • 调用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