First of all, for any operating system, the system kernel must have a clear way to obtain process information. What pkzd uses is a global array struct proc proc[NPROC].
Among them, struct proc is the structure of the process structure, and NPROC is a macro used to determine the maximum number of processes that can exist at the same time. The specific code of the struct proc structure is as follows:
struct proc{ int p_exit;
uint p_stat;
uint p_flag;
uint p_sig;
uint p_esp;
uint p_lesp;
pid_t p_pid;
pid_t p_ppid;
pid_t p_pgrp;
uid_t p_uid;
uid_t p_ruid;
gid_t p_gid;
gid_t p_rgid;
uint p_cpu;
int p_pri;
int p_nice;
time_t p_time;
uint p_error;
uint *p_stack;
uint *p_pgdir;
void *p_wchan;
void *p_ttyp;
int p_signal[NSIG];
void *p_cdir;
void *p_rdir;
uint p_start;
uint p_end;
uint p_brk;
uint p_send;
void *p_ofile[NOFILE];
};
The process of the operating system has various information, such as process id, open file information, etc. Some information is not necessary for the kernel, and some is necessary.
I take the process id and file descriptor table as an example to make a comparison:
As the unique identifier of each process, p_pid must always reside in the system kernel space. If it is placed in the user space by design, there will be cases where the pid of the process may be swapped out to the swap space. Once this happens, the kernel will not be able to Identify the process.
p_ofile is the file descriptor table opened by the process, and the file descriptor table of each process does not need to reside in the kernel space in theory. The reason is that only the current process will read and write files, and a process that is not running will not be able to read files.
There are many reasons why the process id must exist in the kernel space. I will give an example: for example, after the current process executes the exit system call, the kernel needs to send a signal to the parent process of the current process or wake up the parent process that is waiting for the termination of the child process . The p_pid of the parent process has been swapped out, then the kernel will be at a loss.
pkzd stores all the information of the process in struct proc, without distinguishing whether the information needs to be resident in the kernel (this is a lazy way).
The general design of the unix system will put information that is only useful to the current process (such as the file descriptor table) in the user space, which is generally called the u area. The most important reason for designing the u area is to save memory, and today's machines already have a lot of memory, so there is no need to explicitly put all the information that can be placed in the u area in the u area. I The approach
is to directly save the realization of the u area, of course, this is lazy.
Finally, the language used by pkzd is c. The reason why c is used instead of other languages is that c and assembly have a high degree of fit (assembly functions can be called in c, and c can be called in assembly). The most important reason is c's powerful control over resources, which ordinary object-oriented languages cannot do. In addition, the reason for using c is not because many people understand that c can control hardware (generally, the code for controlling hardware is still done in assembly, although there are also examples of using c), the fundamental reason is that c will not be object-oriented like java. The language arbitrarily allocates memory automatically and causes the operating system kernel to lose control of resources (personal opinion after writing the system).
Link to the source code of the OS I wrote: https://sourceforge.net/projects/pkzd/