程序员QNX操作系统C语言&嵌入式

QNX进程管理器

2019-01-04  本文已影响4人  Loyen

QNX相关历史文章:

1.Introduction

在QNX Neutrino中,微内核与进程管理器一起组成procnto模块,所有运行时系统都需要这个模块。

进程管理器可用于创建多个POSIX进程(每个进程可能包含多个POSIX线程),它的主要职责包括:

用户进程可以通过内核调用访问微内核函数,也可以通过向procnto发送消息来访问进程管理器函数。
procnto中执行线程去调用微内核的方式与其他进程中的线程完全相同,进程管理器代码和微内核共享相同的地址空间并不意味着有一套特殊的或私有的接口,系统中的所有线程共享相同的内核接口,并且在调用内核时执行特权切换。

2. Process management

procnto的首要任务就是动态创建新进程,创建的进程也会依赖procnto提供的内存管理和路径名管理相关功能。
进程管理包括进程创建、销毁、属性(进程ID、用户ID、组ID)管理。包含以下接口:

  1. 创建当前执行环境的新实例,可用pthread_create()替代;
  2. 创建一个运行不同程序的新进程,可用posix_spawn()来替代;

3. Memory management

在某些实时内核中,会在开发环境中提供内存保护支持,却很少为运行时配置提供内存保护,原因是内存和性能的损失。随着内存保护在很多嵌入式处理器中越来越普遍,内存保护的好处远远超过了它带来的性能损失,最关键的一点就是提高了软件的鲁棒性。
内存保护对地址空间进行了隔离,避免了一个进程中的错误影响其他进程或内核。启用MMU后,操作系统可以在发生内存访问冲突时中止进程,并立刻反馈给程序员,而不是在运行一段时间后突然崩溃。

3.1 MMU

典型的MMU操作方式是将物理内存划分为4KB页面,在内存中会存储一组页表,页表里存放着虚拟地址到物理地址的映射关系,CPU根据页表内容来访问物理内存。


Virtual address mapping(on an X86)

为了提高性能,通常会使用TLB来提高页表条目的查找效率。页表条目中会对页面进行读写等权限控制。当CPU进行上下文切换的时候,如果是不同进程之间,则需要通过MMU来切换不同的地址空间,如果是在一个进程内部,则不需要这步操作。

3.2 Memory protection at run time

在许多嵌入式系统中,会使用硬件看门狗来检测是否有软件或硬件异常,在出现异常时则进行重启。
在内存保护系统中,有一种更好的方式,可以称为软件看门狗。当软件出现间歇性错误时,操作系统可以捕获事件,并将控制权交给用户线程,而不是直接进行内存转储。用户线程则可以有选择的做决定,而不是像硬件看门狗那样直接重启。软件看门狗可以做:

很显然,软件看门狗能更好的进行控制,还可以收集有关软件故障的信息,有利于事后的诊断。

3.3 Quality control

通过将嵌入式系统划分成一组协作的、受内存保护的进程,我们可以很容易重用这些组件。加上有明确的接口定义,这些进程可以放心的集成到应用程序中,确保它们不会破坏系统的整体可靠性。当然,应用程序不可能做到完全没有bug,系统应该设计成能够容忍并从故障中恢复的架构,而利用MMU提供内存保护正是朝着这个方向迈出了良好的一步。

3.4 Full-protection model

在全保护模型中,QNX Neutrino首先会将image中的所有代码重定位到一个新的虚拟空间中,使能MMU,设置好初始页表。这就允许procnto在支持MMU的环境中启动,随后,进程管理器便会接管该环境,再根据启动的进程来修改页表。

Full protection VM

3.5 Locking memory

QNX Neutrino支持内存锁定,进程可以通过锁定内存来避免获取内存页的延迟。
内存锁定分为以下几级:

3.6 Defragmenting physical memory

就像磁盘碎片一样,程序的运行也有可能带来内存碎片问题。
碎片整理的任务包括更改现有的内存分配和映射,以便使用不同的底层物理页面。通过交换底层的物理内存单元,操作系统可以将碎片化空间合并成连续的区域,但是在移动某些类型的内存时需要小心,因为这类内存的映射表不能被安全的修改。

4. Pathname management

procnto允许资源管理器通过提供标准的API接口,管理路径名空间子集作为自己的“授权域”。当一个进程打开一个文件时,兼容POSIX的open库函数会向procnto发送路径名消息,procnto会根据路径的前缀来判断由哪一个资源管理器来处理。当一个前缀被重叠注册时,会使用与最长的前缀关联的资源管理器来处理。
启动时,procnto会创建以下路径名:

4.1 Resolving pathnames

可以举个例子来说明一下最长路径名匹配,假设有以下路径名进行了注册,并有对应的模块:



下表展示了路径名解析的最长匹配规则:


4.2 Single-device mountpoints

假设有三个服务器:

假设一个客户端想往服务器C发送消息,客户端的代码如下:

int fd;
fd = open("/dev/random", ...);
read(fd, ...);
close(fd);

在这种情况下,C库代码会请求进程管理器提供处理路径/dev/random的服务器,进程管理器将返回服务器列表:

4.3 Unioned filesystem mountpoints

假设有两个服务器:

DIR *dirp;
dirp = opendir("/bin", ...);
closedir(dirp);

结果为:

4.4 Symbolic prefixes

类似于Linux系统中的链接,在QNX中,可以通过ln -s来建立链接,比如:
ln -Ps /net/neutron/bin /bin
此时,/bin/ls会被替换成/net/neutron/bin/ls,在进行路径名匹配时,会匹配到/net上,而/net指向的是lsm-qnetlsm-qnet资源管理器会去解析neutron组件,并将进一步的解析请求发送到叫neutron的网络节点上,从而在neutron节点上完成/bin/ls的解析。符号链接允许我们像访问本地文件系统一样访问远程文件系统。
执行重定向不需要运行本地文件系统,无磁盘工作站的路径名组织可能如下图,本地设备(如;dev/ser1/dev/console)将被路由到本地字符设备管理器,而对其他路径的请求将会被路由到远程文件系统。

4.5 File descriptor namesapce

文件描述符空间属于进程内部资源,资源管理器通过使用SCOID(Server Connection ID)和FD(File Descriptor)来标识OCB(open control block),其中在IO管理器中,使用稀疏矩阵完成三者之间的映射:

Sparse array

OCB结构包含了打开资源的活动信息,下图中表示一个进程打开文件两次,另一个进程打开同一文件一次:

Two processes open the same file

也可以多个不同进程之间的描述符指向同一个OCB结构,通常是在dup()/dup2()/fcntl()或者vfork()/fork()/posix_spawn()/spawn()接口调用时产生的,此时一个进程对OCB操作可能会影响与之关联的进程,如下图:

A process opens a file twice
上一篇下一篇

猜你喜欢

热点阅读