Create a chain of n sub processes - c

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!

Related

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.

Child processes with fork

I am trying to make a simple C program that will call the fork method three times and display identifiers of child processes (UID, GID, PID, PPID, PGID). And I am struggling with proper understanding what is really happening. There is my code in which I use separate methods for method fork() and for displaying identifiers, and also in for for parent process I am trying to use the waitpid method to wait for all child processes to die. I am really confused now because I cannot get it working in a way that clearly says it works in proper way. Can you give me any suggestions or show a better way for my problem?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void identifiers();
void forkMethod();
int main(void)
{
forkMethod();
return 0;
}
void forkMethod()
{
int k;
int status;
for (k=0;k<3;k++){
switch (fork()) {
case -1:
perror("fork error");
exit(EXIT_FAILURE);
break;
case 0:
identifiers();
break;
default:
//wait(&status);
waitpid(getpid(), &status, WNOHANG);
sleep(1);
break;
}
}
}
void identifiers()
{
pid_t pid = getpid();
pid_t ppid = getppid();
pid_t pgid = getpgid(pid);
pid_t uid = getuid();
pid_t gid = getgid();
printf("UID:%d GID:%d PID:%d PPID:%d PGID:%d\n", uid, gid, pid, ppid, pgid);
}
// ===========================================================
First thank you all for answers and pointing all of these mistakes I made,
I know the code is horrible and probably still have a few issues but now i think i have what i wanted to.
As #John Bollinger ask what is main functionality that is my list:
1. Write a function that displays identifiers UID, GUID, PID, PPID, PGID for specified process
2. call fork() function 3 times and display these identifiers for child processes
3. Use the sleep function to display processes in order from the oldest
4. display a processes tree based on results.
Thank you #juhist and #Jonathan Leffler for sharp and simple explanation. If there any significant issues in code please post
and know the final code is:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void identifiers(); // function that display identifiers
void forkMethod(); // function that calls fork() function 3 times
void tree(int); // function displaying processes tree
int main(void)
{
identifiers(); // displaying ID's for parent process
printf("Parent pid: %d\n", getpid());
printf("Child processes: \n");
forkMethod();
return 0;
}
void forkMethod()
{
int k;
int status;
int pid;
for (k=0;k<3;k++){
pid = fork();
switch (pid) {
case -1:
perror("fork error");
exit(EXIT_FAILURE);
break;
case 0:
identifiers();
exit(0);
default:
tree(getpid());
wait(&status);
sleep(1);
break;
}
}
}
void identifiers()
{
pid_t pid = getpid();
pid_t ppid = getppid();
pid_t pgid = getpgid(pid);
pid_t uid = getuid();
pid_t gid = getgid();
printf("\nUID:%d GID:%d PID:%d PPID:%d PGID:%d\n", uid, gid, pid, ppid, pgid);
}
void tree(int pid)
{
char pstree[] = "pstree -np ";
char cmd[12];
sprintf(cmd, "%s%d", pstree, pid);
system(cmd);
}
One of your problems is in this code:
case 0:
identifiers();
break;
Surely you meant to do this instead:
case 0:
identifiers();
exit(0);
Otherwise the child process will continue execution and you will get too many forks.
The other problem is that you're calling waitpid() with the parent pid, not the child pid. The calls does nothing useful as you're using the WNOHANG argument. Either use wait() or store the pid of the child as returned by fork somewhere and use that pid as the argument of waitpid().
Furthermore, you should consider checking the return value of waitpid(). In larger programs, if you have signal handlers it is possible that the call will be interrupted by signal and returns an error code with errno == EINTR. It is good practice to retry system calls interrupted by a signal and check for other possible error returns, too.
On this line:
waitpid(getpid(), &status, WNOHANG);
The getpid() will always get the parent pid, not the pid of the child.
Suggest changing switch(fork()) to
pid= fork(); switch(pid) { ... }
and the waitpid line to
waitpid(pid, &status, 0);

IPC Pipe in Linux C

