I am running the following code:
// A C program to demonstrate Zombie Process.
// Child becomes Zombie as parent is sleeping
// when child process exits.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// Fork returns process id
// in parent process
pid_t child_pid = fork();
// Parent process
if (child_pid > 0)
{printf("in parent process");
sleep(50);
}
// Child process
else
{ printf("in child process");
exit(0);
}
return 0;
}
And get following output:
$main
in child process
I am running the code here: http://tpcg.io/6ZccnX
Why is the statement "in parent process" not printing?
the stdout is usually not flushed until a new line has occured
I've tested the following and both options work as expected:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// Fork returns process id
// in parent process
pid_t child_pid = fork();
// Parent process
if (child_pid > 0)
{
/*option one: put '\n' at the end of the print to flush it */
printf("in parent process\n");
/*option two: flush all the available streams after print*/
// printf("in parent process");
// fflush(NULL);
sleep(50);
}
// Child process
else
{ printf("in child process");
exit(0);
}
return 0;
}
Related
I have the following 2 sets of code that output differently. [outputting to the terminal]
Code 1:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main ()
{
printf("before the fork\n");
fflush(stdout);
int pid=fork();
printf("after the fork\n");
if (pid == 0)
{
sleep(1);
printf("I'm child");
}
else
{
wait();
printf ("I'm parent");
}
exit(0);
}
Output 1:
before the fork
after the fork
after the fork
I'm child
Now only the printf after the fork is commented and we see the printf after wait() for the parent process works as expected.
Code 2:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main ()
{
printf("before the fork\n");
fflush(stdout);
int pid=fork();
// printf("after the fork\n");
if (pid == 0)
{
sleep(1);
printf("I'm child");
}
else
{
wait();
printf ("I'm parent");
}
exit(0);
}
Output 2:
before the fork
I'm childI'm parent
I am confused as in how the printf after the fork() messes up the output.
Note the following output too
Code 3:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main ()
{
printf("before the fork\n");
fflush(stdout);
int pid=fork();
printf("after the fork\n");
if (pid == 0)
{
sleep(1);
printf("I'm child");
}
else
{
//wait();
printf ("I'm parent");
}
exit(0);
}
Output 3:
before the fork
after the fork
I'm parentafter the fork
I'm child
Any idea why this discrepancy?
It's not because of the printf("after the fork\n"); that you get different output.
The reason is when fork() system call is invoked you create a child process. And the both the parent process and child process both are running concurrently. So we don't know which would get priority (maybe parent or child).
My output in a online compiler.
In code2, the child process got the preference and so it executes first, followed by parent process.
Also in code 3, wait() system call is invoked, so if parent process gets the preference , it gets executed till the wait(). After that the child process is executed and after termination of child process, the parent process continues from where it left.
refer this for more understanding
The two child processes perform sorting by different methods. I want the parent process to wait until at least one child process terminates. This code is not giving me the required output.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid1, pid2;
int status;
pid1 = fork();
pid2 = fork();
if(pid1==0 && pid2 !=0)
{
//first child performing selection sort
exit(0);
}
if(pid1>0 && pid2 > 0)
{
wait(&status);
if(WIFEXITED(status))
{
printf("Parent process executed %d\n",WEXITSTATUS(status));
}
}
if(pid1>0 && pid2 ==0)
{
//second child performing bubble sort
exit(0);
}
}
pid2 = fork() is executed by the parent and the first child created from pid1 = fork(), which is not something you desire from the question description.
You might want to have something like this
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
pid_t pid1, pid2;
int status;
pid1 = fork();
if(pid1 == 0) {
//first child performing selection sort
exit(0);
}
if(pid1 > 0) {
pid2 = fork();
if(pid2 == 0) {
//second child performing bubble sort
exit(0);
}
if(pid2 > 0) {
wait(&status);
if(WIFEXITED(status)) {
printf("Parent process executed %d\n",WEXITSTATUS(status));
}
}
}
}
When you do fork(), you have a new child process starts running at the same point with the parent process. So you should make sure that only parent process calls the second fork().
Key: fork() will return 0 on child process.
Here is the way to do that:
Code
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int status;
pid_t ret, pid1, pid2;
pid1 = fork();
if (pid1 == 0) {
// First child performing selection sort
printf("Do selection sort here...\n");
sleep(5);
printf("Selection sort finished\n");
exit(0);
}
pid2 = fork();
if (pid2 == 0) {
// Second child performing bubble sort
printf("Do bubble sort here...\n");
sleep(2);
printf("Bubble sort finished\n");
// The parent must get exit code 100 from this
exit(100);
}
// Parent process waits until at least one child process terminates
do {
status = 0;
ret = wait(&status);
if (WIFEXITED(status)) {
printf("Child process %d has exited with exit code: %d\n",
ret, WEXITSTATUS(status));
break;
}
if (ret < 0) {
printf("wait() error: %s\n", strerror(errno));
break;
}
/* If we reach here, child may be traced or continued. */
} while (1);
printf("Parent has finished its waiting state...\n");
return 0;
}
Compile and Run
ammarfaizi2#integral:/tmp$ gcc -Wall -Wextra test.c -o test
ammarfaizi2#integral:/tmp$ ./test
Do bubble sort here...
Do selection sort here...
Bubble sort finished
Child process 143748 has exited with exit code: 100
Parent has finished its waiting state...
ammarfaizi2#integral:/tmp$ Selection sort finished
In this case, when a child process terminates (at least one), the parent will stop to wait. So you see "Selection sort finished" after the parent process terminates, because we simulate selection sort as 5 seconds work, and bubble sort as 3 seconds work.
I have to write an program which will generate a random amount of processes, and then will kill them one after one, after they all were created.
My problem is that I can't stop the child processes after being created.
Also, I try to call the termination-output to stdout from a child process, but don't really know how to solve it (because pid = 0 is for every child process).
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid = 1;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++){
if(pid != 0){
pid = fork();
pidarr[i] = pid;
if(pid ==0){
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
}
sleep(1);
}
}
if(pid != 0){
wait(NULL);
}
for(int i = (amount-1);i >= 0;i--){
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
sleep(rand()%4);
if(pid != 0){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
if(pid != 0){
printf("All child processes were terminated. I will terminate myself now.\n");
}
return EXIT_SUCCESS;
}
the following code shows how to handle fork and child processes.
the code compiles cleanly, is tested and works
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main( void )
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++)
{
pid = fork();
if( -1 == pid )
{ //then, fork() error
perror( "fork() failed" );
exit(1);
}
// implied else, fork() successful
//pidarr[i] = pid;
if(!pid )
{ // then child process
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
exit(0); // exit child process
}
// implied else, parent process
pidarr[i] = pid;
sleep(1);
} // end for
for(int i = (amount-1); i >= 0; i--)
{
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
printf("All child processes were terminated. I will terminate myself now.\n");
return(0);
} // end function: main
I am not sure about other parts of your logic (e.g. the if clause inside the fork loop), but
if(pid != 0){
wait(NULL);
}
looks suspiciously as of the parent process waits for a child to exit so that it doesn't get to the code which would kill the children at all (unless they exit on their own, but then the killing seems pointless).
Some issues in your code:
1) As #Peter Schneider points out,
parent process waits for a child to exit so that it doesn't get to the code which would kill the children
So first of all, you have to get rid of:
if(pid != 0){
wait(NULL);
}
2) The for loop that kills the children has to be executed only by the parent process, so the if clause embraces the for:
if(pid != 0){
for(int i = (amount-1);i >= 0;i--){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
3) The child processes have to wait doing something until parent kills them, so append the following else clause to the above if:
else{
while(1){
printf("I am a child process %d. Will sleep for 2 senconds\n",getpid());
sleep(2);
}
}
4) the following code makes no sense, because when children are killed they simply stop working.
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
If you want children to do something when the signal from kill() gets to them, you will have to use signals.
It's a simple code which makes two child processes communicate: first one execute "ls" and pass the output into myfd[1]; second one receives the output from myfd[0], and then execute "sort"(and shows the result). The parent process waits for these two processes.
But this code doesn't work. It gets stuck at the second child process. Any possible reason why?
Did I use the right "close" and "dump" in proper place?
my code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void)
{
int pid;
int wpid;
int status = 0;
int myfd[2];
printf("parent's pid: %d\n",getpid());
pipe(myfd);
pid = fork();
if(pid == 0) // child 1 - execute "ls"
{
printf("child1's pid: %d\n",getpid());
close(1);
dup(myfd[1]);
close(0);
close(myfd[0]);
execlp("ls","child_process1",NULL);
}
else
{
pid = fork();
if(pid == 0) // child 2 - execute "sort"
{
printf("child2's pid: %d\n",getpid());
close(myfd[1]);
close(0);
dup(myfd[0]);
execlp("sort","child_process2",NULL);
}
}
// parent
while((wpid = wait(&status)) > 0)
{
// wait until two child processes finish
}
printf("done!\n");
}
Program::
#include <sys/types.h>
#include <stdio.h> //standard input output header file
#include <unistd.h> // POSIX operating system API
#include <stdlib.h>
int main()
{
pid_t pid;
pid = fork();
system("clear");
if(pid < 0)
{
fprintf(stderr, "Fork failed to create process\n");
return 1;
}
else if(pid == 0)
{
printf("This is the child process \'%d\' of \'%d\'\n\n",getpid(),getppid());
execlp("/bin/ls","ls",NULL);
}
else
{
printf("This is parent process \'%d\' my parent is %d\n\n",getpid(),getppid());
wait(NULL);
printf("DONE\n\n");
exit(0);
}
return 0;
}
Output:
This is the child process '3979' of '3978'
This is parent process '3978' my parent is '3681'
DONE
vijay#workspace:~/Documents/os$ a.out os_fork.c
I am unable to understand why the execlp() got executed after parent process not along with child process