Print exit order of child processes - c

I have this code. My aim is to create 'n' child processes from parent process and print the pid of each child processes once it is created.
Then I'll ask each child process to sleep for random duration using rand_r function and exit. I want to print the exit order of child processes i.e I want to print their pids in their exit order.
This is my C code. It is not giving required output:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int func(int n)
{
if(n==0){return 0;}
int pid=fork();
unsigned int k=n;
int x=rand_r(&k) % 3;
//printf("here: %d\n", x);
if(pid==0){
printf("Child %d is created\n",getpid());
func(n-1);
sleep(x);
printf("Child %d exited\n",getpid());
exit(0);
}
return 1;
}
int main(int argc, char *argv[]){
char *inp = argv[1];
int n = atoi(inp);
func(n);
return 0;
}
I want output like this:
Child 7432 is created
Child 7433 is created
Child 7434 is created
Child 7435 is created
Child 7433 exited
Child 7432 exited
Child 7435 exited
Child 7434 exited

Related

Issue with muilti-threading with pthread: thread is executing prematurely

I am trying to call make a thread to another function in a function being ran by a child process. I am starting by calling a child process, which makes another child process, which in turn makes a thread. However, the thread function keeps executing prematurely. What could be the issue?
#define _GNU_SOURCE
#include <sched.h>
#include <pthread.h> // pthread
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>// waitpid
#include <sys/wait.h> //waitpid
#define STACK_Size 1024*1024
void* print(void* ptr)
{
printf("\n4. In thread\n");
char* message;
message = (char*)ptr;
printf("\n5. Message from parent: %s \n\n",message);
}
static int threading(void * ptr)
{
char* message;
message = (char*)ptr;
printf("\n3. In child process 2\n");
pthread_t Tid;
pthread_create(&Tid,NULL,&print,(void*)message);
pthread_join(Tid,NULL);
printf("\n6. Thread done.... exiting child process 2\n\n");
}
static int child(void *ptr)
{
char* message;
message = (char*) ptr;
print("\n2. In child 1");
// creating child process
char* stack_ptr = malloc(STACK_Size);
unsigned long flags =0;
pid_t pid;
pid = clone(threading, stack_ptr+STACK_Size,flags | SIGCHLD,message);
int status;
waitpid(pid,&status,0);
printf("7. Done with child 2\n\n8. Now exiting child process 1\n");
}
int main(int argc, char ** argv)
{
char msg[150];
printf("1. Currently in main program name: %s\n", argv[0]);
sprintf(msg,"The name of the program is (%s), P.S this is parent (pid:%d)",argv[0],getpid());
char* stack_pointer = malloc(STACK_Size);
unsigned long flags =0;
setbuf(stdout,NULL);
if((argc >1) && (strcmp(argv[1],"vm")==0))
{
flags = CLONE_VM;
}
pid_t pid;
pid = clone(child,stack_pointer+STACK_Size,flags | SIGCHLD,msg);
int status;
waitpid(pid,&status,0);
printf("\n9. Done with Parent process\n");
}
Here is the output it's producing:
1. Currently in main program name: ./clone
4. In thread
5. Message from parent:
2. In child 1
3. In child process 2
4. In thread
5. Message from parent: The name of the program is (./clone), P.S this is parent (pid:15159)
6. Thread done.... exiting child process 2
7. Done with child 2
8. Now exiting child process 1
9. Done with Parent process
If what you mean by executing prematurely is the lines containing 4. and 5. being printed before 2., it's because you call your custom print() function to output 2. (print("\n2. In child 1")) which also prints out 4. and 5..

Why does this function produce so many child processes?

