I know that fork() creates a duplicate process (clone) meaning two identical copies of address spaces are created - one for the parent and one for the child. This process becomes child process of the caller. However, I am confused as to what is inside fork_rv (see comment in code below)
include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
int fork_rv;
printf("Before: my pid is %d\n",getpid());
fork_rv=fork();
if (fork_rv == -1)
perror("fork");
else if (fork_rv == 0)
printf ("I am the child. my pid=%d\n",getpid());
else
printf ("I am the parent. my child is %d\n",fork_rv); /* What is inside fork_rv What gets printed exactly? The address of the child?) */
}
Quoting from the Linux manual 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.
While #Brian's answer is already correct, maybe explaining the logic behind these return values makes it easier to understand:
-1 for error should be clear.
0 as value for the child process makes sense because the child process can always get its own pid (getpid()) as well as the pid of its parent process (getppid()).
All values > 0 are the pid of the new child process that was created, returned to the parent process. Since a process can have multiple child processes, a 'get child pid' function is not possible: The pid of which child should it return? And with a 'get children pids' function that would return a list of all child processes pids, it would be cumbersome to find the pid of the latest, new child process.
Related
My program has the following parent child layout:
int main() {
std::vector<pid_t> kids;
pid_t forkid = fork();
if (forkid == 0) {
//child process
pid_t fork2 = fork()
if (fork2 == 0) {
// child process
}else {
//parent
kids.push_back(fork2);
}
}else {
// code here
kids.push_back(forkid);
}
// Not killing the fork2 process - only the first process(forkid) is terminated
for (pid_t k : kids) {
int status;
kill(k, SIGTERM);
waitpid(k, &status, 0);
}
}
I am not able to kill the child process (fork2) - the first process gets terminated. The kids vector seems to only contain the process id of the first process. Never gets the pid of the child process.
What am I doing wrong here. Any help will be appreciated. Thanks.
std::vector<pid_t> kids;
pid_t forkid = fork();
fork() creates a complete duplicate image of the parent process as its child process. Emphasis on: duplicate.
This means that, for example, the child process has its very own kids vector, that has nothing to do, whatsoever, with the parent process's original kids vector.
Since this is the very first thing that happens in main, this is really no different than you running this executable twice, individually as two distinct and separate processes, instead of forking off a process. You can't expect the kids vector in one of the two processes to have any effect on the kids vector in the other one.
The first child process creates a 2nd child process, and also adds the 2nd child process's pid into its own kids vector. But that's just the first child process's kids vector.
The only process id that the original parent process's kids vector ends up having is the first child's process it, so that's all you get to SIGTERM.
Your options are:
Restructure your logic so that both child process get created by the parent process, so it, alone, puts their process ids into its kids vector.
Instead of using fork use multiple execution threads, and the same process. However, neither std::vector, nor any other C++ library container is thread safe. A massive pile of code will need to be written to properly synchronize the threads, in order for things to work themselves out correctly (not to mention that the analogue for the SIGTERM, with respect to multiple execution threads, needs to be invented in some way).
The simplest alternative is the first one.
Today, I wrote a small program in C++ like this:
pid_t pChild=0;
printf("Main process ID:%d\n",getpid());
pChild= fork();
printf("%d\n",pChild);
if (pChild!=0){
printf("Parent process ID:%d\n",getpid());
printf("Child process ID:%d\n",pChild);
}
else printf("Sorry! The child can not be created\n");
return 0;
And the output was like this
Main process ID: 3140
Sorry! The child can not be created
Parent process ID:3140
Child process ID:3141
And then, I wondered about the output.
I guessed the first getpid() of the child process didn't run because it read the same data with the getpid() from its parent; and this msg
Sorry! The child can not be created
It must be from the if statement of the child process. Correct me if I wrong...
But I still can't understand why the fork() function of the child's didn't run. Why it was blocked? Does it because they read the same pChild data (one of the fork() in child process and the other is main process's if-statement)?
Can anyone explain more detail about it? Thank you.
From the fork() documentation:
RETURN VALUE
Upon successful completion, fork() shall return 0 to the child process
and shall return the process ID of the child process to the parent process.
Your code assumes any zero return value is an error.
Continuing:
Both processes shall continue to execute from the fork() function.
Otherwise, -1 shall be returned to the parent process, no child
process shall be created, and errno shall be set to indicate the
error.
A -1 return value is an error indication.
I am trying to figure out why a child process is able to change a parent epoll state.
I have program that declare a static epoll object (an object that wraps epoll):
static EventManager* evMgrPtr = NULL;
The parent process initialized it and use it to watch a listening socket (The parent is basically a daemon that occasionally need to respond to health check request by accepting these request through the listening socket).
The children does totally different thing, however, the program DOES NOT do a fork/exec, rather, the children carry on and run a piece of code in the same translation unit.
pid_t pid = fork();
switch(pid) {
case -1:
YREPL_LOG_FATAL("Couldn't start server process ");
exit(EXIT_OK);
case 0:
#ifndef __FreeBSD__
assert( closeThisFd != -1 );
evMgr.unregisterSocketEvent( closeThisFd );
close( closeThisFd );
#endif
close(outpipe[0]);
close(errpipe[0]);
dup2(outpipe[1], 1);
dup2(errpipe[1], 2);
close(outpipe[1]);
close(errpipe[1]);
The problem is that after I do evMgrPtr->unregisterSocketEvent( closeThisFd ) in the child process, I found out the parent stop watching for the listening socket as well!!!
Can anyone shed some light on why this is happening. I thought once a fork is executed the parent and children will do COW. So whatever children does to its copy of the epoll object should not get reflected in the parent right?
It seems that you use EPOLL-based event loop. So, since file descriptor for epoll-object itself is shared between child and parent, removing file descriptor from epoll()-based descriptor in child also affects parent process :). Please read man epoll, man epoll_create.
I have a string (fileContents) in shared memory that consists of a 9 lines:
sprintf(shared_memory, fileContents.c_str());
I want to call on fork() to create the same number of processes as lines. These processes will manipulate each line. However, I have no idea where to start when calling fork(). Every example I have looked at just consists of returning the process ID of parents and child processes and not showing how or when the processes executes something.
Any guidance would be appreciated, thanks!
Every example I have looked at just consists of returning the process ID of parents and child processes
That's not correct.
The parent process will get the process id of the child process, but the child process will know it's the child process because fork() returns 0.
This code will fork 9 times, with each child doing specific work.
for( int line = 1; line <= 9; ++line ) // *cough*
{
if ( fork() == 0 )
{
// Child process. Handle line, and exit()
}
}
I have managed to fork and exec a different program from within my app. I'm currently working on how to wait until the process called from exec returns a result through a pipe or stdout. However, can I have a group of processes using a single fork, or do I have to fork many times and call the same program again? Can I get a PID for each different process ? I want my app to call the same program I'm currently calling many times but with different parameters: I want a group of 8 processes of the same program running and returning results via pipes. Can someone please point me to the right direction please ? I've gone through the linux.die man pages, but they are quite spartan and cryptic in their description. Is there an ebook or pdf I can find for detailed information ? Thank you!
pid_t pID = fork();
if (pID == 0){
int proc = execl(BOLDAGENT,BOLDAGENT,"-u","2","-c","walkevo.xml",NULL);
std::cout << strerror(errno) << std::endl;
}
For example, how can I control by PID which child (according to the parameter xml file) has obtained which result (by pipe or stdout), and thus act accordingly? Do I have to encapsulate children processes in an object, and work from there, or can I group them altogether?
One Fork syscall make only one new process (one PID). You should organize some data structures (e.g. array of pids, array of parent's ends of pipes, etc), do 8 fork from main program (every child will do exec) and then wait for childs.
After each fork() it will return you a PID of child. You can store this pid and associated information like this:
#define MAX_CHILD=8
pid_t pids[MAX_CHILD];
int pipe_fd[MAX_CHILD];
for(int child=0;child<MAX_CHILD;child++) {
int pipe[2];
/* create a pipe; save one of pipe fd to the pipe_fd[child] */
int ret;
ret = fork();
if(ret) { /* parent */
/* close alien half of pipe */
pids[child] = ret; /* save the pid */
} else { /* child */
/* close alien half of pipe */
/* We are child #child, exec needed program */
exec(...);
/* here can be no more code in the child, as `exec` will not return if there is no error! */
}
}
/* there you can do a `select` to wait data from several pipes; select will give you number of fd with data waiting, you can find a pid from two arrays */
It's mind-bending at first, but you seem to grasp that, when you call fork( ):
the calling process (the "parent") is
essentially duplicated by the
operating system and the duplicate process
becomes the "child"
with a unique PID all its own;
the returned value from the fork( )
call is either: integer
0,1 meaning that the
program receiving the 0 return is the
"child"; or it is the non-zero integer PID
of that forked child; and
the new child process is entered into
the scheduling queue for execution.
The parent remains in the scheduling
queue and continues to execute as
before.
It is this ( 0 .xor. non-0 ) return from fork( ) that tells the program which role it's playing at this instant -- 0 returned, program is the child process; anything else returned, program is the parent process.
If the program playing the parent role wants many children, he has to fork( ) each one separately; there's no such thing as multiple children sharing a fork( ).
Intermediate results certainly can be sent via a pipe.
As for calling each child with different parameters, there's really nothing special to do: you can be sure that, when the child gets control, he will have (copies of) exactly the same variables as does the parent. So communicating parameters to the child is a matter of the parent's setting up variable values he wants the child to operate on; and then calling fork( ).
1 More accurately: fork( ) returns a value of type pid_t, which these days is identical to an integer on quite a few systems.
It's been a while since I've worked in C/C++, but a few points:
The Wikipedia fork-exec page provides a starting point to learn about forking and execing. Google is your friend here too.
As osgx's answer says, fork() can only give you one subprocess, so you'll have to call it 8 times to get 8 processes and then each one will have to exec the other program.
fork() returns the PID of the child process to the main process and 0 to the subprocess, so you should be able to do something like:
int pid = fork();
if (pid == 0) {
/* exec new program here */
} else {
/* continue with parent process stuff */
}