《Linux内核分析》 第六节 进程的描述和进程的创建
《Linux内核分析》 第六节 进程的描述和进程的创建
20135307 张嘉琪 原创作品转载请注明出处 +《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、进程的描述
操作系统的三大功能:
- 进程管理(核心)
- 内存管理
- 文件系统
进程描述符task_struct数据结构
进程控制块PCB——task_struct
为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。
- struct task_struct数据结构很庞大
- 进程的标示pid
- 所有进程链表struct list_head tasks;
- 内核的双向循环链表的实现方法 - 一个更简略的双向循环链表
程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。进程描述符中有几个域用来表示这样的关系
Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info和进程的内核堆栈
二、进程的创建
进程的创建概览及fork一个进程的用户态代码
- iret与int 0x80指令对应,一个是弹出寄存器值,一个是压入寄存器的值
- 如果将系统调用类比于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,vfork,clone都可以创建新进程,他们都是通过调用do_fork来实现的。
- copy_process修改复制的PCB以适应子进程的特点,也就是子进程的初始化

分配一个新的内核堆栈(用于存放子进程数据)
- 内核堆栈的一部分也要从父进程中拷贝
- Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架: 复制一个PCB——taskstruct
err = arch_dup_task_struct(tsk, orig);
- 要给新进程分配一个新的内核堆栈
ti = alloc_thread_info_node(tsk, node);
tsk->stack = ti;
setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
- 从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和taskstruct中thread记录的sp和ip的一致性问题,这是在哪里设定的?
copythread in copy_process
阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;
实验报告
- 特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
- 答:
1 *childregs = *current_pt_regs(); //复制内核堆栈
2 childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
3
4 p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
5 p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址
即新进程是从ret_from_fork开始执行的。
- 分析fork函数对应的内核处理过程sysclone,理解创建一个新进程如何创建和修改taskstruct数据结构
由于创建新进程是由复制当前进程实现的,所以父子进程的PCB_task_struct是一样的。但是进程pid,内核堆栈,进程链表和ip、sp的位置是不能一样的, 他们是不同的进程。
- 使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解
- 更新menu内核,然后删除test_fork.c以及test.c

- 编译内核,可以看到fork命令

- 启动gdb调试,并对重要函数设置断点

- 继续执行之后,停在了do_fork的位置。然后n单步执行,依次进入copy_process、dup_task_struct。按s进入该函数,可以看到dst =src(也就是复制父进程的struct)



总结
Linux通过复制父进程来创建一个新进程,通过调用do_fork来实现,Linux为每个新创建的进程动态地分配一个task_struct结构.为了把内核中的所有进程组织起来,Linux提供了几种组织方式,其中哈希表和双向循环链表方式是针对系统中的所有进程(包括内核线程),而运行队列和等待队列是把处于同一状态的进程组织起来
《Linux内核分析》 第六节 进程的描述和进程的创建的更多相关文章
- LINUX内核分析第六周学习总结——进程的描述与创建
LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...
- LINUX内核分析第六周学习总结——进程的描述和进程的创建
LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- linux内核分析第六周学习笔记
LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- Linux内核分析实验六
Linux内核分析实验六 进程控制块PCB——task_struct(进程描述符) 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struct task_s ...
- Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...
- Linux内核分析第六周学习总结:进程的描述和进程的创建
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.进程的描述 ...
- 20135327郭皓--Linux内核分析第六周 进程的描述和进程的创建
进程的描述和进程的创建 一.进程的描述 操作系统三大功能: 进程管理 内存管理 文件系统 进程描述符task_struct数据结构 task _ struct:为了管理进程,内核必须对每个进程进行清晰 ...
- "Linux内核分析"第六周实验报告
张文俊 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1.进程的描述 ...
- 【MOOC EXP】Linux内核分析实验六报告
程涵 原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的描述和进程的创建 知识点梳理: ...
随机推荐
- BeiDou开源项目
本文主要围绕着BeiDou是什么及其安装和快速开始等两个方面,希望能够对初学者和对此感兴趣的朋友有所帮助. 一. BeiDou是什么 它是服务器呈现的React应用程序的同构框架 特征如下: ✔︎高性 ...
- Jquery分页组件
最近工作不是很忙,所以就看看淘宝kissy分页组件源码,感觉代码也不怎么难 容易理解,所以就按照他们的思路自己重新理一遍,来加深自己对他们的理解,同时对他们的分页组件进行一些重构(因为他们分页是做好了 ...
- JavaScript基础注意点
1.每个语句结尾一定加上分号 2.JavaScript本身对嵌套{ }的层级没有限制,但是过多的嵌套无疑会大大增加看懂代码的难度.遇到这种情况,需要把部分代码抽出来,作为函数来调用,这样可以减少代码的 ...
- POJ1127 Jack Straws
给你一些线段,求出哪些线段是相连的,哪些是不相连的.相连包括间接相连,即这两条线段本身不直接相连,而是通过其它线段的连接而间接相连. 线段相交+并查集 这里主要说如何判断线段相交:快速排斥试验+跨立试 ...
- C#抽象类与抽象方法--就是类里面定义了函数而函数里面什么都没有做的类
看一下代码应该就可以了 using System; using System.Collections.Generic; using System.Linq; using System.Text; na ...
- abp 修改abp.zero的实体映射类,使生成的表和字段为大写状态
在我们项目中,由于涉及到报表配置管理,可以通过一段sql快捷的配置出一个报表页面.部分sql会与abp框架的一些系统表做关联查询,而abp的映射类没有单独设置表和字段的名称,默认用类名和属性名,区分大 ...
- Spring Data JPA、MyBatis还有Hibernate有什么区别
原文:https://www.imooc.com/article/19754?block_id=tuijian_wz Spring Data JPA.MyBatis还有Hibernate有什么区别 2 ...
- 20155304田宜楠《网络对抗技术》Exp1 PC平台逆向破解(5)M
Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序 ...
- Python+Selenium爬取动态加载页面(1)
注: 最近有一小任务,需要收集水质和水雨信息,找了两个网站:国家地表水水质自动监测实时数据发布系统和全国水雨情网.由于这两个网站的数据都是动态加载出来的,所以我用了Selenium来完成我的数据获取. ...
- MiZ702学习笔记8——让MiZ702变身PC的方法
首先你需要一个安装好的linux系统,这里我用的是Ubuntu的虚拟机.VMWare的话,选择较高版本的成功率会高些(当然根据自己电脑的配置进行选择). 打开Ubuntu的虚拟机,找到一个叫做Disk ...