It's a simple code which makes two child processes communicate: first one execute "ls" and pass the output into myfd[1]; second one receives the output from myfd[0], and then execute "sort"(and shows the result). The parent process waits for these two processes.
But this code doesn't work. It gets stuck at the second child process. Any possible reason why?
Did I use the right "close" and "dump" in proper place?
my code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void)
{
int pid;
int wpid;
int status = 0;
int myfd[2];
printf("parent's pid: %d\n",getpid());
pipe(myfd);
pid = fork();
if(pid == 0) // child 1 - execute "ls"
{
printf("child1's pid: %d\n",getpid());
close(1);
dup(myfd[1]);
close(0);
close(myfd[0]);
execlp("ls","child_process1",NULL);
}
else
{
pid = fork();
if(pid == 0) // child 2 - execute "sort"
{
printf("child2's pid: %d\n",getpid());
close(myfd[1]);
close(0);
dup(myfd[0]);
execlp("sort","child_process2",NULL);
}
}
// parent
while((wpid = wait(&status)) > 0)
{
// wait until two child processes finish
}
printf("done!\n");
}

Explanation of code - fork, wait, execv

I'm trying to understand what the following code does:
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include <unistd.h>
int main(void) {
int pid;
for(;;) {
pid = fork();
printf(getpid());
if(pid == -1) {
printf("fork failed");
exit(1);
}
if(pid == 0) {
execv("MYFORKAPP", NULL);
exit(2);
}
wait();
}
return 0;
}
The program itself is called MYFORKAPP. I'm learning about these 3 functions and I saw this code on the internet and I don't understand what it does.
I tried to run it (Fedora GCC) but the terminal is empty.
Should it at-least print the first getpid()?
Can you please explain me this code?
printf(getpid());
This may crash the program. printf() expects its first argument be a string, but getpid() will return a integer, so this integer will be used as a pointer to an array of character, this very likely leads to a crash, i.e. segmentation fault.
Besides that, what this program does is
fork() a child process and wait()
this child process will execuate the same program again
so it will fork() and wait()
and so on, until your system does not have enough resource to create new process
then fork() will fail, these different level child processes will exit one by one
finally, the first process created by your shell will exit, and the program ends.
What the following code does - segmentation fault.
Must be:
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include <unistd.h>
int main(void) {
int pid;
for(;;) {
pid = fork();
if(pid == -1) {
printf("fork failed");
exit(1);
}
if(pid == 0) {
printf("child has pid %d\n", getpid());
execv("MYFORKAPP", NULL);
exit(2);
}
wait();
}
return 0;
}
This is a loop:
1. Parent creates a child process.
2. Child turnes to MYFORKAPP.
3. Parent wait for the child process.
4. Child terminates (may be).
5. goto 1

Creating a process that is not child of the process that created it

I want to create a process B from process A. However, I don't want B to be the child of A, which will be the case if I simply use fork. How can I achieve that? In other words I want process B to keep on executing even if process A is killed.
You can use the setsid() function.
Alternatively, as you have tagged your question "linux", maybe you want to use daemon() instead of fork() + setsid().
Why do you think that B would not keep executing after A is killed if B is a child of A? That's not true.
But if you still want B to not be a child of A then you can do this by fork()ing twice: once to create a child A½ and once to create B. B is a child of A½ and a grandchild of A. Then have A½ exit immediately. B will be inherited by init and will have no further relationship to A.
If you are concerned about signals like SIGHUP and SIGINT that are generated in response to events like a Control-C keypress that are broadcast to the entire foreground process group, see cnicutar's answer.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
switch(pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf(" CHILD: This is the child process!\n");
printf(" CHILD: My PID is %d\n", getpid());
printf(" CHILD: My parent's PID is %d\n", getppid());
/* you can exec another program here if you wish to */
printf(" CHILD: I'm outta here!\n");
break;
default:
printf("PARENT: This is the parent process!\n");
printf("PARENT: My PID is %d\n", getpid());
printf("PARENT: My child's PID is %d\n", pid);
printf("PARENT: I'm not going to wait for my child to exit\n");
signal(SIGCHLD, SIG_IGN);
printf("PARENT: I'm outta here!\n");
}
return 0;
}
If you don't send the signal(), then once after the parents completes the execution (and exits), the child process will be termed as a zombie process. For better understanding, execute the following program.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
/*
Execute this program and do 'ps ax | grep Z' to see that this
is put in a defunct state or zombie state
*/
int main()
{
pid_t child_pid;
child_pid = fork();
if (child_pid > 0) {
sleep(60);
} else {
return 0;
}
return 0;
}
The only way I see is having the child orphan (then adopted by init).
This may be achieved by terminating the father process before the child (but just take care of signal propagation).
Some nice samples may be found here

Resources