In the early days ( late 1990's ) uClinux was scorned by a few because , without a MMU, it could not do a true fork.

The fork system call is the mechanism by which every single UNIX process normally gets started.
Every process is, in fact, a clone of the first process started by the booting kernel.

A fork produces a parent and child. Each have individual task control structures and each can be scheduled independently by the kernel.
When we have an MMU the parent and child eventually occupy different physical memory spaces. The MMU maps different physical memory addresses to identical virtual memory addresses and copies the data from parent to child. Under Linux this happens when either process attepmts to write to a shared physical memory area.

On a typical system this cloneing can work because immediately after the fork the child replaces the parent's program with a new executable.
Sometimes the parent and child are supposed to be identical at first but operating on different data.

uClinux does not have the functionality of a true fork. It does have a close cousin the vfork system call.

When a vfork system call is made the parent task is halted (put in a wait queue and suspend it) and a new task control block created using the same text memory, stack, and data memory as the parent. The new child then has to replace its program and data areas with an execve call or it has to exit before the parent is allowed to continue.

The execve system call is one of a series of exec system calls that all have different arrangements of arguments and envronment variables.

Try this
man 2 execl

The purpose of this call is to use the same kernel space task control block but run a different program under that control block. The text and data are read from an executable file specified in one of the arguments and the new program starts from the defined start location specified in the new executable.

Once the new program memory has been established the parent task is released.

The simpleinit program ( which is the first user code executed by the kernel after boot) is given the job of running all the initial programs required by the system.

Here is an extract where it is booting to single user mode and trying to run a shell
program.

// part of the "boot to single user "code
av[0]= _PATH_BSHELL;// /bin/sh
av[1]= NULL;if((pid = vfork())==0){// pid = 0 in the childexternchar**environ;/* the child */
execve(_PATH_BSHELL, av, environ);// if this works parent is released
err("exec of single user shell failed\n");
_exit(0);// if execve failed exit releases parent}elseif(pid >0){int i;// this is the parentwhile(wait(&i)!= pid)/* nothing */;}elseif(pid <0){
err("fork of single user shell failed\n");}//parent continues, the child has execve'd a new program.

The inetd internet daemon is given the task of monitoring a number of internet sockets and waiting for a connection on one of them.
When a connection is established the daemon has to fork a new process to handle the connection. The /etc/inetd.conf file contains details of the ports to be monitored and the programs used to handle incoming connections.

Example /etc/inetd.conf file

Having established a connection attempt on a designated port the daemon is required to
start executing the handler task for that connection.
The complication here is that the child has to have the incoming socket as its stdin and stdout devices.

The incoming port (fd in this case ) is transferred to stdin and stdout of the new task after the vfork.

Consider this code from thttpd.c ( in directory user/thttpd/ ) which shows the modification made to the MMUfull version of this code to make it run as a foreground process , skipping the daemonize fork

There are a few. You have to fork and you originally ( in MMUfull world) wanted an exact copy of yourself.

These are the problem cases. Normally you can save important data in environment variables
and then restart yourself in a call to execve using a command line argument to select the child mode of operation.

The new child task will detect that it is functioning in child mode and restore the needed data from environment variables and continue.