Windows操作系统下创建进程的过程
进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。而进程则不同,它是程序在某个数据集上的执行,是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。
线程(Thread)是进程的一个实体,是CPU调度和分派的基本单位。线程不能够独立执行,必须依存在进程中,由进程提供多个线程执行控制。从内核角度讲线程是活动体对象,而进程只是一组静态的对象集,进程必须至少拥有一个活动线程才能维持运转。
当某个应用程序调用一个创建进程的函数比如CreateProcess或者用户执行某一个程序(其实windows下用户执行一般普通程序是由explorer.exe调用CreateProcess来完成),操作系统把这个过程分成以下步骤来完成:
1.打开将要在该进程中执行的映像文件。
2.创建Windows执行体进程对象。
3.创建初始线程(栈、堆执行环境初始化及执行线程体对象)。
4.通知Windows子系统新进程创建了(子系统是操作系统的一部分它是一个协助操作系统内核管理用户态/客户方的一个子系统具体的进程为Csrss.exe)。
5.开始执行初始线程(如果创建时候指定了线程的CREATE_SUSPENDED状态则线程暂时挂起不执行)。
6.在新进程和线程环境中完成地址空间的初始化(比如加载必须的DLL和库),然后开始到进程入口执行。
到这里操作系统完成一个新进程的创建过程。下面来看下具体每一步操作系统所做的工作:
1.打开将要在该进程中执行的映像文件。
首先操作系统找到执行的Windows映像然后创建一个内存区对象,以便后面将它映射到新的进程地址空间中。
2.创建Windows执行体进程对象。
接下来操作系统调用内部的系统函数NtCreateProcess来创建一个Windwos执行体进程对象。具体步骤是:
(1)建立EPROCESS
*分配并初始化EPROCESS结构块
*从父进程处继承得到进程的亲和性掩码
*分配进程的最大最小工作集尺(由两个参数决定PsMinimumWorkingSet PsMaximumWorkingSet)
*降新进程的配额块设置为父进程配额块地址,并递增父进程配额块的引用计数
*继承Windows的设备名字空间
*将父进程进程ID保存在新进程对象的InheritedFormUniqueProcessId中
*创建该进程的主访问令牌
*初始化进程句柄表
*将新进程的退出状态设置为STATUS_PENDING
(2)创建初始的进程地址空间
*在适当的页表中创建页表项,以映射初始页面
*从MmresidentAvailablePage算出进程工作集大小
*系统空间的非换页部分和系统缓存的页表被映射到进程
(3)初始化内核进程块KPROCESS
(4)结束进程地址空间的创建过程
(5)建立PEB
(6)完成执行体进程对象的创建过程
3.创建初始线程(栈、堆执行环境初始化及执行线程体对象)。
这时候Windows执行体进程对象已经完全建立完成,但它还没有线程所以无法执行,接下来系统调用NtCreateThread来创建一个挂起的新线程它就是进程的主线程体。
4.通知Windows子系统新进程创建了(子系统是操作系统的一部分它是一个协助操作系统内核管理用户态/客户方的一个子系统具体的进程为Csrss.exe)。接下来操作系统通过客户态(Kernel32.dll)给Windows子系统(Csrss)发送一个新进程线程创建的数据消息,让子系统建立自己的进程线程管理块。当Csrss接收到该消息时候执行下面的处理:
*复制一份该进程和线程句柄
*设置进程优先级
*分配Csrss进程块
*把新进程的异常处理端口绑定到Csrss中,这样当该进程发生异常时,Csrss将会接收到异常消息
*分配和初始化Csrss线程块
*把线程插入到进程的线程列表中
*把进程插入到Csrss的线程列表中
*显示进程启动光标
5.开始执行初始线程(如果创建时候指定了线程的CREATE_SUSPENDED状态则线程暂时挂起不执行)。到这里进程环境已经建立完毕进程中开始创建的主线程到这里获得执行权开始执行线程。
6.在新进程和线程环境中完成地址空间的初始化(比如加载必须的DLL和库),然后开始到进程入口执行。
到这步实质是调用ldrInitializeThunk来初始化加载器,堆管理器NLS表TLS数组以及临界区结构,并且加载任何必须要的DLL并且用
DLL_PROCESS_ATTACH功能代码来调用各DLL入口点,最后当加载器初始化例程返回到用户模式APC分发器时进程映像开始在用户模式下执行,然后它调用线程启动函数开始执行。
到这里操作系统完成了所有的创建工作,我们写的程序就这样被操作系统调用运行起来了。
Windows操作系统下创建进程的过程的更多相关文章
- 【转载】详解CreateProcess调用内核创建进程的过程
原文:详解CreateProcess调用内核创建进程的过程 昨天同学接到了腾讯的电面,有一题问到了CreateProcess创建进程的具体实现过程,他答得不怎么好吧应该是, 为了以防万一,也为了深入学 ...
- 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习
反射实现Model修改前后的内容对比 在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...
- [学习分享] 在Windows操作系统下如何安装RMySQL包
最近在做股票的高频交易数据分析,需要用到数据库,而我只对MySQL比较熟悉,于是就安装了MySQL.当我安装好了MySQL后,正兴冲冲地准备安装RMySQL包时,问题来了:RMySQL包不支持wind ...
- Windows操作系统下远程连接MySQL数据库
用Eclipse做一个后台项目,但是数据库不想放在本地电脑,于是买了一个腾讯云服务器(学生有优惠,挺便宜的),装上MySQL数据库,但是测试连接的时候,发现总是连接不是上,但是本地数据库可以连接,于是 ...
- windows环境下创建 .文件夹
一.windows环境下创建 .文件夹 1.新建一个文件夹 2.重命名为.properties.(名字前后都加点) 二.windows环境下创建 .文件 1.上面的方法对文件同样适用 2.运行CMD, ...
- Windows操作系统下搭建Git服务器和客户端。
本文将介绍如何在Windows操作系统下搭建Git服务器和客户端.服务器端采用的是Bonobo Git Server,一款用ASP.NET MVC开发的Git源代码管理工具,界面简洁,基于Web方式配 ...
- Windows操作系统下SVN无法上传*.o文件
Windows操作系统下SVN无法上传*.o文件 2017年09月07日 10:14:49 yanlaifan 阅读数:834 摘自:https://blog.csdn.net/yanlaifan/ ...
- windows 内核下获取进程路径
windows 内核下获取进程路径 思路:1):在EPROCESS结构中获取.此时要用到一个导出函数:PsGetProcessImageFileName,申明如下: NTSYSAPI UCHAR * ...
- 关于Windows创建进程的过程
之前有听到别人的面试题是问系统创建进程的具体过程是什么,首先想到的是CreateProcess,但是对于具体过程却不是很清楚,今天整理一下. 从操作系统的角度来说 创建进程步骤: 1.申 ...
随机推荐
- Spring MVC入门示例(1)
1.新建一个Java Web项目 2.导入jar包 3.在WEB-INF下面建一个hello.jsp页面. 1 <%@ page language="java" import ...
- 关于__init__.py
假设程序目录结构如下: ├── checkpoints/ ├── data/ │ ├── __init__.py │ ├── dataset.py │ └── get_data.sh ├── mode ...
- CSS布局标准
回顾历史,CSS1于1996.12.17发正式版,它是为辅助HTML的展现效果而生的.1998.5.12,CSS2发正式版.随后发修订版CSS2.1,纠正了CSS2中的一些错误.注意从CSS2起,CS ...
- rem换算公式
当前rem基准值=预设的基准值/设计稿宽度*当前设备的宽度
- jquery高级编程学习
jquery高级编程 第1章.jQuery入门 类型检查 对象 类型检查表达式 String typeof object === "string" Number typeof ob ...
- 配置文件一mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC & ...
- 「题解」:[loj2763][JOI2013]现代豪宅
问题 A: 现代豪宅 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...
- 关于merge的测试
测试多线程情况下merge是否能产生重复数据. merge并发测试: 测试代码: 100线程,,插入连续的1000个数字
- 在MsSql中,创建链接服务器
建立链接服务器,主要为了跨服务器数据库操作 创建链接服务器 --创建远程链接服务器 EXEC sys.sp_addlinkedserver @server = 'SyncServer', -- 目标服 ...
- div中包着文字,div出现隐藏的时候,文字总是在div外面。
背景: 给博客加一个侧边栏,点击出现隐藏,每次点击出现或者隐藏,文字总是很突兀的就出来了. 解决: overflow:hidden