Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ATARI ST MINIX - how does it cope with fork()?

24 views
Skip to first unread message

Robert Walsh

unread,
Oct 20, 1991, 5:02:13 PM10/20/91
to

Say I do this on the Atari ST version on Minix...

main(){
...
fred(&a);
...
}

fred(a)
int *a;
{
...
if(fork()==0){
...
printf("%d\n",*a);
...
}
...
}

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: rjw...@unix2.tcd.ie
Engineering School, Trinity College Dublin.
-----------------------------------------------------------

Christoph van Wuellen

unread,
Oct 21, 1991, 8:01:23 AM10/21/91
to
On the 68000, a process is physically copied upon fork(), and the images
are interchanged upon task switch. This is called shadowing.

C.v.W.

Kevin Benton

unread,
Oct 21, 1991, 8:22:00 AM10/21/91
to
On <Oct 20 21:02>, Robert Walsh (rjw...@unix2.tcd.ie ) confesses:

R>Organization: Trinity College, Dublin
R>Message-ID: <rjwalsh....@unix2.tcd.ie>
R>Newsgroups: comp.sys.atari.st.tech,comp.os.minix


R> Say I do this on the Atari ST version on Minix...

R>main(){
R> ...
R> fred(&a);
R> ...
R>}

R>fred(a)
R>int *a;
R>{
R> ...
R> if(fork()==0){
R> ...
R> printf("%d\n",*a);
R> ...
R> }
R> ...
R>}

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!

Peter Holzer

unread,
Oct 22, 1991, 4:10:33 PM10/22/91
to
s1k...@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.

The page table might then look like

Vir addr phys addr perm

0000 - ---
0400 C000 r-x
0800 C400 r-x
0C00 B400 rw-
1000 B800 rw-
1400 BC00 rw-
1800 - ---
...
7800 - ---
7C00 C400 rw-

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:

0000 - ---
0400 C000 r-x
0800 C400 r-x
0C00 D400 rw-
1000 DC00 rw-
1400 E000 rw-
1800 - ---
...
7800 - ---
7C00 E400 rw-

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 |

Olaf Schlueter

unread,
Oct 22, 1991, 9:19:43 AM10/22/91
to
s1k...@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,schlut}@oski.toppoint.de, ol...@tpki.toppoint.de
Troubadix: "Nein, Madame, Bardinnen, die gibt es nicht, wenn ueberhaupt,
dann Bardamen"

Peter Holzer

unread,
Oct 24, 1991, 10:09:13 AM10/24/91
to
ol...@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.

Frans Meulenbroeks

unread,
Oct 23, 1991, 8:21:21 AM10/23/91
to
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 (meul...@prl.philips.nl)
Philips Research Laboratories

0 new messages