How to change order of creation of processes? - c

I have to make a tree of processes like in this image:
I have managed to create such a tree, but with a minor difference. P4 is actually P3, and P3 is P4. I have created them in order, because i can't think of a way of "attaching" P4 to P1, and P3 to P2. This is what I've written so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "a2_helper.h"
int main(int argc, char **argv){
printf("Main pid is %d\n", getpid());
pid_t pid1[2];
pid_t pid2[4];
pid_t pid3a, pid3b;
//FIRST LAYER
for(int i = 0; i < 2; i++){
pid1[i] = fork();
if(pid1[i] == 0){
printf("[son] pid %d from [parent] pid %d\n", getpid(), getppid());
//SECOND LAYER
if ( i == 0){
for(int j = 0; j < 4; j++){
pid2[j] = fork();
if (pid2[j] == 0){
printf("\t[son] pid %d from [parent] pid %d\n", getpid(), getppid());
//THIRD LAYER
if (j == 1){
pid3a = fork();
if (pid3a == 0){
printf("\t\t[son] pid %d from [parent] pid %d\n", getpid(), getppid());
exit(0);
}
waitpid(pid3a, NULL, 0);
}
if (j == 2){
pid3b = fork();
if (pid3b == 0){
printf("\t\t[son] pid %d from [parent] pid %d\n", getpid(), getppid());
exit(0);
}
waitpid(pid3b, NULL, 0);
}
//END THIRD LAYER
exit(0);
}
}
//END SECOND LAYER
for(int j = 0; j < 4; j++)
waitpid(pid2[j], NULL, 0);
}
exit(0);
}
}
for(int i = 0; i < 2; i++)
waitpid(pid1[i], NULL, 0);
//END FIRST LAYER
return 0;
}
What can I change in order to achieve that?

It's better for fork one fewer times than the paths you need. Look at the following code based on the graph (without P3 and P4 switched)
void doP1(){
if(fork())
doP2();
else
doP4();
}
void doP2(){
if(fork())
doP3();
else if(fork())
doP5();
else if(fork())
doP6();
else
doP7();
}
void doP3(){
return;
}
void doP4(){
return;
}
void doP5(){
doP8();
}
void doP6(){
doP9();
}
void doP7(){
return;
}
void doP8(){
return;
}
void doP9(){
return;
}
int main(){
doP1();
}
I separated every node of the tree into its own function which do nothing but fork in the way the graph shows.
When a data-path splits into two, you don't need to create two child threads, you just need to create one. The parent goes one way, and the child goes another.
i.e. P1 should only call fork once, P2 should only call fork three times, P5 and P6 shouldn't call fork at all
I hope that answers your question!

Related

fork() 4 children in a loop

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);
}
}

How to make parent process wait for child processes to finish?

I have an assignment which gives me this code to transform into a code that makes the parent process wait for all children processes to finish.
PS: the first code has 4 processes and needs to use waitpid to solve this.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t p = fork();
pid_t k = fork();
if(p>0){
printf("p=%d: PID = %d\n", p, getpid());
sleep(45);
exit(0);
}
else if(p==0){
printf("p=%d: PID = %d\n", p, getpid());
exit(0);
}
else if(p<0){
printf("ERRO! p=%d\n", p);
exit(p);
}
}
I've tried this, but I think that this only works for only 1 child process and not for a lot of them.
int main(){
pid_t p = fork();
pid_t k = fork();
if(p<0){
printf("fodeu");
exit(p);
}
else if(p==0){
printf("");
exit(0);
}
else{
for(i=0;i<4;i++){
int returnstatus;
waitpid(p,&returnstatus,0);
if(returnstatus == 0){
printf("o processo filho correu normalmente");
}
else if(returnstatus == 1){
printf("o processo filho ardeu");
}
}
}
}
This won't do your assignment, but I hope it is advice enough to get
you going. The assignment appear to be a riddle around fork(), your
teacher has good taste :-)
fork() is different. It returns twice.
In the parent it returns the process ID of the created process.
In the child it returns 0; a process can always determine its PID using getpid()
Actually, the assignment is not good taste. Usually code using `fork()
never lets any branch escape into enclosing code to avoid complete
bullshit. Like so,
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
if (pid == 0 /*child*/) {
printf("PID %d (child) doing work\n", pid);
sleep(5);
exit(0); // don't let it continue (leak) into parent code
}
else if (pid > 0 /*parent*/) {
int status;
pid_t terminated;
printf("PID %d (parent) waiting for child PID %d\n", getpid(), pid);
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status))
printf("child exited normally with status %d\n", WEXITSTATUS(status));
else
printf("hm. child died otherwise. see 'man waidpid' for more\n");
}
return 0;
}
With this in mind, look at these two innocent looking lines,
pid_t p = fork(); // two processes after this
pid_t k = fork(); // executed by **two** processes, again duplicating
So, after these two lines we have four processes executing the rest of
the code in parallel. This is the point where brains explode. What
does the leaked child of the k line do when it asks what p's value
is?
Look at the output of this little program, to see what's the effect of
leaking.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
printf("MAIN PID %d\n", getpid());
fork();
fork();
printf("PID %d, PPID %d\n", getpid(), getppid());
return 0;
}
This is one way to do it; there will be numerous others.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static void wait_for_kids(void);
int main(void)
{
pid_t p = fork();
pid_t k = fork();
if (p > 0)
{
printf("p=%d: PID = %d\n", p, getpid());
sleep(5);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else if (p == 0)
{
printf("p=%d: PID = %d\n", p, getpid());
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else
{
printf("ERROR! p=%d\n", p);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(p);
}
/*NOTREACHED*/
}
static void wait_for_kids(void)
{
int corpse;
int status;
int pid = getpid();
while ((corpse = waitpid(0, &status, 0)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", pid, corpse, status);
}
Example output:
p=43445: PID = 43444
p=43445: PID = 43446
p=0: PID = 43445
p=0: PID = 43447
43447: p = 0, k = 0 - exiting
43445: child 43447 exited with status 0x0000
43445: p = 0, k = 43447 - exiting
43446: p = 43445, k = 0 - exiting
43444: child 43445 exited with status 0x0000
43444: child 43446 exited with status 0x0000
43444: p = 43445, k = 43446 - exiting

How to run child processes simultaneously? in c

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);
}
}

creating a second process in C

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");
}

Controlling multiple children, handling sigchld

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.

Resources