int main(void) { pid_t p; int status; fprintf(stderr, "Parent, PID = %ld: Creating child...\n", (long)getpid()); p = fork(); if (p < 0) { /* fork failed */ perror("fork"); exit(1); } if (p == 0) { /* In child process */ change_pname("child"); sleep(SLEEP_SEC); exit(101); } change_pname("father"); /* * In parent process. Wait for the child to terminate * and report its termination status. */ printf("Parent, PID = %ld: Created child with PID = %ld, waiting for it to terminate...\n", (long)getpid(), (long)p); p = wait(&status); explain_wait_status(p, status); printf("Parent: All done, exiting...\n"); return 0; }
pid_t make_proc_tree(struct tree_node *node) { int status,i; pid_t pid; pid = fork(); if (pid<0){ /*Error*/ printf("%s :",node->name); perror("fork"); exit(-1); } if (pid==0){ change_pname(node->name); /*Change the process name*/ printf("%s : Created \n", node->name); /*Message "created"*/ for (i=0; i<node->nr_children; i++) make_proc_tree(node->children+i); /*recursion to create children*/ if (node->nr_children==0){ /*if leaf sleep*/ printf("%s: Sleeping...\n", node->name); sleep(SLEEP_PROC_SEC); printf("%s: Exiting...\n", node->name); exit(0); } else { printf("%s: Waiting...\n", node->name); /*else procedure is father of other procedures*/ for(i=0; i<node->nr_children; i++){ pid = wait(&status); /*Waiting for children to be terminated*/ explain_wait_status(pid, status); } printf("%s: Exiting...\n", node->name); exit(0); } } return pid; }
//--FUNCTIONS-- void create_ptree(node_type *cur, size_t lvl) { int status; pid_t *CHILDREN=NULL; //Children PID array. if (cur->nr_children>0) { //Allocation of children PID array memory. CHILDREN=(pid_t *)malloc((cur->nr_children)*sizeof(pid_t)); if (CHILDREN==NULL) { alloc_err; exit(EXIT_FAILURE); } } pid_t par=getpid(), child=0, retv=0; change_pname(cur->name); //Change name. // proc_enter(par); //Enter message. size_t i=0; for (i=0; i<cur->nr_children; i++) { //Create heirs. // fprintf(stderr, "FORK LV: %u - IT: %u\n", lvl, i); //DEBUG child=fork(); if (child<0) { //Sanity. fork_err(cur); exit(EXIT_FAILURE); } if (child==0) { //Recursion for child: create_ptree(&cur->children[i], lvl+1); //... } else { //Rest of parent: CHILDREN[i]=child; continue; } } if (cur->nr_children>0) { //Node: //Wait for heirs to sleep. wait_for_ready_children(cur->nr_children); } //else //Leaf: Fall-through. if (raise(SIGSTOP)) { //Sleep yourself. sign_err(par, "0"); exit(EXIT_FAILURE); } actual_msg(par, cur->name); //Wake-up and print awake message. // fprintf(stderr, "i=%u, child=%ld, CHILDREN[i]=%ld\n", i, (long)child, (long)CHILDREN[i]); if (cur->nr_children>0) { for (i=0; i<cur->nr_children; i++) {//Parents continue and bury their children 1 by 1. cont_msg(cur->name, CHILDREN[i]); if ((kill(CHILDREN[i], SIGCONT))==-1) { sign_err(par, "1"); exit(EXIT_FAILURE); } // wait_for_ready_children(1); //NEEDs DEBUGGING: Doesn't work with this instead of the 2 next commands. retv=wait(&status); //Wait the just awoken child to terminate before you wake up the next (condition for the depth first traversal). bury_msg(cur->name, retv); //Bury message. } } //else //Fall-through. // proc_exit(par); //Exit message. // kill(par, SIGKILL); exit(EXIT_SUCCESS); //Children and parents who buried theirs, just roll off and die. }
void fork_procs(struct tree_node *root) { pid_t child ; int i,status ; pid_t* children; children = (pid_t*)malloc((sizeof(pid_t)*root->nr_children)); if (children == NULL){ fprintf(stderr, "allocate children failed\n"); exit(1); } printf("PID = %ld, name %s, starting...\n",(long)getpid(), root->name); change_pname(root->name); for (i = 0 ; i < root->nr_children; i++){ printf("%s:Creating child %s...\n",root->name,root->children[i].name); child = fork(); if (child < 0) { perror("child fork"); exit(1); } if (child == 0) { /* Child */ fork_procs(&root->children[i]); } /* Father saves child's pid ! */ children[i] = child; } wait_for_ready_children(root->nr_children); printf("%s: All children ready ! Suspending with SIGSTOP...\n",root->name); /* * Suspend Self */ raise(SIGSTOP); printf("PID = %ld, name = %s is awake\n",(long)getpid(), root->name); for (i = 0 ; i < root->nr_children;i++){ printf("%s: Activating child %s...\n",root->name,root->children[i].name); kill(children[i],SIGCONT); children[i] = wait(&status); explain_wait_status(children[i],status); } printf("%s: Exiting...\n",root->name); free(children); exit(0); }
void fork_procs(struct tree_node *current){ pid_t p_new[20]; int status; int i; struct tree_node *temp; change_pname(current->name); printf("%s:Starting..\n",current->name); for(i=0;i<current->nr_children;i++){ p_new[i]=fork(); if(p_new[i]<0){ perror("fork"); exit(2); } else if(p_new[i]==0){ fork_procs(current->children+i); } } wait_for_ready_children(current->nr_children); printf("%s:I gave birth to %d childs and then suspended myself..\n",current->name,current->nr_children); raise(SIGSTOP); printf("%s:Before you know,awake!..\n",current->name); for(i=0;i<current->nr_children;i++){ temp=current->children+i; printf("I, %s , am your father %s,and i say wake!\n",current->name,temp->name); kill(p_new[i],SIGCONT); p_new[i]=wait(&status); explain_wait_status(p_new[i],status); } printf("%s:Exiting..\n",current->name); exit(3); }