I wrote this code in order to calculate the factorial of a number using processes and pipe(). I wanted to pass on the result from the child process to the child process. For example, to create calculate 5! the main which is the father sends the number 1 in the pipe. Then the first child is created and does 1*2, then it pushes in the pipe the number 2, the second child does 2*3 pushes the result in the pipe etc... Also, I use argv[1][0] thinking that we run the program like this (./ex3 5) where 5 is the number of which the factorial we would like to find. After running the program though, I noticed that a lot of child process was created (I only wanted 4). Why is that?
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int fd[2];
int w,count=2;
void child_creator(){
pid_t child;
child=fork();
if (child==0) {
close(fd[1]);
read(fd[0],&w,sizeof(w));
close(fd[0]);
w=w*count;
count++;
printf("I am child %d , my father is %d , the prod is %d\n",getpid(),getppid(),w);
sleep(1);
close(fd[0]);
write(fd[1],&w,sizeof(w));
close(fd[1]);
}
}
int main(int argc , char **argv){
int fact=argv[1][0]-'0';
pipe(fd);
w=1;
for (int i=0; i<fact-1; i++){
printf("this is i %d\n", i);
child_creator();
}
return 0;
}
After a suggested answer I tried this code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int fd[1000][2];
int w,count=1,j=0;
void child_creator(){
pid_t child;
j++;
pipe(fd[j]);
child=fork();
if (child==0) {
close(fd[j-1][1]);
read(fd[j-1][0],&w,sizeof(w));
close(fd[j-1][0]);
w=w*count;
printf("I am child %d , my father is %d , the prod is %d\n",getpid(),getppid(),w);
sleep(1);
close(fd[j-1][0]);
write(fd[j][1],&w,sizeof(w));
close(fd[j][1]);
exit(0);
}
}
int main(int argc , char **argv){
int fact=argv[1][0]-'0';
w=1;
for (int i=0; i<fact-1; i++){
count++;
child_creator();
sleep(2);
}
return 0;
}
Both the parent and child are returning to the for loop in main(). Since the child doesn't need to do anything after it writes its result, it should just exit rather than returning.
You also have problems with your handling of the pipe file descriptors. You do close(fd[1]) at the beginning of the child, but later try to write(fd[1],&w,sizeof(w)). You can't write to a closed FD. You don't need to close anything until the child is exiting, and exiting a process automatically closes all its files.
void child_creator(){
pid_t child;
child=fork();
if (child==0) {
read(fd[0],&w,sizeof(w));
w=w*count;
count++;
printf("I am child %d , my father is %d , the prod is %d\n",getpid(),getppid(),w);
sleep(1);
write(fd[1],&w,sizeof(w));
exit(0);
}
}

Fork Tree C Programs

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

Create a chain of n sub processes

In c++ create chain of n processes with n as input and the output of processes should be as parent1->child1(parent2)-->child2(parent3),by using recursive function im able to generate the output but unable to exit the loop i also need help in sending an input of n for which the loop should break.
below is my code:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int foo(const char *whoami) {
printf("I am a %s. My pid is:%d my ppid is %d\n", whoami, getpid(), getppid() );
return 1;
}
int func() {
pid_t pid=fork();
if (pid==0) { /* only execute this if child */
foo("child");
pid_t pid=fork();
if (pid==0) { /* only execute this if child */
foo("child");
func();
exit(0);
}
}
exit(0);
}
wait(0); /* only the parent waits */
return 0;
}
int main(void){
foo("parent");
func();
return 0;
}
You can't exit the loop for a simple reason, and that is, you spawn child processes endless. Whenever you fork() a new process starts, then it forks again.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int n=5;
int foo(const char *whoami) {
printf("I am a %s. My pid is:%d my ppid is %d\n", whoami, getpid(), getppid() );
return 1;
}
int func(int n)
{
if (n == 0)
{
return 0;
}
int pid = fork();
if (pid == -1) {
exit(0);
}
if (pid==0) {
foo("child");
n = n-1;
func(n);
exit(0);
}
else {
wait(NULL);
}
return 0;
}
int main()
{
func(n);
return 0;
}
gcc -std=c99 prog.c -o prog
./prog
OUTPUT:
I am a child. My pid is: 1159 my ppid is 1158
I am a child. My pid is: 1160 my ppid is 1159
I am a child. My pid is: 1161 my ppid is 1160
I am a child. My pid is: 1162 my ppid is 1161
I am a child. My pid is: 1163 my ppid is 1162
From what you are saying i understand you are having the following problems:
1st. You are trying to send 'data' from one process to another
2nd. You are trying to find a way to stop your program from running.
Now for the first. If you want to do that and i understood it correctly, there are 2 ways to achieve that. One is the use of shared memory and the other is the use of pipelines. Shared memory is pretty obvious on what is doing. Pipes are taking the stdout of a process and redirecting it as a stdin in the next process.
Now you need a closure to your program. A child process is executed when it executes a command(exec) or when it is told so(with an IF statement for example and a return). You can create a statement of your liking, and when a child process meets your requirments then you can make it die(There is also a way to kill the parent process from the child process with the kill(pid, SIGKILL); command.
I didn't provide you with any code because it is unclear to me the exact nature of your problem.
Hope my assuming led you to something!

Calling every child process at once to kill?

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.

Resources