<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Loading_a_Process</id>
	<title>Loading a Process - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Loading_a_Process"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Loading_a_Process&amp;action=history"/>
	<updated>2026-04-06T00:31:23Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Loading_a_Process&amp;diff=716&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“加载和启动进程可以通过多种方式完成。  == 载入器功能 == 在[http://forum.osdev.org/viewtopic.php?p=112592#p112592 这篇文章]Brendan描述了创建的进程执行加载功能的方式，该功能可以将可执行文件加载到其地址空间中。 只有当进程获得其时间片时，此加载程序函数才处于活动状态。 这样，生成新进程的进程就不会被阻止。  *创建一个新的页面目录（映射到内核…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Loading_a_Process&amp;diff=716&amp;oldid=prev"/>
		<updated>2022-03-04T06:18:56Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“加载和启动进程可以通过多种方式完成。  == 载入器功能 == 在[http://forum.osdev.org/viewtopic.php?p=112592#p112592 这篇文章]Brendan描述了创建的进程执行加载功能的方式，该功能可以将可执行文件加载到其地址空间中。 只有当进程获得其时间片时，此加载程序函数才处于活动状态。 这样，生成新进程的进程就不会被阻止。  *创建一个新的页面目录（映射到内核…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;加载和启动进程可以通过多种方式完成。&lt;br /&gt;
&lt;br /&gt;
== 载入器功能 ==&lt;br /&gt;
在[http://forum.osdev.org/viewtopic.php?p=112592#p112592 这篇文章]Brendan描述了创建的进程执行加载功能的方式，该功能可以将可执行文件加载到其地址空间中。 只有当进程获得其时间片时，此加载程序函数才处于活动状态。 这样，生成新进程的进程就不会被阻止。&lt;br /&gt;
&lt;br /&gt;
*创建一个新的页面目录（映射到内核空间）；&lt;br /&gt;
*将内核页面表复制到新的页面目录中；&lt;br /&gt;
*设置计划程序数据（线程优先级等）并将初始EIP设置为“启动进程”内核函数；&lt;br /&gt;
*（可选）等待或阻止，直到新线程设置某种状态以返回；&lt;br /&gt;
* 返回给调用者。&lt;br /&gt;
&lt;br /&gt;
在此之后，我在内核空间中运行了一个新的线程/进程。 当调度器给它一个时间片时，内核设置“用户空间”（加载一个可执行文件等），然后“返回”到CPL=3。 不过，所有这些都是在新地址空间内发生的，因此不存在分页等问题。&lt;br /&gt;
&lt;br /&gt;
对于错误处理，对于我的操作系统，一切都是异步的——生成线程不会阻止从生成线程等待状态。 在内核“返回”到新进程/线程之前，它会向第一个线程发送一条状态/错误消息。 这意味着“spawnThread（）”函数可能会返回“OK”，之后可能会向你发送一个错误（例如“failed to load executable file”）。&lt;br /&gt;
&lt;br /&gt;
对于同步操作系统，“spawnProcess（）”函数将阻塞，直到返回完整状态。 理论上，这对应用程序程序员来说更容易使用，但对性能来说更糟。 例如，用户界面可能会锁定几秒钟，因为系统挣计划生成一个进程（例如，新进程的可执行文件恰好是慢速文件系统上的一个大文件）。 为了避免这个问题，应用程序程序员可能希望生成一个新线程来生成新进程；但这使得它比异步函数更难使用，开销更大，而且大多数应用程序程序员不会这么做（这要么太麻烦，要么他们根本没有意识到问题的存在）。&lt;br /&gt;
&lt;br /&gt;
== 进程管理器==&lt;br /&gt;
进程管理器用于加载Messiah Andrw[http://forum.osdev.org/viewtopic.php?p=112605#p112605 文章]中描述的可执行文件。&lt;br /&gt;
&lt;br /&gt;
进程管理器在自己的线程中运行。 通常这个线程处于休眠状态，但是如果一个作业被添加到进程管理器的队列（“生成进程”——这就是它现在使用的全部功能），进程管理器的线程处于休眠状态。 发送请求的进程通常会休眠，直到进程管理器完成其工作 - 但在多线程应用程序中，在加载进程的同时也可以执行其他操作。&lt;br /&gt;
&lt;br /&gt;
当我的调度程序切换到这些特殊的内核线程（进程管理器、vfs管理器等）时，它实际上会切换到它正在工作的进程的内存上下文。 这样，真正大的请求（例如，从文件中加载20MB）实际上是在一个单独的内核线程中处理的，数据被加载到进程的地址空间中，从而允许进程和所有其他进程继续做它想做的事情。&lt;br /&gt;
&lt;br /&gt;
这确实会对性能造成（相当轻微的）损失。 例如，要将程序加载到内存中，系统必须执行以下操作：&lt;br /&gt;
&lt;br /&gt;
* 父程序请求加载程序。&lt;br /&gt;
* - 跳到内核领域 -&lt;br /&gt;
* 内核将请求添加到进程管理器的队列中。唤醒进程管理器。&lt;br /&gt;
* - 跳转到用户领域-&lt;br /&gt;
* 父程序请求进入睡眠状态。&lt;br /&gt;
* - 跳转到内核领域 -&lt;br /&gt;
* 从“awake”列表中删除程序。&lt;br /&gt;
*-等待上下文切换到进程管理器-&lt;br /&gt;
* 设置新进程的内存。从VFS管理器请求文件。唤醒VFS管理器。将进程管理器转为睡眠状态。&lt;br /&gt;
&lt;br /&gt;
循环开始：&lt;br /&gt;
*- 等待上下文切换到VFS管理器 -&lt;br /&gt;
*从磁盘驱动程序请求部分文件。 唤醒磁盘驱动程序。 让VFS进入睡眠状态。（请求被分成128kb的块，因此可以同时进行多个读/写操作）。&lt;br /&gt;
* - 等待上下文切换到磁盘驱动程序-&lt;br /&gt;
* 从磁盘加载部分文件。唤醒VFS。&lt;br /&gt;
如果未完全加载，则返回循环的开头（VFS将只请求文件的一部分，例如，先请求ELF头，然后请求程序头，然后请求数据等）。&lt;br /&gt;
&lt;br /&gt;
* 唤醒进程管理器。&lt;br /&gt;
* - 等待上下文切换到进程管理器-&lt;br /&gt;
* 将新进程添加到调度算法中。 唤醒父进程。 如果没有其他东西要排队，将进程管理器发送到睡眠状态。&lt;br /&gt;
&lt;br /&gt;
正如你所看到的，需要做很多工作。 这些特殊线程并不是内核的一部分，它们也不存在于它们自己的地址中，它们只是走到其他进程，然后说“怎么了，我能跟你相处一段吗？”&lt;br /&gt;
&lt;br /&gt;
==延迟加载==&lt;br /&gt;
当你的操作系统支持从任何文件（而不仅仅是交换文件）交换页面时，你可以创建一个地址空间，将页面标记为不存在，并映射到磁盘上的可执行文件。 这样，当新进程开始执行时，内存管理器将自动从可执行文件中交换所需的页面。 它只加载此时需要的页面，因此在启动时需要更少的内存。&lt;br /&gt;
&lt;br /&gt;
==准入调度器（Admission Scheduler）==&lt;br /&gt;
一些操作系统使用长期调度器（long-term scheduler）或准入调度器（admission scheduler）来控制特定进程的启动时间。 它主要用于实时操作系统来控制系统的负载。 这个想法类似于前面[[Loading a Process#进程管理器|进程管理器]]方法。 如果你曾经打算支持实时调度，这是一条路要走。 或者哪怕你的操作系统最初只是一个简单的桌面操作系统，你这样做也可以对准入调度器进行编码，以自动加载其队列中的任何可执行文件。&lt;br /&gt;
&lt;br /&gt;
==参考文献==&lt;br /&gt;
===文章===&lt;br /&gt;
*[[Context Switching|上下文切换]]&lt;br /&gt;
*[[Processes and Threads|进程和线程]]&lt;br /&gt;
&lt;br /&gt;
=== 论坛主题 ===&lt;br /&gt;
* [http://forum.osdev.org/viewtopic.php?f=1&amp;amp;t=15622 Loading processes in (new) virtual address space]&lt;br /&gt;
&lt;br /&gt;
===外部链接===&lt;br /&gt;
* [[Wikipedia:Scheduling (computing)#Long-term_Scheduler|Admission Scheduler]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Processes and Threads]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>