This article mainly focuses on the two system calls, fork and execve, in Linux 0.11 and describes what will happen when we call them.
Fork
In Linux programing, fork is one of most widely used functions. Fork will create a same process as the current process. Based on the return value of the fork function, we can decide whether we are in the father process or child process. Fork is a system call, that calling this function will trigger a soft interrupt and the kernel will do the next jobs.
In Linux0.11, kernel will try to find a used item in array task[64]. If all the array is full, fork will return an error EAGAIN, which means the number of processes has reached its limit, please try again. Linux 0.11 supports at most 64 processes coexisting at the same time. And each process’s segment descriptor’s base address is 64MB $\times$ [the index in array task]. Based on this, kernel will add the new process’s code segment descriptor and data segment descriptor into GDT.
Once a process has been created, kernel will malloc a page to store the process’s task structure and store the current registers’ values into the TSS structure in task structure. This step is very important, because without this, the child may run the fork function again. Then the kernel set the return value into EAX register to make sure the father and child have different return values.
Based on the sgement limit of the father process, kernel will copy the page directory and page table to new process and put them at the begin of the linear address. So even the father and child process use different page directory and page table, but they use the same physical page. As the same page is being used by two processes, kernel set the page as read only, and add the page’s count by 1.
As the child process’s task structure is directly copied from its father, the child process has its father’s file and other resources. So the kernel will add the counts of these resources by 1.
Execve
In Linux programing, fork and execve are usually used together, using fork create a process and calling execve to open an executable file.
After calling the fork system call, child and father process nearly shared all the resources. Like fork, execve is also a system call. In this system call, it will first malloc 32 pages (128KB) to store the environment values. Based on the file path, find the inode of the executable file and check the validity of this file. After the checking, put the environment values in the 32 pages. Change the current executable file into the new executable file (note: process 0 and process 1 have no executable file). Then close the resources (including the shared pages) of the father process by minus the counts of them by 1.
Read the information of the executable file head. Based on this information set the new code segment limit and data segment limit and insert the pages, storing the environment values, into the end of the data segment and create a table to manage these values. Set the stack pointer and code pointer.
After finished all these perpared work, when the process is waken up again, it will run in a new code segment, and this page is missing. In this case, it will trigger an interrupt, mallocing a new page and read the code from the executable file. If in the system, there is another process executing the same executable file, these processes will share the same pages.