2023-2024-1 20232825《Linux内核原理与分析》第七周作业

一、task_struct数据结构

         在Linux内核中,通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在linux-3.18.6/include/linux/sched.h文件中。struct task_struct的数据结构非常庞大,struct task_struct的state是进程状态,stack是堆栈等,大概有400多行代码,如下代码摘录了struct task_struct数据结构的部分关键定义,并在每句后由相应的注释解释:

struct task_struct { 
 volatile long state;        //进程状态/* -1 unrunnable, 0 runnable, >0 stopped */
 void *stack;                // 指定进程内核堆栈
 pid_t pid;                  //进程标识符
 unsigned int rt_priority;   //实时优先级
 unsigned int policy;        //调度策略
 struct files_struct *files; //系统打开文件
 ...
}

二、分析 fork 函数对应的内核处理过程 sys_clone

         do_fork函数原型位于linux-3.18.6/kernel/fork.c。
        fork函数可以创建进程,创建一个进程是复制当前进程的信息,被复制的进程成为父进程,被创建的新进程成为子进程。父进程和子进程的绝大部分信息是完全一样的,但是有些信息不能一样,比如pid的值和内核堆栈。还有将新进程链接到各种链表中,要保存进程执行到哪个位置,有一个thread数据结构记录ip和sp等信息也不能一样。所以,父进程创建子进程时,会有一个地方复制父进程的进程描述符task_struct结构体变量,并有很多地方来修改复制的进程描述符task_struct结构体变量。

三、使用 gdb 跟踪分析一个 fork 系统调用内核处理函数 sys_clone

1、在MenuOS中添加fork函数,函数如下:

#include <unistd.h> 
int Fork(int argc, char *argv[]) 
{
int pid;
/* fork another process */
pid = fork();                                 
if (pid<0) 
{ 
/* error occurred */
fprintf(stderr,"Fork Failed!");
exit(-1);
} 
else if (pid==0)                              
{
/*   child process  */
printf("This is Child Process!\n");
} 
else 
{   
/*  parent process   */
printf("This is Parent Process!\n");          
/* parent will wait for the child to complete*/
wait(NULL);
printf("Child Complete!\n");
}
}

 2、在make rootfs后,help指令可见我们的fork指令

 3、进入gdb进行调试,在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork等处各设置断点

 4、不断执行之后,有如下的结果

 

 

 

 总结:

1、fork函数执行过程如下:

①当调用 Fork 函数时,它会调用 fork() 系统调用来创建一个新的子进程。

②如果 fork() 返回一个负数,那意味着创建子进程失败,通常是由于系统资源不足等原因。在这种情况下,程序会打印错误消息 "Fork Failed!" 并退出,返回状态码 -1。

③如果 fork() 返回0,那说明这是子进程。子进程会打印 "This is Child Process!

④如果 fork() 返回一个正数,那说明这是父进程。父进程会打印 "This is Parent Process!"。

⑤父进程会继续执行,并在 wait(NULL) 调用中等待子进程的终止。这是为了确保父进程在子进程完成之前不会继续执行。

⑥一旦子进程完成,父进程会继续执行,并打印 "Child Complete!"。

2、经过分析和资料查找,可以得到如下结果:

sys_clone 是Linux内核的系统调用,用于创建一个新进程(或线程)。这个系统调用接受一个或多个标志和参数,允许创建一个新的执行上下文,可以在同一地址空间或不同地址空间中运行。sys_clone 实际上是对 do_fork 函数的封装。

do_fork 是Linux内核中的一个关键函数,负责创建新进程或线程。它会复制父进程的状态、资源和执行环境,并为新进程分配新的任务结构体(task_struct)。这个函数会调用 copy_processcopy_thread 来执行具体的进程复制工作。

dup_task_struct 负责分配新的任务结构体,并复制父进程的任务结构体信息。

copy_process 是一个辅助函数,用于复制进程相关的信息,包括文件描述符、信号处理器、资源限制等。它会创建一个新的执行上下文,确保新进程拥有适当的资源和状态。

copy_thread 也是一个辅助函数,用于复制进程的线程信息。这包括处理线程的调度、信号处理、寄存器状态等。copy_thread 确保新进程的线程拥有适当的状态。

ret_from_fork 函数是一个汇编函数,它在进程创建后执行,负责将新进程的执行流程切换到用户空间。这个函数主要用于设置寄存器状态,以使新进程从创建点开始执行用户空间代码。

这些函数一起协作以实现新进程的创建,包括分配资源、复制父进程的状态和创建新的任务结构体。这是Linux内核用于多任务处理的核心机制,允许多个进程或线程同时运行在一个系统上。每个函数都有特定的职责,以确保新进程的正确初始化和执行。

以上就是fork函数的执行原理和过程。

附、chatGPT辅助问答:

1、

 

2、

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值