Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I've this code that executes some code depending of if the active process is the parent or the child process in an infinite loop:
pid_t childPID;
childPID=fork();
while (1)
{
if (childPID >=0)
{
if (childPID==0)
{
[do child process stuff]
}
else
{
[do parent process stuff]
}
}
else
{
printf("\n Fork failed, quitting!!!!!\n");
return 1;
}
}
Code is simple but there's one very big thing on it for me which I don't understand how it happens although I have a guess:
If not taking into consideration that we're creating 2 processes it looks like childPid is constantly being reasigned which I don't think makes any sense.
So my guess, is that fork creates a childPid for each process, returning a 0 to the parent process and the pid to the child process, even though this syntax makes me think it should only return only one result and assign it to chilPid.
Is my guess correct or is there some other thing involved?
Thank you.
So my guess, is that fork creates a childPid for each process, returning a 0 to the parent process and the pid to the child process, even though this syntax makes me think it should only return only one result and assign it to chilPid.
Exactly that. From the fork reference manual:
RETURN VALUE:
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
so
Is my guess
Why guess if this is precisely defined in the POSIX specification?
From fork(2) linux man page:
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately
So childPID is 0 in the child process and is child's pid in parent's process
What fork does is to create a new copy of the actual process to be the child process.
The childPID=fork(); is evalueated in both processes and it returns one and only one value, the trick is that the value is different depending on which of the process is executed. On the parent process it returns the PID of the new process (child), and on the child process returns 0, if fork wasn't succesful returns -1 adn the child process is never created
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
For(i=0, i<3, i++){
Fork()
}
Hello, this Code creates 5 process.
How can i create only 3 processes ?
Or how do i create only Child processes ?
Thank you
When you create a fork, both the parent and the newly created child process continue from the point of forking. So, if you have a loop running three times with fork, the parent creates three children, the first child creates two children, and so on. So, your example will result in more than five processes.
When a fork is created, you can record the pid (process ID). In the child process, the pid value of itself will be 0, while the parent process will have the child's pid stored. You can use this to control subsequent forks.
To create three processes, you can use:
pid_t pid;
pid = fork();
// this will be true only in the child process
// so, only the child creates another process, resulting in a total of
// three processes
if (pid == 0) {
fork();
}
After the first call to fork(), both the parent and the child process are executing the for-loop, so both of them execute the second call to fork, and now you have more processes than you wanted. To fix this you need to make the child do something different than the parent. You can tell which process is which by looking at the return value of fork; it returns 0 in the child and a nonzero value in the parent. So, something like this:
fflush(0); // not directly relevant but always a good idea before forking
for (int i = 0; i < 3; i++) {
if (fork() == 0) {
_exit(main_for_child(i)); // very important to use _exit, not exit
}
// control reaches this point only in the parent
}
This question already has answers here:
How is it possible for fork() to return two values?
(5 answers)
Closed 7 years ago.
I've decided to learn C, and here is the snippet from one of the books that I use:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result = fork();
if (result == -1){
fprintf(stderr, "Error\n");
return 1;
}
if (result == 0)
printf("I'm a child with PID = %d\n", getpid());
else
printf("I'm a parent with PID = %d\n", getpid());
return 0;
}
Its output is:
I'm a parent with PID = 5228
I'm a child with PID = 5229
Everything's clear, but how could it be that result == 0 and result != 0 at the same time? It looks like this variable stores two values, because the printf instruction is executed twice. I know, that fork() returns 0 and a parent's PID, but how does result check if it returns true for different conditions?
Because it's not the same variable. When you fork a process, you end up with two totally different processes (see this answer for more detail).
Hence the result variable in the parent is not the same as the one in the child. What you're seeing is two processes, both attached to the same output device, each writing their own message.
In fact, the fork documentation specifically covers that:
On success, the PID of the child process is returned in the parent, and 0 is returned in the child.
So you can use the return value from fork (as you do) to see if you're the parent or child (and to see if it worked as well, it'll return -1 if it fails and you'll be the parent with no child).
The idea is that the parent gets the process ID of the child so it can do something with it (like wait() for it to finish) and the child gets zero. The child can always get the process ID of the parent by calling getppid().
A variable can only hold a single value at a time. What you're seeing is happening because fork() is creating another process: there's now two instances of your program running; one in which result == 0 (the spawned process), and another where result != 0 (the original process)
fork replicates a child from a parent. So the newly created child inherits several properties like shared memory, message queue, file streams etc from the parent. So when you call fork, another process with another variable result is created.
The fork() function create a new process, after this line your program split to 2 from that spot. Because you need to know which process are you, the function return 0 if you are the child process, and some pid if you are the father process.
from the man page:
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
fork() function will create a new process. in parent process, fork() will return the pid of child process, so "result" variable will not equal with 0, and in child process, fork() just return 0, so "result" is 0.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm forking, and executing a certain block in the child process. My problem is that my child process never gets into the if statement. Why is this?
if((x = strcmp(subargs[next_redirect], ">")) == 0)
{
pid = fork();
fprintf(stderr, "my PID is %i\n", pid);
if(pid == 0)
{
fprintf(stderr, "the name of our file is %s\n", subargs[i+1]);
fp = creat(subargs[i+1], S_IWUSR | S_IRUSR);
dup2(fp, STDOUT_FILENO);
close(fp);
//create sub-command
makesubcommand(subcommand, subargs, last_redirect + 1, i);
execvp(subcommand[0], subcommand);
}
last_redirect = i;
next_redirect = getnextredirect(subargs, i+2, subargc);
}
My output is
my PID is 11080
my PID is 0
When you fork, the child process receives a PID of 0, correct?
My problem is at if(pid == 0){}. The code in that block never executes.
Your child process is not getting to if because of wait() system call.
The system call wait() blocks the calling process until one of its child processes exits or a signal is received.wait() takes the address of an integer variable and returns the process ID of the completed process. Some flags that indicate the completion status of the child process are passed back with the integer pointer. One of the main purposes of wait() is to wait for completion of child processes.
The execution of wait() could have two possible situations.
If there are at least one child processes running when the call to wait() is made, the caller will be blocked until one of its child processes exits. At that moment, the caller resumes its execution.
If there is no child process running when the call to wait() is made, then this wait() has no effect at all. That is, it is as if no wait() is there.
So remove the wait() system call. and your program will run ok.
Check the call of execvp in your code, which may have errors. You can check the return value of wait to get the child pid or -1.
Apologies. It turns out that my problem was
fprintf(stderr, "the name of our file is %s\n", subargs[i+1]);
I was left thinking that the block was never executed because this wouldn't print anything.
it turns out that there is a problem with subargs.
I appreciate all the help.
Currently, I am doing some exercises on operating system based on UNIX. I have used the fork() system call to create a child process and the code snippet is as follows :
if(!fork())
{
printf("I am parent process.\n");
}
else
printf("I am child process.\n");
And this program first executes the child process and then parent process.
But, when I replace if(!fork()) by if(fork()!=0) then the parent block and then child block executes.Here my question is - does the result should be the same in both cases or there is some reason behind this? Thanks in advance!!
There is no guaranteed order of execution.
However, if(!fork()) and if(fork()!=0) do give opposite results logically: if fork() returns zero, then !fork() is true whilst fork()!=0 is false.
Also, from the man page for fork():
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
So the correct check is
pid_t pid = fork();
if(pid == -1) {
// ERROR in PARENT
} else if(pid == 0) {
// CHILD process
} else {
// PARENT process, and the child has ID pid
}
EDIT: As Wyzard says, you should definitely make sure you make use of pid later as well. (Also, fixed the type to be pid_t instead of int.)
You shouldn't really use either of those, because when the child finishes, it'll remain as a zombie until the parent finishes too. You should either capture the child's pid in a variable and use it to retrieve the child's exit status:
pid_t child_pid = fork();
if (child_pid == -1)
{
// Fork failed, check errno
}
else if (child_pid)
{
// Do parent stuff...
int status;
waitpid(child_pid, &status, 0);
}
else
{
// Child stuff
}
or you should use the "double-fork trick" to dissociate the child from the parent, so that the child won't remain as a zombie waiting for the parent to retrieve its exit status.
Also, you can't rely on the child executing before the parent after a fork. You have two processes, running concurrently, with no guarantee about relative order of execution. They may take turns, or they may run simultaneously on different CPU cores.
The order in which the parent and child get to their respective printf() statements is undefined. It is likely that if you were to repeat your tests a large number of times, the results would be similar for both, in that for either version there would be times that the parent prints first and times the parent prints last.
!fork() and fork() == 0 both behave in the same way.
The condition itself cannot be the reason the execution sequence is any different.
The process is replicated, which means that child is now competing with parent for resources, including CPU. It is the OS scheduler that decides which process will get the CPU.
The sequence in which child and parent processes are being execute is determined by the scheduler. It determines when and for how long each process is being executed by the processor. So the sequence of the output may vary for one and the same program code. It is purely coincidental that the change in the source code led to the change of the output sequence.
By the way, your printf's should be just the other way round: if fork() returns 0, it's the child, not the parent process.
See code example at http://en.wikipedia.org/wiki/Fork_%28operating_system%29. The German version of this article (http://de.wikipedia.org/wiki/Fork_%28Unix%29) contains a sample output and a short discusion about operation sequence.
Is the child, after the fork, start the program from the beginning or from the place of is parent?
for example, it this program, is the child start from line 1 or line 3?
int i=1
fork()
i=i*2
fork
i=i*2
fork() creates a new process by duplicating the calling process.
The new process, referred to as the child, is an exact duplicate of
the calling process, referred to as the parent, except for the
following points: […]
from fork(2)
As it is an exact duplicate, it will also have the same instruction pointer and stack. So the child will be right after the call to fork(). Now, you may ask, how do I find out whether the current program is the child or the parent? See the manpage on the return value:
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
So if the result of fork() is equal to 0, you're in the child process, if its greater than 0 you're in the parent and if its below 0 you're in trouble.
Please note that this implies that every code which is independent of the result value of fork(), will be executed in both the child and the parent. So if you're for example creating a pool with 16 processes, you should be doing:
for (int i = 0; i < 16; i++) {
pid_t pid = fork()
if (pid == 0) {
do_some_work();
exit(0);
} else if (pid < 0) {
// fork failed
do_some_error_handling();
}
}
If you miss the exit(0), you'll spawn 2¹⁶-1 processes (been there, just with 100 instead of 16. No fun.)
The fork starts from line 3, the point where the fork occurred.
When fork returns, it returns in both the parent (returning the PID of the child) and the child (returning 0). Execution continues from there in both the parent and the child.
As such, typical use of fork is something like:
if (0 == (child = fork()))
// continue as child.
else
// Continue as parent.
The Child will be created at line 2 i.e., fork() but it will start its execution from the line 3 i.e., i = i*2. What confuses me here is your line 4. What are you trying to do there?