When using fork(), is it possible to ensure that the child process executes before the parent without using wait() in the parent?
This is related to a homework problem in the Process API chapter of Operating Systems: Three Easy Pieces, a free online operating systems book.
The problem says:
Write another program using fork(). The child process should
print "hello"; the parent process should print "goodbye". You should
try to ensure that the child process always prints first; can you do
this without calling wait() in the parent?
Here's my solution using wait():
#include <stdio.h>
#include <stdlib.h> // exit
#include <sys/wait.h> // wait
#include <unistd.h> // fork
int main(void) {
int f = fork();
if (f < 0) { // fork failed
fprintf(stderr, "fork failed\n");
exit(1);
} else if (f == 0) { // child
printf("hello\n");
} else { // parent
wait(NULL);
printf("goodbye\n");
}
}
After thinking about it, I decided the answer to the last question was "no, you can't", but then a later question seems to imply that you can:
Now write a program that uses wait() to wait for the child process
to finish in the parent. What does wait() return? What happens if
you use wait() in the child?
Am I interpreting the second question wrong? If not, how do you do what the first question asks? How can I make the child print first without using wait() in the parent?
I hope this answer is not too late.
Minutes ago, I have emailed Remiz(this book's author), and got such a replay(extract some segments):
Without calling wait() is hard, and not really the main point.
What you did -- learning about signals on your own -- is a good sign,
showing you will seek out deeper knowledge. Good for you!
Later, you'll be able to use a shared memory segment, and
either condition variables or semaphores, to solve this problem.
Create a pipe in the parent. After fork, close the write half in the parent and the read half in the child.
Then, poll for readability. Since the child never writes to it, it will wait until the child (and all grandchildren, unless you take special care) no longer exists, at which time poll will give a "read with hangup" response. (Alternatively, you could actually communicate over the pipe).
You should read about O_CLOEXEC. As a general rule, that flag should always be set unless you have a good reason to clear it.
I can't see why second question would imply that answer is "yes" to the first.
Yes there is plenty of solutions to obtain what asked, but of course I suspect that all are not in the "spirit" of the problem/question where the focus in on fork/wait primitives. The point is always to remember that you can't assume anything after a fork regarding the way processes ran relatively to each other.
To ensure the child process print first you need a kind of synchronization in between both processes, and there is a lot of system primitives that have a semantic of "communication" between processes (for example locks, semaphores, signals, etc). I doubt one of these is to be used her, as they are generally introduced slightly later in such a course.
Any other attempt only that will only rely on time assumption (like using sleep or loops to "slow" down the parent, etc) can lead to failure, means that you will not be able to prove that it will always succeed. Even if testing would probably show you that it seems correct, most of the runs you would try will not have the bad characteristics that lead to failure. Remember that except in realtime OSes, scheduling is almost an approximation of fair concurrency.
NOTE:
As Jonathan Leffler commented, I also suppose that using other wait-like primitives is forbidden (aka wait4, waitpid, etc) -- "spirit" argument.
I'm not sure whether this is against the spirit of the question, but I think that calling the pause system call in the parent process branch will cause the scheduler to immediately run the child process (if it didn't already run).
#include <unistd.h>
#include <stdio.h>
int main(){
fork();
return 0;
}
In my understanding, fork() will copy the parent's process, and run it as a child process; if that was the case, would the program above break? Because how I am understanding this program is: the program above will call fork() indefinitely, and eventually cause a Stack Overflow.
According to the POSIX specification:
Both processes shall continue to execute from the fork() function.
So, both processes will continue after the call to fork(), and both will immediately terminate.
The fork call does not make either the child or the parent process go back to the beginning of main and start over. It returns like a normal function, but it does it twice, once in the child and once in the parent, with different return values so you can tell which is which.
So, in your program, fork succeeds and then both processes go on to the return 0 and exit. Nothing bad will happen.
A variation will cause problems, though:
#include <unistd.h>
int
main(void)
{
for (;;)
fork();
/* not reached */
}
This is called a "fork bomb". Because it calls fork inside an infinite loop, never checking whether it's the parent or the child, the original process becomes two processes, and then four, and then eight, and ... until you run out of RAM, or at least process IDs. And it doesn't check for failure either, so it doesn't stop after the fork calls start failing. All of these processes will continue chewing up CPU forever, and none of the other programs running on the computer will be able to make forward progress.
Back in the days of mammoths and SunOS 4 it was even worse than that, a fork bomb would be liable to tickle a kernel bug and outright crash the minicomputer, and then the BOFH would come looking for you and he or she would not be happy. I would expect a modern kernel not to crash, and you might even be able to kill off the entire exponential process tree with control-C, but I'm not going to try it just to find out.
Incidentally, return_type whatever() is bad style in C, because for historical reasons it means whatever takes any number of arguments. Always write return_type whatever(void) instead.
Consider:
int main()
{
if (fork() == 0){
printf("a");
}
else{
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
(from Computer Systems, Bryant - O'Hallaron).
We are asked for all the possible output sequences.
I answered: acbc, abcc, bacc.
However, I am missing one output compared to the solution (bcac). I thought this output was not possible because the parent process waits for its child to return before printing c (waitpid). Is this not true? Why? And, in that case, what is the difference between the code above and the same without the waitpid line?
I don't see any way bcac is possible. At first I expected some trickery based on the stdio buffers being flushed in an unexpected order. But even then:
The child won't output c until after it has output a. Therefore the first c in bcac must have come from the parent.
The parent won't output c until after the waitpid completes. But that can't happen until after the child is finished, including the final stdio flush that happens during exit(). Therefore the first c is always from the child.
Proof by contradiction has been achieved... the output can't be bcac.
Well, there is one thing you could do to mess up the order. You could exec the program inside a process that already has a child which is about to exit. If the pre-existing child exits before the new child prints a, then the main process will detect that exit with waitpid, and go ahead and print its stuff and possibly exit before the child prints anything.
This is something to watch out for in setuid programs: don't assume that because your program only created one child process that it only has one child process. If you're in an advanced defensive-code learning context this answer makes sense. In a unix-newbie context it doesn't seem relevant, and it's probably better to just say bcac is impossible, even though it's technically not true.
It's tricky, but the call to waitpid can be interrupted (returns -1 and errno is EINTR). In this case the parent can output c before the child outputs anything and bcac is possible.
To prevent bcac from occurring, either a signal mask needs to be set, or, better, the waitpid return value is checked and if it was interrupted gets called again.
Sorry for this, just can't seem to make sense of what is going on in this little piece of C :
#include <stdio.h>
main()
{
int i;
if (fork()) { /* must be the parent */
for (i=0; i<1000; i++)
printf("\t\t\tParent %d\n", i);
}
else { /* must be the child */
for (i=0; i<1000; i++)
printf("Child %d\n", i);
}
}
As I understand it, it will print child 1000 times and parent 1000 times, but apparently it is much more complex and I must fully understand it ! Would anyone please be able to explain it to me ? Also, how would I change the program such that the parent and the child execute different computation?
Thanks a lot for your help with this :)
fork() creates a new process. So from that point on, there will be two separate processes that both continue from the point of code where the fork() was. In the main process fork() returns the PID of the new child process and in the child process it returns zero. So the code will execute different branches of the if statement in different processes.
Please also remember that new process is not the same thing as thread. Those processes won't have any global variables or similar things in common but they are completely separate. But they otherwise they are identical.
The fork() function spawns a new process, with an exact copy of the memory of the original "parent" process. Both processes continue to execute from the same point, but fork() returns 0 for the child, and non-zero for the parent. So the parent executes the first loop, and the child executes the second loop.
Note that as there is nothing synchronising the parent and the child, the order that you see the strings displayed on screen will be essentially random.
The fork() function generates what is called a child process. The child process is a clone of the process that called fork() in the first place. It even starts executing at the same place the parent process left off, which is right after calling fork().
The only difference is that fork() will return true (or zero) for the parent process and false (or non-zero) for the child process. That means the parent process, after calling fork(), will execute the first part of the conditional. The child process will start executing the second part of the conditional.
Each one will print 1000 times as they are scheduled by the operating system, and each will eventually terminate when they reach the end of the main method.
In many programs and man pages of Linux, I have seen code using fork(). Why do we need to use fork() and what is its purpose?
fork() is how you create new processes in Unix. When you call fork, you're creating a copy of your own process that has its own address space. This allows multiple tasks to run independently of one another as though they each had the full memory of the machine to themselves.
Here are some example usages of fork:
Your shell uses fork to run the programs you invoke from the command line.
Web servers like apache use fork to create multiple server processes, each of which handles requests in its own address space. If one dies or leaks memory, others are unaffected, so it functions as a mechanism for fault tolerance.
Google Chrome uses fork to handle each page within a separate process. This will prevent client-side code on one page from bringing your whole browser down.
fork is used to spawn processes in some parallel programs (like those written using MPI). Note this is different from using threads, which don't have their own address space and exist within a process.
Scripting languages use fork indirectly to start child processes. For example, every time you use a command like subprocess.Popen in Python, you fork a child process and read its output. This enables programs to work together.
Typical usage of fork in a shell might look something like this:
int child_process_id = fork();
if (child_process_id) {
// Fork returns a valid pid in the parent process. Parent executes this.
// wait for the child process to complete
waitpid(child_process_id, ...); // omitted extra args for brevity
// child process finished!
} else {
// Fork returns 0 in the child process. Child executes this.
// new argv array for the child process
const char *argv[] = {"arg1", "arg2", "arg3", NULL};
// now start executing some other program
exec("/path/to/a/program", argv);
}
The shell spawns a child process using exec and waits for it to complete, then continues with its own execution. Note that you don't have to use fork this way. You can always spawn off lots of child processes, as a parallel program might do, and each might run a program concurrently. Basically, any time you're creating new processes in a Unix system, you're using fork(). For the Windows equivalent, take a look at CreateProcess.
If you want more examples and a longer explanation, Wikipedia has a decent summary. And here are some slides here on how processes, threads, and concurrency work in modern operating systems.
fork() is how Unix create new processes. At the point you called fork(), your process is cloned, and two different processes continue the execution from there. One of them, the child, will have fork() return 0. The other, the parent, will have fork() return the PID (process ID) of the child.
For example, if you type the following in a shell, the shell program will call fork(), and then execute the command you passed (telnetd, in this case) in the child, while the parent will display the prompt again, as well as a message indicating the PID of the background process.
$ telnetd &
As for the reason you create new processes, that's how your operating system can do many things at the same time. It's why you can run a program and, while it is running, switch to another window and do something else.
fork() is used to create child process. When a fork() function is called, a new process will be spawned and the fork() function call will return a different value for the child and the parent.
If the return value is 0, you know you're the child process and if the return value is a number (which happens to be the child process id), you know you're the parent. (and if it's a negative number, the fork was failed and no child process was created)
http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
fork() is basically used to create a child process for the process in which you are calling this function. Whenever you call a fork(), it returns a zero for the child id.
pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process
by this you can provide different actions for the parent and the child and make use of multithreading feature.
fork() will create a new child process identical to the parent. So everything you run in the code after that will be run by both processes — very useful if you have for instance a server, and you want to handle multiple requests.
System call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of fork():
If fork() returns a negative value, the creation of a child process was unsuccessful.
fork() returns a zero to the newly created child process.
fork() returns a positive value, the process ID of the child process, to the parent. The returned process ID is of type pid_t defined in sys/types.h. Normally, the process ID is an integer. Moreover, a process can use function getpid() to retrieve the process ID assigned to this process.
Therefore, after the system call to fork(), a simple test can tell which process is the child. Please note that Unix will make an exact copy of the parent's address space and give it to the child. Therefore, the parent and child processes have separate address spaces.
Let us understand it with an example to make the above points clear. This example does not distinguish parent and the child processes.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
}
Suppose the above program executes up to the point of the call to fork().
If the call to fork() is executed successfully, Unix will make two identical copies of address spaces, one for the parent and the other for the child.
Both processes will start their execution at the next statement following the fork() call. In this case, both processes will start their execution at the assignment
pid = .....;
Both processes start their execution right after the system call fork(). Since both processes have identical but separate address spaces, those variables initialized before the fork() call have the same values in both address spaces. Since every process has its own address space, any modifications will be independent of the others. In other words, if the parent changes the value of its variable, the modification will only affect the variable in the parent process's address space. Other address spaces created by fork() calls will not be affected even though they have identical variable names.
What is the reason of using write rather than printf? It is because printf() is "buffered," meaning printf() will group the output of a process together. While buffering the output for the parent process, the child may also use printf to print out some information, which will also be buffered. As a result, since the output will not be send to screen immediately, you may not get the right order of the expected result. Worse, the output from the two processes may be mixed in strange ways. To overcome this problem, you may consider to use the "unbuffered" write.
If you run this program, you might see the following on the screen:
................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
................
Process ID 3456 may be the one assigned to the parent or the child. Due to the fact that these processes are run concurrently, their output lines are intermixed in a rather unpredictable way. Moreover, the order of these lines are determined by the CPU scheduler. Hence, if you run this program again, you may get a totally different result.
You probably don't need to use fork in day-to-day programming if you are writing applications.
Even if you do want your program to start another program to do some task, there are other simpler interfaces which use fork behind the scenes, such as "system" in C and perl.
For example, if you wanted your application to launch another program such as bc to do some calculation for you, you might use 'system' to run it. System does a 'fork' to create a new process, then an 'exec' to turn that process into bc. Once bc completes, system returns control to your program.
You can also run other programs asynchronously, but I can't remember how.
If you are writing servers, shells, viruses or operating systems, you are more likely to want to use fork.
Multiprocessing is central to computing. For example, your IE or Firefox can create a process to download a file for you while you are still browsing the internet. Or, while you are printing out a document in a word processor, you can still look at different pages and still do some editing with it.
Fork creates new processes. Without fork you would have a unix system that could only run init.
Fork() is used to create new processes as every body has written.
Here is my code that creates processes in the form of binary tree.......It will ask to scan the number of levels upto which you want to create processes in binary tree
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
int t1,t2,p,i,n,ab;
p=getpid();
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);
printf("root %d\n",p);fflush(stdout);
for(i=1;i<n;i++)
{
t1=fork();
if(t1!=0)
t2=fork();
if(t1!=0 && t2!=0)
break;
printf("child pid %d parent pid %d\n",getpid(),getppid());fflush(stdout);
}
waitpid(t1,&ab,0);
waitpid(t2,&ab,0);
return 0;
}
OUTPUT
enter the number of levels
3
root 20665
child pid 20670 parent pid 20665
child pid 20669 parent pid 20665
child pid 20672 parent pid 20670
child pid 20671 parent pid 20670
child pid 20674 parent pid 20669
child pid 20673 parent pid 20669
First one needs to understand what is fork () system call. Let me explain
fork() system call creates the exact duplicate of parent process, It makes the duplicate of parent stack, heap, initialized data, uninitialized data and share the code in read-only mode with parent process.
Fork system call copies the memory on the copy-on-write basis, means child makes in virtual memory page when there is requirement of copying.
Now Purpose of fork():
Fork() can be used at the place where there is division of work like a server has to handle multiple clients, So parent has to accept the connection on regular basis, So server does fork for each client to perform read-write.
fork() is used to spawn a child process. Typically it's used in similar sorts of situations as threading, but there are differences. Unlike threads, fork() creates whole seperate processes, which means that the child and the parent while they are direct copies of each other at the point that fork() is called, they are completely seperate, neither can access the other's memory space (without going to the normal troubles you go to access another program's memory).
fork() is still used by some server applications, mostly ones that run as root on a *NIX machine that drop permissions before processing user requests. There are some other usecases still, but mostly people have moved to multithreading now.
The rationale behind fork() versus just having an exec() function to initiate a new process is explained in an answer to a similar question on the unix stack exchange.
Essentially, since fork copies the current process, all of the various possible options for a process are established by default, so the programmer does not have supply them.
In the Windows operating system, by contrast, programmers have to use the CreateProcess function which is MUCH more complicated and requires populating a multifarious structure to define the parameters of the new process.
So, to sum up, the reason for forking (versus exec'ing) is simplicity in creating new processes.
Fork() system call use to create a child process. It is exact duplicate of parent process. Fork copies stack section, heap section, data section, environment variable, command line arguments from parent.
refer: http://man7.org/linux/man-pages/man2/fork.2.html
Fork() was created as a way to create another process with shared a copy of memory state to the parent. It works the way it does because it was the most minimal change possible to get good threading capabilities in time-slicing mainframe systems that previously lacked this capability. Additionally, programs needed remarkably little modification to become multi-process, fork() could simply be added in the appropriate locations, which is rather elegant. Basically, fork() was the path of least resistance.
Originally it actually had to copy the entire parent process' memory space. With the advent of virtual memory, it has been hacked and changed to be more efficient, with copy-on-write mechanisms avoiding the need to actual copy any memory.
However, modern systems now allow the creation of actual threads, which simply share the parent process' actual heap. With modern multi-threading programming paradigms and more advanced languages, it's questionable whether fork() provides any real benefit, since fork() actually prevents processes from communicating through memory directly, and forces them to use slower message passing mechanisms.