The goal is to try and fork 4 children in a loop, but I'm not sure how to properly do that. This is what I have so far. I tried to draw it out and I think I'm not waiting to reap the child properly. And I create like 2 children every iteration. So, 8 children in total.
void main() {
int i = 0;
pid_t pid;
int status;
for(i = 0; i < 4; i++) {
pid = fork();
if(pid == 0) {
/* Child Process */
fork();
exit(0);
} else {
/* Parent Process */
wait(&status);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
}
Creating four children processes from the same parent process can be achieved by forking once on each iteration of the for loop:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0)
exit(0); // child process
// parent process
wait(NULL);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
However, you probably want the parent process to wait for the children after it has created all of the four children, because you usually want the children to do something before exiting and concurrently with the other children:
int main() {
// create the four children processes
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0) {
// child process
// ... do some stuff ...
exit(0);
}
}
// wait for the four children processes to finish
for (int i = 0; i < 4; i++) {
pid_t pid = wait(NULL);
printf("Process %d is terminated.\n", pid);
}
}
Related
In this simple C code, I am trying to create 10 children. Then do some work (such as printing the time) in them individually. Then I try to kill all of them in parent process. You will easily understand the code below. The problem is that, whenever I run this, first it gives the various outputs from children then Linux shuts down. Then I start from passing user password and everything is closed. Why this happens?
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
int main() {
pid_t pids[10];
int i;
int n= 10;
for (i= 0; i<n; ++i) {
if ((pids[i] = fork()) <0) {
perror("fork");
abort();
}
else if (pids[i] == 0) {
struct timeval tv;
time_t t;
struct tm*info;
char buffer[64];
gettimeofday(&tv,NULL);
t = tv.tv_sec;
info = localtime(&t);
sleep(1);
printf("CHILD PID: %d and the time is %s\n",getpid(),asctime(info));
}
}
int status;
pid_t pid;
sleep(5);
while (n >0) {
pid = wait(&status);
kill((long)pid, SIGTERM);
printf("CHILD %d killed.",pid);
--n;
}
}
In process created by fork() all variables have the same value as before fork. After fork in this your code
for (i= 0; i<n; ++i) {
if ((pids[i] = fork()) <0) {
perror("fork");
abort();
}
else if (pids[i] == 0) {
...
}
}
i in child process is the same as it was in parent before fork, so for loop continue to execute and spawn a lot of grand children processes.
After loop is executed all spawned processes call wait(). Processes which are spawned on last iteration (with i==9) have no children, so wait() indicates error by returning -1 (and errno==ECHILD). Then you call kill() with pid==-1, which is:
If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init)
If you want child processes to terminate by themself then you should exit explicitly, e.g. with _exit() function. In this case you don't need to send TERM signal:
int main(void)
{
pid_t pids[10];
int i;
int n = 10;
for (i = 0; i<n; ++i)
{
if ((pids[i] = fork()) < 0)
{
perror("fork");
abort();
// abort() never return, "else" is not needed
}
if (pids[i] == 0)
{
struct timeval tv;
time_t t;
struct tm*info;
gettimeofday(&tv,NULL);
t = tv.tv_sec;
info = localtime(&t);
sleep(1);
printf("CHILD PID: %d and the time is %s\n",getpid(),asctime(info));
_exit(0); // terminate process explicitly
}
}
int status;
pid_t pid;
sleep(5);
while (n > 0)
{
pid = wait(&status);
// No kill needed for already exited process
// kill((long)pid, SIGTERM);
if (pid == -1)
{
perror("wait");
abort();
} else {
printf("CHILD %d killed.\n", pid);
}
--n;
}
}
If you want to terminate child processes from parent process then children should wait until terminated, but you should send signal before waiting for child process termination:
int main(void)
{
pid_t pids[10];
int i;
int n = 10;
for (i = 0; i<n; ++i)
{
if ((pids[i] = fork()) < 0)
{
perror("fork");
abort();
// abort() never return, "else" is not needed
}
if (pids[i] == 0)
{
struct timeval tv;
time_t t;
struct tm*info;
gettimeofday(&tv,NULL);
t = tv.tv_sec;
info = localtime(&t);
sleep(1);
printf("CHILD PID: %d and the time is %s\n",getpid(),asctime(info));
// wait until terminated
for (;;)
pause();
}
}
int status;
pid_t pid;
sleep(5);
for (i = 0; i<n; ++i) {
if (kill(pids[i], SIGTERM) == -1) {
perror("kill");
}
}
while (n--)
{
pid = wait(&status);
if (pid == -1)
{
perror("wait");
abort();
} else {
printf("CHILD %d killed.\n", pid);
}
}
}
Code below outputs child and parents PID output however need it to look more like the sample output below. How could I modify my code to allow this to happen.
Any help is greatly appreciated.
parent process: counter=1
child process: counter=1
parent process: counter=2
child process: counter=2
The code is (edited to fix missing semicolon and make more readable):
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void) {
int pid;
pid = fork();
if (pid < 0)
{
printf("\n Error ");
exit(1);
}
else if (pid == 0)
{
printf("\n Child Process ");
printf("\n Pid is %d ", getpid());
exit(0);
}
else
{
printf("\n Parent process ")
printf("\n Pid is %d ", getpid());
exit(1);
}
}
You have a missing ; in your code, so it wouldn't compile cleanly. Also, there is no loop outputting the text that you require.
Consider instead the following:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main()
{
pid_t pid;
char *child = "child";
char *parent = "parent";
char *me;
pid = fork();
if (pid < 0) {
perror("fork()");
exit(EXIT_FAILURE);
} else if (pid == 0)
me = child;
else
me = parent;
for (int i = 0; i < 2; ++i)
printf("%s: counter is %d\n", me, i + 1);
return EXIT_SUCCESS;
}
This calls fork() and detects whether the current process is the child or the parent. Depending on which it is, we point me to the correct string and enter a short loop that just prints our string and the counter.
The output may be
parent: counter is 1
parent: counter is 2
child: counter is 1
child: counter is 2
So here is my code that will take an int as an command line argument then fork N child processes (That run simultaneously). And then when each child ends, the parent will echo the child that child exit status.
But right now I can only do child by child but not simultaneously. How can I do it?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
int main ( int argc, char *argv[] )
{
int i, pid, ran;
for(i = 0; i < atoi(argv[1]); i++) {
pid = fork();
srand(time(NULL));
ran = (rand() % 10) + 1 ;
if (pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
printf("Sleep for = %d\n", ran);
sleep(ran);
exit(ran);
} else {
int status = 0;
pid_t childpid = wait(&status);
printf("Parent knows child %d is finished. \n", (int)childpid);
}
}
}
You're calling wait() inside of the loop where you're spawning the children, so it won't continue the loop to start the next child until the current one is done.
You need to call wait() outside of the loop in a separate loop:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
int main ( int argc, char *argv[] )
{
int i, pid, ran;
for(i = 0; i < atoi(argv[1]); i++) {
pid = fork();
srand(time(NULL));
ran = (rand() % 10) + 1 ;
if (pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
printf("Sleep for = %d\n", ran);
sleep(ran);
exit(ran);
}
}
for(i = 0; i < atoi(argv[1]); i++) {
int status = 0;
pid_t childpid = wait(&status);
printf("Parent knows child %d is finished. \n", (int)childpid);
}
}
Im new in C programming and i have to do this:
Write a program that creates a second process, and then in both processes outputs the process ID and the owners user ID.
I don't know if thats right and how to continue from here. Here is what i have:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int ChildPID;
printf("This is the parent process number %d\n",getpid());
if ((ChildPID = fork()) == -1) {
perror("Could not fork");
exit(EXIT_FAILURE);
}
if (ChildPID == 0) {
//----In the child process
printf("This is the child process, number %d parent number %d\n", getpid(), getppid());
}
return(EXIT_SUCCESS);
}
The piece of code given below gives your solution. Here you can clearly identify parent code and child process code. Both are printing their corresponding pids.
void ExecuteChild(void);
void ExecuteParent(void);
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ExecuteChild();
else
ExecuteParent();
}
void ExecuteChild(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("CHILD[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Child Exiting -------------\n");
}
void ExecuteParent(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("PARENT[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Parent Exiting -------------\n");
}
Let's say i have a main C program that has to wait for sigchld of two children, and that these two sons have to do two separate task, for example one should write "1", and the other
one should write "2" ,wait 2 seconds and then terminate, now how should I write the code so that the father write his children's pid only after the two sons ends with sigchld? It's obvious that i'm missing some theory, if you look at my code you will understand what my issue is.
After that i'll have to force the execution of the second son before the first son, suggestion?
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int pids[2], cpid, i, status;
char buff[200];
for(i=0; i < 2; i++)
{
if ((pids[i] = fork()) < 0)
perror("errno");
else
{
//child
if (pids[i] == 0)
{
if(i == 0)
write(1,"1\n", 2);
else
{
sleep(2);
write(1,"2\n", 2);
}
return 0;
}
}
}
for(i = 0; i < 2; i++)
{
cpid = waitpid(pids[i], &status, 0);
if (WTERMSIG(status))
printf("status:%d , pid terminated:\n", status,cpid);
else
printf("error: not exited with a signal\n");
}
return 0;
}
If the last for loop is changed as:
for(i = 0; i < 2; i++)
{
cpid = waitpid(pids[i], &status, 0);
if (WIFEXITED(status))
printf("status:%d , pid %d terminated normally :\n", status,cpid);
else if (WTERMSIG(status))
printf("status:%d , pid %d terminated by signal:\n", status,cpid);
else
printf("error: not exited with a signal\n");
}
Then the thing works better, as there is no signal to terminate the childs.