Linux内核设计第六周

——进程的描述和创建

第一部分 知识点总结

一、进程描述符task_struct数据结构

1、操作系统的三大功能:

进程管理、内存管理、文件系统

2、进程的作用:

将信号、进程间通信、内存管理和文件系统联系起来

3、进程控制块PCB——task_struct数据结构

提供了内核需要了解的信息

4、task_struct结构庞大,有400多行代码。包含了进程状态、内核堆栈等相关信息的定义。 可以从下面的图示中,清晰的看出大体的框架。

5、Linux的进程和操作系统原理中描述的进程状态(就绪状态、运行状态、阻塞状态)有所不同,实际内核中,就绪和运行状态都用TASK_RUNNING表示。

6、进程标志符pid/tpid——用于标识进程

7、总体浏览task_struct结构

二、进程的创建概览及fork一个进程的用户态代码

1、进程创建的关键信息:状态、内核堆栈、CPU上下文切换、链接、文件系统、信号、内存等。

2、进程的起源

3、进程创建步骤:

  • 复制进程描述符
  • 修改子进程的PCB信息

4、shell命令如何创建子进程

  • 使用fork函数在用户态创建子进程
  • fork系统调用在父进程和子进程各返回一次
  • 在子进程中,返回0,在父进程中,返回子进程ID

三、理解进程创建过程复杂代码的方法

理解进程创建过程复杂代码的方法:

  • 先根据对功能的理解,自己预想可以怎样实现;
  • 再从源代码中,找到和预想相似的证据。

1、系统调用复习

  • 从系统内核理解

  • 从用户程序理解

2、fork代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
int pid;
/* fork another process */
pid = fork();
if (pid < )
{
/* error occurred */
fprintf(stderr,"Fork Failed!");
exit(-);
}
else if (pid == ) //pid == 0和下面的else都会被执行到(一个是在父进程中即pid ==0的情况,一个是在子进程中,即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");
}
}

3、fork、vork、clone都可以创建一个子进程,它们都调用了do_fork()实现进程创建。

四、浏览进程创建过程的关键代码

1、复制PCB——task_struct

err = arch_dup_task_struct(tsk, orig);

2、给新进程创建新的内核堆栈

ti = alloc_thread_info_node(tsk, node);//创建新的内核堆栈
tsk->stack = ti;
setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
setup_thread_stack(tsk,orig);

3复制copy_process

即内核堆栈中的thread.sp的内容

4、fork执行过程分析

5、子进程是从哪里执行的? 
代码部分为

*childregs = *current_pt_regs(); //复制内核堆栈
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因! p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

ret_from_fork就是子函数开始执行的地方,我们查看ret_from_fork在系统文件entry32.h中的定义可以发现,是执行了如下图所示的过程。

第二部分 实验部分

1、更新menu,删除test_fork.c和test.c文件,重新执行make rootfs

2、重新make rootfs之后,可以看到内核被启动

3、像之前的实验一样,启动gdb调试

4、在fork系统调用的关键代码处,设置断点。

5、在Menu系统中输入fork指令,可以看到只输出了fork功能的描述,没有之后的部分,说明该过程在断点处停止了。

6、单步调试,可以看到程序停在了copy_process函数处

7、继续单步执行,程序再次停在了dup_task_struct函数处

8、进入duptaskstruct函数,继续单步执行,程序再次停在了duptaskstruct函数处

9、在copy_thread函数中,继续单步执行,可以看到,内核空间压栈地址被初始化了。

10、继续执行单步调试,如图所示,当前内核堆栈寄存器中的值复制到子进程中

11、如图所示,标记代码的作用是,设置子进程被调度的起点

12、如图所示,我们可以看到程序停止在了ret_from_fork处

13、对ret_from_fork继续执行单步调试,我们可以看,当前系统执行的是汇编代码

14、当程序跳转到syscall_exit处后,就不能再继续gdb跟踪调试了

总结:

子进程是从ret_ from_ fork开始执行的。子进程在进入sys_ call之前与父进程的堆栈状态相同,ret_ from_ fork中跳转到了syscall_ exit,继续执行上周我们分析过的部分,注意:当子进程获得CPU控制权的时候,它的ret_ from_ fork可以把后面堆栈从iret返回到用户态,这里的用户态是子进程的用户态

