The main reason is that the separation of the fork() and exec() steps allows arbitrary configuration of the child environment to make other system calls. For example, you can:
- Setting up an arbitrary set of open file descriptors;
- Change signal mask;
- Set the current working directory;
- Establish a process group and / or session;
- Set user, group and additional groups;
- Set hard and soft resource limits;
... and much more. If you combined these calls into a single spawn() call, it had to have a very complex interface so that it could code all these possible changes in the child environment - and if you ever added a new parameter, the interface had to be changed. On the other hand, the separate fork() and exec() steps allow you to use regular system calls ( open() , close() , dup() , fcntl() , ...) to control the child environment before exec() . New functionality (e.g. capset() ) is easily supported.
caf
source share