首先对于任何一个操作系统, 系统内核必须应该明确一种获取进程信息的办法, pkzd所使用的是一个全局数组struct proc proc[NPROC]。
其中struct proc为进程结构的结构体, NPROC是一个用来确定当前能同时存在的进程的最大数目的宏。struct proc结构的具体代码如下:
1 struct proc{ 2 int p_exit; 3 uint p_stat; 4 uint p_flag; 5 uint p_sig; 6 uint p_esp; 7 uint p_lesp; 8 pid_t p_pid; 9 pid_t p_ppid; 10 pid_t p_pgrp; 11 uid_t p_uid; 12 uid_t p_ruid; 13 gid_t p_gid; 14 gid_t p_rgid; 15 uint p_cpu; 16 int p_pri; 17 int p_nice; 18 time_t p_time; 19 uint p_error; 20 uint *p_stack; 21 uint *p_pgdir; 22 void *p_wchan; 23 void *p_ttyp; 24 int p_signal[NSIG]; 25 void *p_cdir; 26 void *p_rdir; 27 uint p_start; 28 uint p_end; 29 uint p_brk; 30 uint p_send; 31 void *p_ofile[NOFILE]; 32 };
操作系统的进程有各种各样的信息, 比如进程id, 打开的文件信息等。有的信息对内核而言不是必须的,而有的则是必须的。
我以进程id和文件描述符表为例做个对比:
pkzd将进程的所有信息都存放在struct proc中,而不去区分信息是否必要常驻内核(这是一种偷懒的方式)。
unix系统的一般设计都会将只对当前进程有用的信息(比如文件描述符表)放在用户空间中, 这个空间一般称为u区。设计u区的最重要的理由是为了节省内存, 而现如今的机器已经都有非常充裕的内存了,所以已经不需要特别明确的把所有可以放在u区的信息都放在u区,我的做法
更是直接省去了u区的实现,当然这是偷懒的。
最后pkzd所使用的语言为c,之所以采用c而非其他语言,首先c和汇编的契合度很高(c中可以调用汇编函数,汇编中又可调用c)。最重要的理由是c对资源的有力控制,而一般的面向对象的语言并不能做到。另外使用c的理由并非是因为很多人理解的c能操控硬件(一般控制硬件的代码还是用汇编完成的,虽然也有使用c的例子),根本的理由是c不会像java这样的面向对象的语言肆意的自动分配内存而导致操作系统内核对资源的失控(个人编写系统后的见解)。
我编写的操作系统的源代码的链接:https://sourceforge.net/projects/pkzd/