宋宸宁+ 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

Linux内核设计第六周 ——进程的描述和创建的更多相关文章

  1. 20135327郭皓--Linux内核分析第六周 进程的描述和进程的创建

    进程的描述和进程的创建 一.进程的描述 操作系统三大功能: 进程管理 内存管理 文件系统 进程描述符task_struct数据结构 task _ struct:为了管理进程,内核必须对每个进程进行清晰 ...

  2. Linux内核设计第八周 ——进程的切换和系统的一般执行过程

    Linux内核设计第八周 ——进程的切换和系统的一般执行过程 第一部分 知识点总结 第二部分 实验部分 1.配置实验环境,确保menu内核可以正常启动 2.进入gdb调试,在shedule和conte ...

  3. Linux内核设计第六周学习总结 分析Linux内核创建一个新进程的过程

    陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验过程 登陆实验楼 ...

  4. 《Linux内核分析》第六周 进程的描述与创建

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK SIX(3 ...

  5. Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程

    Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  6. LINUX内核分析第六周学习总结——进程的描述与创建

    LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...

  7. LINUX内核分析第六周学习总结——进程的描述和进程的创建

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  8. Linux内核设计第三周——构造一个简单的Linux系统

    Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...

  9. Linux内核设计第七周 ——可执行程序的装载

    Linux内核设计第七周 ——可执行程序的装载 第一部分 知识点总结 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 编译链接的过程 预处理阶段 gcc -E -o XX.cpp ...

随机推荐

  1. Python学习笔记04

    语句之后有冒号,表示有一个语句块,且以四个空格的缩进来表示隶属关系. 与C# 相比,没有了{},没有了(),被冒号和缩进取代了 if,while,for,range,continue,break if ...

  2. COGS1752 [BOI2007]摩基亚Mokia(CDQ分治 + 二维前缀和 + 线段树)

    题目这么说的: 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它 ...

  3. Apache ActiveMQの版本更迭和Apache ActiveMQの故障转移

    本文描述apache activemq 版本更迭的原因以及Apache ActiveMQのThe Failover Transport new features in 5.2.0  1.对信息的传输/ ...

  4. Codeforces Round #246 (Div. 2) A. Choosing Teams

    给定n k以及n个人已参加的比赛数,让你判断最少还能参加k次比赛的队伍数,每对3人,每个人最多参加5次比赛 #include <iostream> using namespace std; ...

  5. 模态视图(modalTrasitionStyle)如何适应不同的版本

    随着版本的更新,模态视图对版本也有不同的要求,那如何让模态视图适应多版本的要求呢?下面是小编的个人看法! -(void)presentModalVC { modalViewController *mo ...

  6. 【BZOJ】2823: [AHOI2012]信号塔

    题意 给\(n\)个点,求一个能覆盖所有点的面积最小的圆.(\(n \le 50000\)) 分析 随机增量法 题解 理论上\(O(n^3)\)暴力,实际上加上随机化后期望是\(O(n)\)的. 算法 ...

  7. Codeforces Round #210 (Div. 2) C. Levko and Array Recovery

    题目链接 线段树的逆过程,想了老一会,然后发现应该是包含区间对存在有影响,就不知怎么做了...然后尚大神,说,So easy,你要倒着来,然后再正着来,判断是不是合法就行了.然后我乱写了写,就过了.数 ...

  8. CF 346B. Lucky Common Subsequence(DP+KMP)

    这题确实很棒..又是无想法..其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了. dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len] ...

  9. python 教程

    教程 http://www.runoob.com/python/att-list-append.html 习题 http://blog.csdn.net/liuyuan_jq/article/deta ...

  10. iOS 项目中用到的一些开源库和第三方组件

    iOS 项目中用到的一些 iOS 开源库和第三方组件 分享一下我目前所在公司 iOS 项目中用到的一些 iOS 开源库和第三方组件, 感谢开源, 减少了我们的劳动力, 节约了我们大量的时间, 让我们有 ...