I'm trying to create fork tree diagram, but still with no success. Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void procStatus(int level) {
printf("L%d: PID[%d] (PPID[%d])\n", level, getpid(), getppid());
fflush(NULL);
}
void levelFork(int *level) {
if (fork() == 0)
(*level)++;
wait(NULL);
}
void main() {
int level = 0;
procStatus(level);
levelFork(&level);
procStatus(level);
}
I want to create like this picture below:
And this is output look like:
Any help would be appreciated.
Code will be like this, you should fork two child for every new child process until reached target depth level ,after forking two child,parent process must exit system, only new child process should create new processes ,
you can discard parent processes by looking childpid(return value of fork)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <math.h>
int main(int argc, char *argv[])
{
pid_t childpid;
int i, n;
if (argc != 2) {
fprintf(stderr, "Usage: %s n\n", argv[0]); return 1;
}
n = atoi(argv[1]);
childpid=-1;
for (i = 1; i <= n; i++){
int b;
for(b=0;b<2;b++)
{
childpid=fork();
if (childpid <= 0) break;
}
if (childpid > 0) break;
}
while(wait(NULL) > 0) ; /* wait for all of your children */
fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n",i, (long)getpid(), (long)getppid(), (long)childpid);
return 0;
}
output of code is this
└──╼ $./fork.o 2
i:3 process ID:23913 parent ID:23911 child ID:0
i:3 process ID:23915 parent ID:23911 child ID:0
i:3 process ID:23914 parent ID:23912 child ID:0
i:3 process ID:23916 parent ID:23912 child ID:0
i:2 process ID:23911 parent ID:23910 child ID:23915
i:2 process ID:23912 parent ID:23910 child ID:23916
i:1 process ID:23910 parent ID:23277 child ID:23912
You need a way of specifying the max depth and then using that to fork new processes. Once you are done with the forking you can start the printing. The snippet below should work
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void procStatus(int level) {
printf("L%d: PID[%d] (PPID[%d])\n", level, getpid(), getppid());
fflush(NULL);
}
void levelFork(int *level,int maxlevel) {
int locallevel= *level;
while(locallevel!=maxlevel){
int pid = fork();
if (pid == 0){
(*level)++; // childs level is higher
levelFork(level,maxlevel);
return;
}
locallevel++;
wait(NULL);
}
}
void main() {
int level = 0;
int maxlevel=3;
levelFork(&level,maxlevel);
procStatus(level);
}
Related
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 want to fork and exec several processes from another.
My parent code is
/*Daddy.c*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int status;
char *nChild;
for (int i=0; i<3;i++){
int pid = fork();
if (pid == 0)
{
sprintf(nChild, "%d", i);
printf("%d\n", i);
char *const arguments[]={nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
wait(&status);
printf("Dad %d went out!\n", getpid());
exit(0);
}
and my child process is
/*child.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int args, char **argv){
if( args !=2){
printf("Child going away!\n");
exit(1);
}
printf("Child %s: %d going away stylishly!\n", argv[1], getpid());
exit(0);
}
When I don´t create three forks, but one, I know how to create the child, do some work and exit from child and parent. But, in this case, with several children it seems like the child never executes.
Because of the line wait(&status) I did hope that when the first child exits, the parent also exits but, any child prints any message.
Some relevant previous questions didn´t help.
You need to make parent wait for all child processes to finish. If not, assume that 1 child waited for is done and then parent exits. What about the other 2 children? They become orphan since their parent doesn't wait for them.
pid_t wpid;
int status = 0;
.
.
while ((wpid = wait(&status)) > 0); // the parent waits for all the child processes
This code did the job
/* daddy.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void)
{
int status=0;
char nChild[16];
pid_t wpid;
for (int i=0; i<3;i++){
sprintf(nChild, "%d", i);
int pid = fork();
if (pid == 0)
{
printf("%s\n", nChild);
char *const arguments[]={"child", nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
while ((wpid=wait(&status)) >0);
printf("Dad %d went out!\n", getpid());
exit(0);
}
As #OnzOg said in the comments of the question, allocation of nChild was the main problem. Also execv need pass child name twice, one as argument.
And finally, to improve the code, parent process needs to wait all processes to finish.
I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}
I have to create four process, Every son has to create one son and just wait for it to finish.
PROCESS 0 --> PROCESS 1 --> PROCESS 2 --> PROCESS 3 --> PROCESS 4
How to do it ? I've tried the following so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#define NUM_PROC 5
int main (void)
{
int pid;
int i;
int status;
for (i=0; i < NUM_PROC; i++)
{
if ((pid=fork()) <0 )
{
printf("Error in forking\n");
exit(EXIT_FAILURE);
} else if (pid ==0) {
printf("Sono: %d, mio padre e: %d\n", getpid(), getppid());
pid = fork();
}
else {
printf("Sono: %d, mio padre e: %d\n", getpid(), getppid());
wait( &status);
}
}
exit(EXIT_SUCCESS);
}
Main program is creating a new child process in the loop, which then runs the same loop as the parent and creates more child processes.
Using a for loop and generalizing for N processes:
for (int i=0; i<N; i++)
{
pid = fork();
if (pid == -1) { // handle error }
else if (pid == 0) {
// son process (NO FORK INSIDE THIS ELSE IF!)
}
else { // parent process
wait(NULL);
exit(0);
}
}
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.