I have written a basic c++ program in unix with fork() and wait() system call. I am only creating one child. I have used two pipes. So After fork operation with first pipe i am writing from child to parent and as after parent receives the data, parent is writing back to child in second pipe. after that in parent side I am using wait(0) system call. but still my parent process dies before child process?
structure is something like this:
main()
char buff[] = "Parent process kills";
char cuff[] = "before Child process";
int fd1[2];
int fd2[2];
pipe(fd1);
pipe(fd2);
if((pid = fork()) == 0)
{
close(fd1[0]);
close(fd2[1]);
write(fd1[1],buff,strlen(buff)+1);
read(fd2[0],cuff,sizeof(cuff));
}
else
{
close(fd1[1]);
close(fd2[0]);
read(fd1[0],buff,sizeof(buff));
write(fd2[1],cuff,strlen(cuff)+1);
wait((int *) 0);
}
close(fd1);
close(fd2);
}'
Even though wait() is used but still parent process dies before child.
Thanks in adavance.
Your call to read result in undefined behavior. You try to read into string literals, not the buffers you have. In this case it probably results in a crash.
Your write calls also writes a string literal and not the buffer you have.
Also, since you have character arrays initialized to strings, sizeo(buff) and strlen(buff) + 1 are equal.
Are you sure you're not dying due to a segfault? Each of these commands is trying to send more than you intend:
write(fd1[1],"buff",strlen(buff)+1);
and
write(fd2[1],"cuff",strlen(cuff)+1);
and each of these is trying to receive into read-only memory:
read(fd2[0],"cuff",sizeof(cuff));
and
read(fd1[0],"buff",sizeof(buff));
There is a subtle error in the line
if(pid == fork())
You compare the result of fork() with pid instead of assigning to it and comparing it to zero. What you wanted to write is this:
if((pid = fork()))
Note the extra set of parentheses that tells the compiler that you really want to do the assignment, and that you don't want get a warning on it.
And with the corrected if, you have the parent executing the first case, not the second, so the correct code would be:
if(pid == fork()) {
close(fd1[1]);
close(fd2[0]);
read(fd1[0],"buff",sizeof(buff));
write(fd2[1],"cuff",strlen(cuff)+1);
wait((int *) 0);
} else {
close(fd1[0]);
close(fd2[1]);
write(fd1[1],"buff",strlen(buff)+1);
read(fd2[0],"cuff",sizeof(cuff));
}
Related
#1 code
int child_pid;
for (int i = 0; i < 3; i++)
{
child_pid = fork();
if (child_pid == 0)
{ sleep(10); }
else
{ wait(&status); }
}
execlp("sleep","sleep","20",(char*)NULL);
#2 code
int child_pid;
for (int i = 0; i < 5; i++)
{
child_pid = fork();
if (child_pid == 0)
{ sleep(1); }
else
{ wait(&status);
execlp("sleep","sleep","20",(char*)NULL); }
}
Can someone explain to me what is happening in these codes?
I understand fork() returns a zero to a newly created child process. That's why I don't understand why in #2 code the else branch is also being executed? Execlp replaces the calling process image with a new process image, but what does this really mean?
EDIT:
The answer is that the first code will create 8 processes, but I'm not able to understand how? And why will the first code finish 230 seconds? How does exec affect this?
The second code will create 5 processes, but it will finish after (5*2sec+5*20sec). In the second code why does it go to the else branch?
I'm trying to understand how many processes are created as well as why and how long the code will sleep?
Thanks in advance.
fork will return two times, one in the original process, with the return value of the pid of the child process, the other in the child process, with the return value of zero
DESCRIPTION
fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.
and:
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, after to fork(), you have your newly created process, so you have 2 process, the child (the new process) and the parent (the initial process).
So, what your child (pid == 0) is going into the sleep when you parent (pid > 0) is executing your sleep.
After doing an exec* (execl, execlp, execv, execve, etc...) your process is terminated (try to place a printf or whatever AFTER your execlp, you will see it will never print it (except in case of error (execlp's return value == -1)).
To answer to your initial question:
Yes, your program pass in your if AND in your else (put printf to see clearer), because you have in fact 2 process, and you can even try to put a printf after the else statement, at the very end of your program, and you will see that the child pass (print his pid, it should be equal to 0).
I am trying to change a variable value inside a child process and keep it for the rest of the program. So In the below example why my cout keeps printing 0, and how do I solve it?
int var = 0;
int pid = fork();
if (pid == 0){ //child process
var = 1;
exit(1);
}
else if (pid> 0){ //parent process
if (-1 == wait (0))
perror ("there was an error with wait");
}
cout << var;
This is how code execution is going to go.
Child Process
int var =0;
var = 1;
exit (1);
Parent Process
int var =0;
if (-1 == wait (0))
perror ("there was an error with wait);
cout << var;
So as you can see, var will not be changed for the parent process.
When you fork, the child and parent have separate copies of the variables that were present before they split off into execution paths. Processes do not share the same block of memory. Therefore, altering var for the child will not affect the var in the parent.
If you want multiple execution paths on the same piece of memory, you should use threads.
Thank you for reading.
Looks like the fork() call has failed. Check the errno value
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.
ERRORS
EAGAIN
fork() cannot allocate sufficient memory to copy the parent's page tables and allocate a task structure for the child.
EAGAIN
It was not possible to create a new process because the caller's RLIMIT_NPROC resource limit was encountered. To exceed this limit, the process must have either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.
ENOMEM
fork() failed to allocate the necessary kernel structures because memory is tight.
CONFORMING TO SVr4, 4.3BSD, POSIX.1-2001.
There are lot of questions on fork() but I am little bit confused in this code.I am analyzing a code in c++ in that I have got this function.
int daemon(int nochdir, int noclose)
{
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0); /* exit the original process */
}
if (setsid() < 0) /* shoudn't fail */
return -1;
/* dyke out this switch if you want to acquire a control tty in */
/* the future -- not normally advisable for daemons */
printf("Starting %s [ OK ]\n",AGENT_NAME);
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0);
}
if (!nochdir)
{
chdir("/");
}
if (!noclose)
{
dup(0);
dup(1);
}
return 0;
}
So the fork will create an exact copy of the code from where the fork() has been called. so,
Is switch executed twice or once?
If twice then in the switch what if the child executes first? Will it just break or go to the other statements?
What If the parent executes? will the main process be terminated and child will continue?
Edit:
So the switch will also run twice once with parent and once with child. and behaves on the return values.
And the final thing is, the daemon is a predefined function and it has been redefined and used like user created daemon. How it will create the daemon process and what the
`if (!nochdir)
{
chdir("/");
}`
and
if (!noclose)
{
dup(0);
dup(1);
}
I am calling this function like this.
if (daemon(0, 0) < 0)
{
printf("Starting %s [ Failed ]\n",AGENT_NAME);
exit(2);
}
Is switch executed twice or once?
It is said that fork is the function that is called once but returns twice, that is once in each process: once in parent and once in a child.
man :
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
It might return just once (-1): only in parent if child wasn't created. It always returns in the parent ( -1 on error, > 0 on success).
If twice then in the switch what if the child executes first? Will it
just break or go to the other statements?
It is unknown whether child or parent returns first. After fork() all the memory segments are copied into child, but it continues with the correct value 0 returned from the fork(). Parent continues with pid of the child. You use return value of fork in the code to determine whether you are child or parent. Maybe this will get more clear if you write code this way
int daemon( int nochdir, int noclose)
{
pid_t pid; /* to drive logic in the code */
if ( ( pid = Fork()) < 0) /* fork and remember actual value returned to pid */
return -1;
if( pid > 0)
_exit(0); /* exit the original process */
// here pid is 0, i.e. the child
What If the parent executes? will the main process be terminated and
child will continue?
What if the parent exit() is called before any child instructions? Then yes, parent will terminate, child will do on its own. Both the parent and the child processes possess the same code segments, but execute independently of each other (unless you added some synchronization).
http://linux.die.net/man/2/fork
Yes, when the parent executes it will continue in the default: case as the switch will have returned the child process id.
The common convention of saying that fork() is a function which is called once and returns two times is a bit obfuscating as it only returns once in each process space. The question is whether a child was created or not which determines which of the two ways a parent returns. The parent never gets a result of '0' from fork(), only either -1 or >0. The child always (if at all) gets zero.
If the child wasn't created, then fork() never returns in its process space.
Unless there's an error, fork will return twice: once in the parent process and once in the child process. fork creates a copy of the current process, then continues execution in both processes and you can determine by the return value. Note that the copy (child) is not a "perfect" copy: for example, in the child, all threads are terminated except for the one executing fork. The exact behavior is a bit complex.
It's not specified whether the parent or child process continues execution first. This depends on your OS and might even be totally random on your OS. Since they are two separate processes (which happen to run the same code) the order doesn't matter. The parent process will get a return value >0 (or -1 on error) and thus execute the default: label. The child process will get a return value of 0 and thus execute the case 0: label. This return value of fork is how the parent process knows it's a parent and the child process that it is a child (the child can query its own PID using getpid(2) and the PID of its parent using getppid(2)).
Yes, the parent runs into the default: label and executes _exit, thus terminating. The child will continue to run (note that here setsid() is very important; without it, the child would not continue to run if the shell session of your parent exits). This is the usual pattern for creating a daemon: when you run the program, it spawns actual main program (the daemon) through forking and then exits. For example, in the shell, you'll see the program exits quickly, but when you enter ps you can see that there's a process with the same name (your daemon).
My program is supposed to limit the number of child processes to 3.
With the code below, waitpid stalls my parent process so I can't create more child processes after the first one. If I don't use waitpid then I don't know when a child process quits to decrease the number of alive processes.
int numProcs = 0;
while(1==1) {
/*
* inserts code that waits for incoming input
*/
numProcs++;
pid = fork();
if (pid == 0) {
doStuff(); // may exit anytime, based on user input
} else {
if (numProcs > 3) {
wait(&status);
numProcs--;
} else {
waitpid(pid, &status, 0); // PROBLEM!
numProcs--;
}
}
}
I've been searching for this problem the whole day. Can somebody help?
At the risk of being obvious, you basically want to just drop the else clause. The logic you're looking for is something like:
int max_active = 3; // or whatever
int number_active = 0;
bool done = false;
for (; !done; ++number_active) {
// wait for something to do;
GetSomeWork();
// wait for something to finish, if necessary.
for (; number_active >= max_active; --number_active)
wait(&status);
pid = fork();
if (pid < 0)
ReportErrorAndDie();
if (pid == 0)
DoTheWorkAndExit();
}
This actually lets you change the value of max_active without restarting, which is the only justification for the for loop around the wait() call.
The obvious complaint is that number_active in my version doesn't actually tell you how many processes are active, which is true. It tells you how many processes you haven't wait()'ed for, which means that you might keep some zombies (but the number is limited). If you're constantly running at or close to the maximum number of tasks, this doesn't matter, and unless your maximum is huge, it doesn't matter anyway, since the only Design Requirement was that you don't use more than the maximum number of tasks, and consequently you only have to know that the number active is not more than the maximum.
If this really bothers you and you want to clean the tasks up, you can put:
for (; waitpid(-1, &status, WNOHANG) > 0; --number_active) {}
before the other for loop, which will reap the zombies before checking if you need to block. (I can't remember if waitpid(-1, &status WNOHANG) returns an error if there are no processes at all, but in any event there's no point continuing the loop on an error.)
You have two problems with your code, but the second one is masked by the first.
Your immediate problem is that waitpid(pid, &status, 0); will block until the process with the specified pid terminates. You want to add the WNOHANG option as a third parameter to the waitpid() call. That will ensure that the call dosn't block.
This will add a new problem: You will have to check for yourself is any child process have terminated. You can do that using the WIFEXITED macro:
} else {
waitpid (-1, &status, WNOHANG);
if (WIFEXITED(status)) {
numProcs--;
}
}
The second problem is that your original code only waits for the latest pid to be created. You should instead wait for -1, which is all child processes.
I am kind of newbie on C++, and working on a simple program on Linux which is supposed to invoke another program in the same directory and get the output of the invoked program without showing output of the invoked program on console. This is the code snippet that I am working on:
pid_t pid;
cout<<"General sentance:"<<endl<<sentence<<endl;
cout<<"==============================="<<endl;
//int i=system("./Satzoo");
if(pid=fork()<0)
cout<<"Process could not be created..."<<endl;
else
{
cout<<pid<<endl;
execv("./Satzoo",NULL);
}
cout<<"General sentance:"<<endl<<sentence<<endl;
cout<<"==============================="<<endl;
One of the problem I encounter is that I am able to print the first two lines on console but I cant print the last two lines. I think the program stops working when I invoke the Satzoo program.
Another thing is that this code invokes Satzoo program twice, I dont know why? I can see the output on screen twice. On the other hand if I use system() instead of execv(), then the Satzoo works only once.
I haven't figured out how to read the output of Satzoo in my program.
Any help is appreciated.
Thanks
You aren't distinguisng between the child and the parent process after the call to fork(). So both the child and the parent run execv() and thus their respective process images are replaced.
You want something more like:
pid_t pid;
printf("before fork\n");
if((pid = fork()) < 0)
{
printf("an error occurred while forking\n");
}
else if(pid == 0)
{
/* this is the child */
printf("the child's pid is: %d\n", getpid());
execv("./Satzoo",NULL);
printf("if this line is printed then execv failed\n");
}
else
{
/* this is the parent */
printf("parent continues execution\n");
}
The fork() function clones the current process and returns different values in each process. In the "parent" process, it returns the pid of the child. In the child process, it returns zero. So you would normally invoke it using a model like this:
if (fork() > 0) {
cout << "in parent" << endl;
} else {
cout << "in child" << endl;
exit(0);
}
I have omitted error handling in the above.
In your example, both of the above code paths (both parent and child) fall into the else clause of your call to fork(), causing both of them to execv("./Satzoo"). That is why your program runs twice, and why you never reach the statements beyond that.
Instead of using fork() and doing everything manually (properly managing process execution is a fair amount of work), you may be interested in using the popen() function instead:
FILE *in = popen("./Satzoo", "r");
// use "in" like a normal stdio FILE to read the output of Satzoo
pclose(in);
From the fork() manpage:
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. 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.
You check to make sure it succeeds, but not whether the pid indicates we're in the child or the parent. Thus, both the child and the parent do the same thing twice, which means that your program gets executed twice and the ending text is never printed. You need to check the return value of fork() more than just once.
exec - The exec() family of functions replaces the current process image with a new process image.
system - Blocks on execution of the command. Execution of the calling program continues after the system command returns
There are three return value tests you want with fork
0: you are the child
-1: error
other: you are the parent
You ran the other program from both the child and the parent...