第六周——分析Linux内核创建一个新进程的过程
“万子恵 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
万子恵 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验部分
跟踪调试
1)更新menu
rm menu -rf //强制删除
git clone https://github.com/mengning/menu.git
2)更新test.c
cd menu
mv test_fork.c test.c
3)编译一下
make rootfs //自动编译

调用一下fork

4)调试time
qemu -kernel linux-3.18.6/arch/x86/boot/bzIamge -initrd rootfs.img -s -S
gdb
file linux-3.18.6/linux
target remote:1234
之后设一票断点(重要的部分),但是最后运行时我的实验楼突然卡住了,没能运行出来,这里会用文字和一些老师的图片请见谅
b sys_clone
b dup_task_struct
b copy_process
b copy_thread
b ret_form_fork

总结部分
内核三大功能:
进程管理
文件管理
内核系统
进程描述
进程控制块PCB _ TASK _ STRUCT 进程描述符
1)Linux进程的状态与操作系统原理中的描述的进程状态似乎有所不同,比如就绪状态和运行状态都是TASK_RUNNING

2)我们来看一下task_struct的整体吧~

所有进程链表struct list_head tasks;


程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。进程描述符中有几个域用来表示这样的关系




进程创建
1)kernel的两个线程
a.用户态进程启动kernel_init
b.启动kthreadd 所有内核线程的祖先
0号进程(手写)->1号进程(复制0号进程的PCB,根据其修改pid加载init可执行程序)
关于fork
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 < 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");
}
}
fork用户态子进程,else if和else都会被执行哦
在fork后,两个进程,fork系统调用在父子进程个返回一次
1)子 pid=0
2)父 pid=子进程的id
fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;
创建一个新进程在内核中的执行过程
系统调用复习

创建新进程是通过当前进程来实现的(不过有一些信息不能一样啦,pid啊,一部分的内核堆栈啊)
Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架:
复制一个PCB——task_struct
err = arch_dup_task_struct(tsk, orig);//复制整个PCB
要给新进程分配一个新的内核堆栈
ti = alloc_thread_info_node(tsk, node);
tsk->stack = ti;
setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
要修改复制过来的进程数据,比如pid、进程链表等等都要改改吧,见copy_process内部。
从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copy_thread in copy_process
*childregs = *current_pt_regs(); //复制内核堆栈
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶,拷贝内核堆栈数据和指定新进程的第一条指令地址
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址(从这句子程序得到CPU时,开始执行)
复制的时候只复制内核堆栈相关的一部分,内核堆栈最栈底
1.阅读理解task _ struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;
2.分析fork函数对应的内核处理过程sys _ clone,理解创建一个新进程如何创建和修改task_ struct数据结构;
请看总结。
3.使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解,推荐在实验楼Linux虚拟机环境下完成实验。
有实验截图~
4.特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
ret _ from _ fork 因为得到了cpu,复制了相关的信息(init指令和SAVE_ALL压到内核站的内容)设置子进程调度Ip。
第六周——分析Linux内核创建一个新进程的过程的更多相关文章
- 第六周分析Linux内核创建一个新进程的过程
潘恒 原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 task_struct结构: ...
- linux内核分析第六周-分析Linux内核创建一个新进程的过程
Linux内核对进程管理是操作系统的重要任务之一. 此次实验就是了解内核创建一个新进程的大致过程. 为了简单,使用fork再用户态创建一个进程.代码如下: 下面是准备工作 cd LinuxKer ...
- linux内核分析 第六周 分析Linux内核创建一个新进程的过程
进程的描述 操作系统的三大管理功能:进程管理.内存管理.文件系统 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. 进程控制块PCB task_struct:进 ...
- Linux内核及分析 第六周 分析Linux内核创建一个新进程的过程
实验过程 1.github上克隆相应的mengning/menu.git 2.测试menuOS,测试fork直接执行结果 3.配置调试系统,进入gdb调试,利用file linux-3.18.6/vm ...
- 实验 六:分析linux内核创建一个新进程的过程
实验六:分析Linux内核创建一个新进程的过程 作者:王朝宪 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029 ...
- 作业六:分析Linux内核创建一个新进程的过程
分析Linux内核创建一个新进程的过程 进程描述符PCB----task_struct数据结构 操作系统:1.进程管理 2.内存管理 3 文件系统 一.新进程如何创建和修改task_struct数据结 ...
- 实验六:分析Linux内核创建一个新进程的过程
原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- linux内核分析作业6:分析Linux内核创建一个新进程的过程
task_struct结构: struct task_struct { volatile long state;进程状态 void *stack; 堆栈 pid_t pid; 进程标识符 u ...
随机推荐
- mysql 存储 emoji报错( Incorrect string value: '\xF0\x9F\x98\x84\xF0\x9F)的解决方案
1.报错原因: mysql utf-8 编码储存的是 2-3个的字节,而emoji则是4个字节. 2.解决办法: 修改mysql的配置文件,windows下的为my.ini(linux下的为my.cn ...
- css3 transfrom变换
Transform 转换 CSS3中的转换允许我们对元素进行旋转.缩放.移动或倾斜,它分为2D转换 或3D转换 在CSS2时代,如果要做一些图片转换角度,都依赖于图片.flash或JavaScript ...
- iOS9 +http请求不能用的解决办法
报错NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802); 查询得知 iOS9引入了新特性App ...
- JS常用正则表达式和JS控制输入框输入限制(数字、汉字、字符)
验证数字:^[0-9]*$验证n位的数字:^\d{n}$验证至少n位数字:^\d{n,}$验证m-n位的数字:^\d{m,n}$验证零和非零开头的数字:^(0|[1-9][0-9]*)$验证有两位小数 ...
- js中Array的一些扩展
IE下很多Array的方法都不被支持.每次都要写.所以记下来,以免忘记: 以下是对Array的一些扩展,在FF ,google 下是不需要加的. /** * 方法Array.filter(functi ...
- classpath路径和properties
在Java程序中,一般情况下使用绝对路径还是相对路径都不太合适,因为Java程序的jar包所放的位置不确定,执行java程序时当前的路径也不确定,所以不合适.一般在Java程序中我们会把资源放到cla ...
- php 错误堆栈
ob_start(); debug_print_backtrace(); $errpr = ob_get_clean();
- php常见的关键字
一 instanceof 检测一个对象是否属于某个类型 <?php class A { } $a = new A(); if($a instanceof A) { echo "yes& ...
- 杭电ACM1003
原题: Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- 对于.NET Socket连接的细节记录
如果客户端直接连接一个不存在的服务器端,客户端会抛出异常: 如果在连接过程中,客户端强制关闭了连接(没有调用Close直接关闭了程序),服务器端会抛出异常: 如果在连接过程中,客户端调用了Close, ...