Loading a Process

来自osdev
跳到导航 跳到搜索

加载和启动进程可以通过多种方式完成。

载入器功能

这篇文章Brendan描述了创建的进程执行加载功能的方式,该功能可以将可执行文件加载到其地址空间中。 只有当进程获得其时间片时,此加载程序函数才处于活动状态。 这样,生成新进程的进程就不会被阻止。

  • 创建一个新的页面目录(映射到内核空间);
  • 将内核页面表复制到新的页面目录中;
  • 设置计划程序数据(线程优先级等)并将初始EIP设置为“启动进程”内核函数;
  • (可选)等待或阻止,直到新线程设置某种状态以返回;
  • 返回给调用者。

在此之后,我在内核空间中运行了一个新的线程/进程。 当调度器给它一个时间片时,内核设置“用户空间”(加载一个可执行文件等),然后“返回”到CPL=3。 不过,所有这些都是在新地址空间内发生的,因此不存在分页等问题。

对于错误处理,对于我的操作系统,一切都是异步的——生成线程不会阻止从生成线程等待状态。 在内核“返回”到新进程/线程之前,它会向第一个线程发送一条状态/错误消息。 这意味着“spawnThread()”函数可能会返回“OK”,之后可能会向你发送一个错误(例如“failed to load executable file”)。

对于同步操作系统,“spawnProcess()”函数将阻塞,直到返回完整状态。 理论上,这对应用程序程序员来说更容易使用,但对性能来说更糟。 例如,用户界面可能会锁定几秒钟,因为系统挣计划生成一个进程(例如,新进程的可执行文件恰好是慢速文件系统上的一个大文件)。 为了避免这个问题,应用程序程序员可能希望生成一个新线程来生成新进程;但这使得它比异步函数更难使用,开销更大,而且大多数应用程序程序员不会这么做(这要么太麻烦,要么他们根本没有意识到问题的存在)。

进程管理器

进程管理器用于加载Messiah Andrw文章中描述的可执行文件。

进程管理器在自己的线程中运行。 通常这个线程处于休眠状态,但是如果一个作业被添加到进程管理器的队列(“生成进程”——这就是它现在使用的全部功能),进程管理器的线程处于休眠状态。 发送请求的进程通常会休眠,直到进程管理器完成其工作 - 但在多线程应用程序中,在加载进程的同时也可以执行其他操作。

当我的调度程序切换到这些特殊的内核线程(进程管理器、vfs管理器等)时,它实际上会切换到它正在工作的进程的内存上下文。 这样,真正大的请求(例如,从文件中加载20MB)实际上是在一个单独的内核线程中处理的,数据被加载到进程的地址空间中,从而允许进程和所有其他进程继续做它想做的事情。

这确实会对性能造成(相当轻微的)损失。 例如,要将程序加载到内存中,系统必须执行以下操作:

  • 父程序请求加载程序。
  • - 跳到内核领域 -
  • 内核将请求添加到进程管理器的队列中。唤醒进程管理器。
  • - 跳转到用户领域-
  • 父程序请求进入睡眠状态。
  • - 跳转到内核领域 -
  • 从“awake”列表中删除程序。
  • -等待上下文切换到进程管理器-
  • 设置新进程的内存。从VFS管理器请求文件。唤醒VFS管理器。将进程管理器转为睡眠状态。

循环开始:

  • - 等待上下文切换到VFS管理器 -
  • 从磁盘驱动程序请求部分文件。 唤醒磁盘驱动程序。 让VFS进入睡眠状态。(请求被分成128kb的块,因此可以同时进行多个读/写操作)。
  • - 等待上下文切换到磁盘驱动程序-
  • 从磁盘加载部分文件。唤醒VFS。

如果未完全加载,则返回循环的开头(VFS将只请求文件的一部分,例如,先请求ELF头,然后请求程序头,然后请求数据等)。

  • 唤醒进程管理器。
  • - 等待上下文切换到进程管理器-
  • 将新进程添加到调度算法中。 唤醒父进程。 如果没有其他东西要排队,将进程管理器发送到睡眠状态。

正如你所看到的,需要做很多工作。 这些特殊线程并不是内核的一部分,它们也不存在于它们自己的地址中,它们只是走到其他进程,然后说“怎么了,我能跟你相处一段吗?”

延迟加载

当你的操作系统支持从任何文件(而不仅仅是交换文件)交换页面时,你可以创建一个地址空间,将页面标记为不存在,并映射到磁盘上的可执行文件。 这样,当新进程开始执行时,内存管理器将自动从可执行文件中交换所需的页面。 它只加载此时需要的页面,因此在启动时需要更少的内存。

准入调度器(Admission Scheduler)

一些操作系统使用长期调度器(long-term scheduler)或准入调度器(admission scheduler)来控制特定进程的启动时间。 它主要用于实时操作系统来控制系统的负载。 这个想法类似于前面进程管理器方法。 如果你曾经打算支持实时调度,这是一条路要走。 或者哪怕你的操作系统最初只是一个简单的桌面操作系统,你这样做也可以对准入调度器进行编码,以自动加载其队列中的任何可执行文件。

参考文献

文章

论坛主题

外部链接