|
6#
楼主 |
发表于 2015-9-14 11:21:29
|
只看该作者
在改造的过程中发现,原来的 PSP 进程数据结构设计有个令人难受的弊端。
在开发的早期,我只是学习 DOS 的做法,弄个 PSP 在进程空间的最开头。DOS 的 PSP 占用 256 字节,而我们的 PSP 长度是可变的。
然而,PSP 处于进程空间的最开头,其坏处之一就是破坏了对齐性。具体来说,我遇到这样的问题:
ahci 程序需要一些按照 4K 对齐的内存。这需要在程序开始运行之后动态分配。
假定进程的 PSP 被分配为 4K 对齐,那么,既然保证动态分配的内存也是 4K 对齐,那就无法保证 main 的地址是 4K 对齐(除非修改内核的进程管理代码,让 PSP 的长度总是 4K 的倍数,这样是很大的浪费)。
这样,如果要把 ahci 程序自身挪到扩展内存顶端,就需要连同 PSP 一起挪动(否则就不是从 4K 对齐的边界处开始挪动)。而且为了做成 int13 的处理程序,我们在 PSP 之前还需要增加其他一些结构,比如说,记录 int13 处理程序的长度,记录常规内存 int13 处理程序的地址,还要有保护模式的中断描述符表(它占用 2K),等等。这些附加的结构,设计为 8K,这 8K 之后,紧接着就是 PSP。而 PSP 之后,紧接着就是 main 函数。
然而问题出来了:8K 的 int13 信息空间与 main 函数之间,隔着个可变长度的 PSP。这就让 8K 的 int13 空间与 main 的代码不能直接访问(相对位置的差值不是常数,而是变化的)。虽然 PSP 的长度是可以确定的,但这是通过变量来计算的。这个 PSP 夹在中间,带来了很多计算方面的负担。这是个瓶颈,如果没有这个可变长度的 PSP,我们的计算要简单得多,程序也容易看懂。有了这个 PSP,每次互访,地址都要经过转换、计算,程序太复杂了,给后来的开发者造成了阅读代码的痛苦。
为此我考虑解决的办法。进程开头直接放置 main 代码,而把 PSP 挪到进程尾部。
进程的长度可以通过 _end 变量来确定。gcc 用 end 或 _end 来表示 __bss_end。这样,我找到了一个办法,让进程的长度能够记录在 ahci 程序的结尾附近。内核的进程管理代码可以读出 ahci 进程所需要的长度,并在 _end 处开始放置 PSP。如此一来,问题就解决了。
|
|