Would the reference I make to '*a' in the fork() refer back to the parents address space, or does Minix have some way of knowing where abouts pointers are kept on the stack, so it could adjust their value to point into the child's address space? If not, is a real fork() command not really possible on an ST? Hope someone can help.... -- ----------------------------------------------------------- Robert Walsh Email: rjwa...@unix2.tcd.ie Engineering School, Trinity College Dublin. -----------------------------------------------------------
R> Would the reference I make to '*a' in the fork() refer R>back to the parents address space, or does Minix have some way R>of knowing where abouts pointers are kept on the stack, so it R>could adjust their value to point into the child's address R>space? R> If not, is a real fork() command not really possible on R>an ST? Hope someone can help....
I can't speak for Minix's fork, but here's how most *nix's handle forks...
When you generate a new child process, the whole program is copied in memory to a new process (variables included, except malloc'd space). What does this mean? If you let the compiler allocate a variable, the parent's copy and the child's copy will have the same value at the start, but if you change it, you will have to change it in both places. If you allocated it at runtime (malloc), then the pointers will have the same value (map to the same shared memory). Thus, if you change a value in the child or the parent, the other's copy is also instantly changed.
Kevin
-- Kevin Benton - SysOp of... Project Thunder (ssci) 1:157/516.0 :-) once in a while... FidoNet 1:157/533.14 you might actually learn UseNet uunet!ssci!kevin to like it!
s1ke...@ssci.UUCP (Kevin Benton) writes: >I can't speak for Minix's fork, but here's how most *nix's handle forks... >When you generate a new child process, the whole program is copied in memory to >a new process (variables included, except malloc'd space). What does this >mean? If you let the compiler allocate a variable, the parent's copy and the >child's copy will have the same value at the start, but if you change it, you >will have to change it in both places. If you allocated it at runtime >(malloc), then the pointers will have the same value (map to the same shared >memory). Thus, if you change a value in the child or the parent, the other's >copy is also instantly changed.
This is, of course, not true. Processes in Unix do not share their address space. Fork copies the data segment of the process and sets up the MMU appropriately.
As an example, lets assume our MMU uses 1k pages and has 16 bit addresses and our program uses 2k of text, 3k of data, and 1k stack.
So that pointer 0xC23 refers to physical address 0xB423. If the process forks, the pages in the data and stack segment are copied to free pages, (e.g. D400, DC00, E000, E400) and the page table for the child process is set up as follows:
Now the pointer 0xC23 in the child process refers to physical address 0xC023 and the same pointer in the parent process still refers to 0xB423. They can never interfere with each other.
Of course, if you don't have an MMU (like the Atari ST), you have to use all sorts of evil tricks to emulate one (like physically copying lots of memory on context switches -- BTW, I always wondered how much slower the average program would become if it did all pointer arithmetic relative to a base pointer instead of absolute). -- | _ | Peter J. Holzer | Think of it | | |_|_) | Technical University Vienna | as evolution | | | | | Dept. for Real-Time Systems | in action! | | __/ | h...@vmars.tuwien.ac.at | Tony Rand |
s1ke...@ssci.UUCP (Kevin Benton) writes: >I can't speak for Minix's fork, but here's how most *nix's handle forks... >When you generate a new child process, the whole program is copied in memory to >a new process (variables included, except malloc'd space). What does this >mean? If you let the compiler allocate a variable, the parent's copy and the >child's copy will have the same value at the start, but if you change it, you >will have to change it in both places. If you allocated it at runtime >(malloc), then the pointers will have the same value (map to the same shared >memory). Thus, if you change a value in the child or the parent, the other's >copy is also instantly changed.
Sorry, I think that is not right: the adress space of a process is always contigous in Unix. From the process viewpoint, it starts always at the (virtual) adress 0 and ends at a certain value, the brk value. Malloced areas live within this range and the memory needed for them is claimed by moving the brk value with the brk() or sbrk() system calls. (There is no malloc system call in Unix - it is a library procedure, which calls sbrk() if needed). If a process forks the whole area between 0 and the current brk value is copied to a free (real) memory block, and the mmu is programmed to treat this as the child's adress space, i.e., although the childs runs at a different (real) memory address, all virtual adresses remain the same, but the memory cells they refer to are not identical with the memory cells the parent refers to if it reads or writes the same virtual address. As a result, the whole adress space of a process is local and never shared with anyone else. You need an advanced Unix version with shared memory and have to learn some new system calls to get shared memory.
As I wrote this posting I discovered, that the handling of stack space does not fit well into this scheme. As far as I know, there is no procedure in Unix Systems to let you divide the data segment of a process into a upward growing data area used for malloc and a downward growing stack area. So how this is done in real Unix ? I guess, that every process gets the whole maximum virtual adress space granted in the following manner:
The stack pointer initially starts at the highest possible virtual adress (determined by hardware memory size and swap space), and grows downward. The rest of the process sits in the bottom of the virtual address space and occupies range 0 up to brk. The use of any address between brk and stack pointer is forbidden and causes a memory fault. Therefore the OS does not need to keep pages between brk and stack pointer anywhere (neither memory nor swap space), although the process has valid addresses within the whole possible virtual address space. Note that if the stack pointer moves across a page boundary into a not yet granted page, it can do this only in steps of 2, 4 or another fixed amount of bytes depending on the CPU used, so the mmu does not need to know, whether a page fault creating address has been created by a stack register. It only has to check, whether the illegal address is a valid extension of the stack space or an illegal gripe into neverland caused by a run away or improper assigned pointer.
This is a guess, and there are probably people around reading this who know what is really going in real Unix systems.
-- Olaf Schlueter, Sandkuhle 4-6, 2300 Kiel 1, Germany, Toppoint Mailbox e.V. {olaf,schl...@oski.toppoint.de, o...@tpki.toppoint.de Troubadix: "Nein, Madame, Bardinnen, die gibt es nicht, wenn ueberhaupt, dann Bardamen"
o...@oski.toppoint.de (Olaf Schlueter) writes: >Sorry, I think that is not right: the adress space of a process is >always contigous in Unix. From the process viewpoint, it starts always >at the (virtual) adress 0 and ends at a certain value, the brk value. >Malloced areas live within this range and the memory needed for them is >claimed by moving the brk value with the brk() or sbrk() system calls. >(There is no malloc system call in Unix - it is a library procedure, >which calls sbrk() if needed). If a process forks the whole area >between 0 and the current brk value is copied to a free (real) memory >block, and the mmu is programmed to treat this as the child's adress >space,
Yes (of course the stack is copied, too). Some of the newer Unices avoid copying the whole data segment by revoking write permissions on it and copying only those pages one of the processes tries to write to.
>The stack pointer initially starts at the highest possible virtual adress >(determined by hardware memory size and swap space), and grows downward.
usually it starts at a fixed address (0x7FFFFFFF).
>The rest of the process sits in the bottom of the virtual address space >and occupies range 0 up to brk. The use of any address between brk and >stack pointer is forbidden and causes a memory fault. Therefore the OS >does not need to keep pages between brk and stack pointer anywhere >(neither memory nor swap space), although the process has valid >addresses within the whole possible virtual address space.
This is correct. 32-bit Unixes usually divide the address space of a process into four areas of 1GB each (because of the architecture of the VAX MMU): text- and data segment. user stack kernel text and data kernel stack.
The kernel area can only be accessed in supervisor mode.
-- | _ | Peter J. Holzer | Think of it | | |_|_) | Technical University Vienna | as evolution | | | | | Dept. for Real-Time Systems | in action! | | __/ | h...@vmars.tuwien.ac.at | Tony Rand |
h...@vmars.tuwien.ac.at (Peter Holzer) writes: >Of course, if you don't have an MMU (like the Atari ST), you have to >use all sorts of evil tricks to emulate one (like physically copying >lots of memory on context switches -- BTW, I always wondered how much >slower the average program would become if it did all pointer >arithmetic relative to a base pointer instead of absolute).
It has been considered in the past to modify the compiler so that it would access all variables relative to the pc or so, using offsets. (e.g. -30(pc)). However since the offset is limited to 16 bits, this would effectively limit the program size to 32k (or perhaps 64k with some tricks). I don't think such a limit is wanted.
Instead using shadowing is chosen.
Of course you can always dynamically calculate all addresses relative to either a base pointer or the PC, but that will require a calculation of the kind move.l base_ptr,a0 add.l #address,a0 move.l (a0),destination for all variable accesses and subroutine calls. I don't think a system with such an overhead would be acceptable. Not by me anyway. -- Frans Meulenbroeks (meule...@prl.philips.nl) Philips Research Laboratories