How to implement a system call fork ()?
How to implement a system call fork ()?
As we know, every process will call fork () in Linux. It will return 0 or 1 as normal or -1 to represent error. But, I don't know how to make a variable that can have two values at the same time. Can you give me some hits to help me to implement it?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: How to implement a system call fork ()?
Nope.gapry wrote:It will return 0 or 1
If you look up what it really does, it might also give you a clue as to how it did it.
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
Re: How to implement a system call fork ()?
I recommend you read the specification for fork...
I think some more reading is necessary, the link I provided should clear things up.
- fork() returns 0 in the 'child' process.
- fork() returns the PID of the child process in the 'parent' process (NOT simply 1).
- fork() returns -1 if an error occurs while forking.
I think some more reading is necessary, the link I provided should clear things up.
Re: How to implement a system call fork ()?
The important part to understand is that fork() creates a copy of the current process, assuming there only is a single thread in the process (the one calling fork). This is how it works:
Naturally, you can speed things up using copy-on-write where the address space contents is not copied until it is written to in any of the two thread. This is somewhat complicated and I recommend against doing it in your first OS until you got a basic fork working, you don't need this optimization for a long while anyway in my experience (I still don't have it). Keep in mind that in many cases, you don't actually do a full copy, such as mmap'd shared files and all that. There's a heap of special cases you'll want to get to eventually.
My kernel doesn't have a fork() system call as such, I have a more general thread_create() system call that creates a thread with the given registers in potentially a new thread. A user-space fork() fills in the registers desired for the new thread (identical, except a single value) and creates that thread in a cloned process, this gives the same result but with a stronger primitive. Linux does the same with the clone() system call, though mine is better designed.
I suspect you don't know paging well, you'll want to do that.
- Allocate a new process structure, this is the child process.
- Allocate a new address space for use by the child process and map the kernel in it, too.
- Iterate over all the user-space memory mappings of the parent process and map new memory at the same location in the child process and copy the data so each address space is identical.
- Copy other miscellaneous process attributes into the child process, such as signal handlers. Note that a perfect copy is not made, for instance any pending signals is not pending in the child process.
- Allocate a new thread structure associated with the child process, this is the child thread.
- Locate where the system call will return to and set the registers of the child thread so it resumes execution there (making a copy of the original thread) except the register containing the system call result is zero (marking it as the child).
- Mark the child thread as runnable, the current process has now been forked.
- Return the pid of the child process (marking the parent thread as such).
Naturally, you can speed things up using copy-on-write where the address space contents is not copied until it is written to in any of the two thread. This is somewhat complicated and I recommend against doing it in your first OS until you got a basic fork working, you don't need this optimization for a long while anyway in my experience (I still don't have it). Keep in mind that in many cases, you don't actually do a full copy, such as mmap'd shared files and all that. There's a heap of special cases you'll want to get to eventually.
My kernel doesn't have a fork() system call as such, I have a more general thread_create() system call that creates a thread with the given registers in potentially a new thread. A user-space fork() fills in the registers desired for the new thread (identical, except a single value) and creates that thread in a cloned process, this gives the same result but with a stronger primitive. Linux does the same with the clone() system call, though mine is better designed.
I suspect you don't know paging well, you'll want to do that.