How to send signal from a children to another children in C? - c

How can I send a signal form passenger-children to the taxi - children?
I have the following C code:
passengerPid = fork()
if(passengerPid) { //passenger-parents
taxiPid = fork();
if(taxiPid) { //taxi - parents
} else { //taxi - children
}
}
else { //passenger - children
}

How can I send a signal form passenger-children to the taxi - children? yes it's possible but question here is how will you get taxi-children pid in passenger-children process ? once you got pid of that taxi-children, for sending signal to one process from another process you can use kill() function. Use any IPC mechanism to sending pid(any int data) of one process to other process.
Here is my Solution, before this go through man page of wait() & waitpid() :
/**How can I send a signal form passenger-children to the taxi - children? **/
#include<stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
int passengerPid, taxiPid;
passengerPid = fork();
if(passengerPid) { //passenger-parents
taxiPid = fork();
if(taxiPid) {
//taxi - parents
printf("taxi parents or main parent process : pid = %d ppid = %d\n",getpid(),getppid());
/** parents should wait until all children's got finish
use wait() or waitpid() to collect the children's status **/
int s,ret;
while((ret = wait(&s))!=-1)//if there is no further child, wait returns
{
if(ret == passengerPid) {
if(WIFEXITED(s)) {
printf("passenger children removed after sleep, status is : %d\n",WEXITSTATUS(s));
} else if(WIFSIGNALED(s)) {
printf("passenger children removed forcefully because of signal no : %d \n",WTERMSIG(s));
}
} else if(ret == taxiPid) {
if(WIFEXITED(s)) {
printf("taxi children removed after sleep, status is : %d\n",WEXITSTATUS(s));
} else if(WIFSIGNALED(s)) {
printf("taxi children removed forcefully because of signal no : %d \n",WTERMSIG(s));
}
}
}
printf("all done !! parents is also going to complete \n");
}
else {
//for sending pid of this process
#if 0
int fd = open("data",O_WRONLY | 0664);
if(fd == -1) {
perror("open");
return 0;
}
int w_pid = getpid();
write(fd,&w_pid,4);
close(fd);
#endif
//taxi - children
printf("taxi children : pid = %d ppid = %d\n",getpid(),getppid());
sleep(10);//random delay to observe whether this process got any signal or not ?
exit(1);//sends it's exit status to it's parent process whether it's terminated normally or by any external signal
}
}
else {
//passenger - children
printf("passenger children : pid = %d ppid = %d\n",getpid(),getppid());
printf("sending signal from passenger children to taxi children :\n");
sleep(5);
int pid;
#if 0
int fd = open("data",O_RDONLY | 0664);
if(fd == -1) {
perror("open");
return 0;
}
read(fd,&pid,4);
close(fd);
#endif
printf("pid of child received : %d \n",pid);
kill(pid,SIGKILL);//sending signal no 2 to taxi child, bydefault action of SIGINT will be performed
perror("kill");
printf("passenger children dies after sending signal & completion of delay\n");
exit(0);
}
}
how above code works is explained in comments itself. usage of macro(#if 0) part in both process is for sending pid of that taxi-child process to passenger-child process. Enable the macro for observing the output.
I hope it help's.

Related

How to send a signal around specific processes?

I'm trying to send a signal around circle of processes for a certain amount of times. my first argument represents the number of processes I wish to create. my second one is just a place holder I am currently initiating to be 0. My third is the number of time I want to pass this signal around. I have designed the processes to have a relationship as such: Parent->child1,
child1->child2, child2->child3.... and so on. I'm just figuring out C and I'm confused to why my code is stopping midway. It runs for an iteration or two and then stalls out. Can someone explain why?
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int startProcess;
int N;
int numOfCycles;
sigset_t killSet;
void myHandler1 () {
if(N >= 2 && numOfCycles > 0) {
printf("N=%d, numOfCycles=%d, Signal caught. PID = %d\n",N,numOfCycles,getpid());
numOfCycles--;
kill((getpid()+1),SIGUSR1);
}
else if(N >= 2 && numOfCycles == 0) {
exit(1);
}
else if(N == 1 && numOfCycles > 0) {
printf("N=%d, numOfCycles=%d, Signal caught. PID = %d\n",N,numOfCycles,getpid());
numOfCycles--;
kill(startProcess,SIGUSR1);
}
else if(N == 1 && numOfCycles == 0) {
exit(1);
}
else {
printf("Cycle Complete\n");
exit(1);
}
}
void main(int arg, char ** argv) {
struct sigaction temp, vitas, arctic;
sigemptyset(&killSet);
sigaddset(&killSet,SIGUSR1);
N = atoi(argv[1]);
pid_t process1;
startProcess = atoi(argv[2]);
numOfCycles = atoi(argv[3]);
temp.sa_handler = myHandler1;
temp.sa_flags = SA_RESTART;
// vitas.sa_handler = myHandler2;
// vitas.sa_flags = SA_NODEFER;
//
// arctic.sa_handler = myHandler3;
// arctic.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &temp, NULL);
if (N > 1 ) {
process1 = fork();
if(process1 == 0) {
if(N > 2) {
printf("I am a child with PID=%d, PPID=%d, N =%d\n",getpid(),getppid(),N);
}
N--;
char narg = N+'0';
char *pnarg = &narg;
if(startProcess == 0) {
char nstartProcess[6];
startProcess=getppid();
sprintf(nstartProcess,"%d",startProcess);
char *pstartProcess = &nstartProcess[0];
execl("circle",argv[0],pnarg,pstartProcess,argv[3],NULL);
}
else{
if(N == 1){
printf("I am the final child with PID=%d, PPID=%d, N =%d, startProcess=%d\n",getpid(),getppid(),N,startProcess);
printf("\nSignal Passing start\n\n");
kill(startProcess, SIGUSR1);
while(1) {
sigsuspend(&killSet);
}
}
else {
execl("circle",argv[0],pnarg,argv[2],argv[3],NULL);
}
}
}
else {
printf("I am a parent with PID=%d, PPID=%d, N =%d, startProcess=%d\n",getpid(),getppid(),N,startProcess);
wait(NULL);
while(1) {
sigsuspend(&killSet);
}
}
}
}
stalls out. Can someone explain why?
The final child is not woken up from sigsuspend(&killSet) because you did sigaddset(&killSet,SIGUSR1); - you seem to have thought you have to add the signal to be waited for to the set, but on the contrary the signals in the given set are blocked from delivery. So just drop the sigaddset call.
To add to #Armali and as the sigset was not the only point to consider, it's seems more simple to provide an implementation with a far more simple handler and which avoid fork+exec, you'll found explanations in the comments. I'm not sur i'have understood what is your intent, from the comments i guess that you are looking to launch N processus with the last one sending cycles time SIGUSR1 to the parent, each child processus sending SIGUSR1 to their parent on receipt. Correct me if i'm wrong.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int startProcess;
int N;
int numOfCycles;
sigset_t killSet;
// Two counters for the signal handler
int numSignals=0;
int numSignalsTotal=0;
// A simple handler that do nothing else that incrementing values in the process.
// To use a SIGINFO handler : void myHandler1 (int signal, siginfo_t *info, void *ucontext) {
void myHandler1 (int signal) {
numSignals++;
numSignalsTotal++;
}
void main(int arg, char ** argv) {
struct sigaction temp;
// As Armali pointed that, here you should not add SIGUSR1 to the sigset a you want
// to suspend your process and waiting for it.
sigemptyset(&killSet);
N = atoi(argv[1]);
pid_t process1 = 0;
startProcess = atoi(argv[2]);
numOfCycles = atoi(argv[3]);
// A more complete initialization here, you need to include SIGUSR1 here to associate it
// to your handler. It seems you doesn't need specific flag like SA_RESTART for it here,
// as the handler code doesn't require that.
temp.sa_handler = myHandler1;
sigemptyset(&temp.sa_mask);
sigaddset(&temp.sa_mask,SIGUSR1);
temp.sa_flags = 0;
temp.sa_restorer = NULL;
// Always check that your function calls return OK. Always.
if (sigaction(SIGUSR1, &temp, NULL) != 0) {
perror("ERR: Failed to set handler ...");
exit(1);
}
// Instead of a mix of fork + exec, it is more simple to keep one process and fork it for each new process.
// Here, we fork at least once, the parent process will alaways be "PARENT" and have a 0 startProcess,
// the child processes will fork themselves, the parent process is their and the new forked one will be
// the next child.
while (startProcess == 0 || N > 1 ) {
process1 = fork();
// To follow the forks : printf(" Fork pid=%d %s %s %s %s\n", process1, argv[0],argv[1],argv[2],argv[3]);
if(process1 != 0 && startProcess == 0) {
// If fork() gives us a pid and we have startProcess 0, then we are the "PARENT" process.
// The only thing we have to do is waiting for signals from our childs, if there is childs.
printf(" I am a parent with PID=%d, PPID=%d, N =%d, startProcess=%d\n",getpid(),getppid(),N,startProcess);
// If there's no child, we simply quit the loop.
if (N == 1) break;
// For reference, "PARENT" output what is its first child.
printf(" -> child = %d\n" , process1);
// Here, while we have cycles, we wait for signals
while(numOfCycles > 0) {
// If you use a handler, you need to operate synchronously with it, so here we block SIGUSR1 as we will wait for it.
if (sigprocmask(SIG_BLOCK, &temp.sa_mask, NULL) != 0) {
perror("ERR: Failed to block usr1...");
exit(1);
}
// We wait for a SIGUSR1.
sigsuspend(&killSet);
// We have a SIGUSR1, we unblock SIGUSR1 as we will modify numSignals and don't want handler doing that at the same time.
if (sigprocmask(SIG_UNBLOCK, &temp.sa_mask, NULL) != 0) {
perror("ERR: Failed to unblock usr1...");
exit(1);
}
// We output on STDOUT that "PARENT" caught a SIGUSR1, we should have the number of signals received in numSignals
printf(" ===> PARENT : N=%d, numOfCycles=%d, Signal caught. PID = %d, count = %d\n",N,numOfCycles,getpid(), numSignals);
// We substract that from our cycles and reset numSignals
numOfCycles-=numSignals; numSignals=0;
}
// If we are here, no more cycles, so we output on STDOUT a summary of "PARENT" processing
printf(" PARENT : N=%d, PID = %d, total = %d\n",N,getpid(), numSignalsTotal);
// Before leaving, "PARENT" should wait for its potential remaining childs to exit
printf(" PARENT waiting for child to terminate.\n");
if (wait(NULL) == -1) {
perror("ERR: PARENt failed to wait for childs termination...");
exit(1);
}
// We quit the loop, so we exit
break;
} else {
// If only one process (N=1) was asked, nothing more to do for the fork, we quit the loop then exit
if (N == 1 && startProcess == 0) break;
// We get the parent process pid in startProcess, as we are a child process
startProcess = getppid();
// If we are the forked process, we decrement N, it will "our" N as child
if (N > 1 && process1 == 0) {
N--;
}
if(process1 == 0) {
// If we are the forked process, we simply state our identity on STDOUT, the final child should be the one with N=1
if (N > 1) {
printf(" I am a child with PID=%d, PPID=%d, N =%d, startProcess=%d\n",getpid(),getppid(),N,startProcess);
} else {
printf(" I am the final child with PID=%d, PPID=%d, N =%d, startProcess=%d\n",getpid(),getppid(),N,startProcess);
}
if (N == 1) {
// If we are the final child, we simply have to send SIGUSR1 signals to our parent process for the number of cycles,
// after that we simply quit the loop and exit, no more forks are required.
while(numOfCycles > 0) {
printf("\n Cycle %d, first Signal start to %d\n\n", numOfCycles--, startProcess);
if (kill(startProcess, SIGUSR1) != 0) {
perror("ERR: LAST CHILD : Failed to send USR1...");
exit(1);
}
}
break;
}
// Note that if we are NOT the final child, we have to go through the loop to fork a new process for the next child.
} else {
if (N > 1) {
// If we are here, we are the forked process for a child and we are not the final child.
// So we do our payload, waiting for SIGUSR1 signals from our child and sending SIGUSR1 to our parent for the
// required number of cycles.
while(numOfCycles > 0) {
// If you use a handle, you need to operate synchronously with it, so here we block SIGUSR1 as we will wait for it.
if (sigprocmask(SIG_BLOCK, &temp.sa_mask, NULL) != 0) {
perror("ERR: Failed to block usr1...");
exit(1);
}
// We wait for a SIGUSR1.
sigsuspend(&killSet);
// We have a SIGUSR1, we unblock SIGUSR1 as we will modify numSignals and don't want handler doing that at the same time.
if (sigprocmask(SIG_UNBLOCK, &temp.sa_mask, NULL) != 0) {
perror("ERR: Failed to unblock usr1...");
exit(1);
}
// We output on STDOUT that this child caught a SIGUSR1, we should have the number of signals received in numSignals
printf(" ===> CHILD: N=%d, numOfCycles=%d, Signal caught. PID = %d, count = %d\n",N,numOfCycles,getpid(), numSignals);
// For each receveid signals from our child, we send one to our parent
while (numSignals > 0) {
printf("\n Signal Passing start to %d\n\n", startProcess);
if (kill(startProcess, SIGUSR1) != 0) {
perror("ERR: CHILD : Failed to send USR1...");
exit(1);
}
// We decrement accordingly our number of cycles and signals
numOfCycles--;
numSignals--;
}
}
// If we are here, no more cycles, so we output on STDOUT a summary of the child processing
printf(" CHILD : N=%d, PID = %d, total = %d\n",N,getpid(), numSignalsTotal);
// We quit the loop, so we exit, then terminate our child
break;
}
}
}
}
// We should always restore signal handler to default when we exit.
temp.sa_handler = SIG_DFL;
sigemptyset(&temp.sa_mask);
sigaddset(&temp.sa_mask,SIGUSR1);
temp.sa_flags = 0;
temp.sa_restorer = NULL;
// Always check that your function calls return OK. Always.
if (sigaction(SIGUSR1, &temp, NULL) != 0) {
perror("ERR: Failed to restore SIGUSR1 ...");
exit(1);
}
// We output on STDOUT the related PID at each process termination.
printf(" End of PID %d\n",getpid());
}

Create multiple generations of children process

So I'm trying to understand the concept of grandchildren.
I'm able to create a given number of sons (i.e brothers) but I don't know how to create multiple generations .
This is what I did to create one grandson :
int main ()
{
//Displaying the father
printf("Initial : Father = %d\n\n", getpid());
/****** FORK *******/
pid_t varFork, varFork2;
varFork = fork();
if(varFork == -1) //If we have an error, we close the process
{
printf("ERROR\n");
exit(-1);
}
else if (varFork == 0) //if we have a son, we display it's ID and it's father's
{
printf("SON 1\n");
printf(" ID = %d, Father's ID = %d\n", getpid(), getppid());
varFork2 = fork();//creation of the second fork
if(varFork2 == -1) //If we have an error, we close the process
{
printf("ERROR\n");
exit(-1);
}
else if (varFork2 == 0) //now we have the son of the first son, so the grandson of the father
{
printf("\nGRANDSON 1\n");
printf(" ID = %d, Father's ID = %d\n", getpid(), getppid());
}
else sleep(0.1);/*we wait 0.1sec so that the father doesn't die before we can
display it's id (and before the son process gets adopted by a user process descending from the initial process)*/
}
else //in the other case, we have a father
{
sleep(0.1);//again we put the father asleep to avoid adoption
}
return 0;
}
How can I create X generations of grandsons, X being a global variable (1son, 1 grandson, 1 great-grandson, etc.) ?
How can I create X generations
Before forking, decrement X and continue forking inside the child until X is 0.
Or inside the child decrement X and only continue forking if after decrementing it X still is greater 0.
The code might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
void logmsg(const char *, int);
#define MAX_GENERATIONS (4)
int main(void)
{
pid_t pid = 0;
for (size_t g = 0; g < MAX_GENERATIONS; ++g)
{
logmsg("About to fork.", 0);
switch (pid = fork())
{
case -1:
{
logmsg("fork() failed", errno);
break;
}
case 0:
{
logmsg("Hello world. I am the new child.", 0);
break;
}
default:
{
char s[1024];
snprintf(s, sizeof s, "Successfully created child carrying PID %d.", (int) pid);
logmsg(s, 0);
g = MAX_GENERATIONS; /* Child forked, so we are done, set g to end looping. */
break;
}
}
}
logmsg("Sleeping for 3s.", 0);
sleep(3);
if (0 != pid) /* In case we forked a child ... */
{
logmsg("Waiting for child to end.", 0);
if (-1 == wait(NULL)) /* ... wait for the child to terminate. */
{
logmsg("wait() failed", errno);
}
}
logmsg("Child ended, terminating as well.", 0);
return EXIT_SUCCESS;
}
void logmsg(const char * msg, int error)
{
char s[1024];
snprintf(s, sizeof s, "PID %d: %s", (int) getpid(), msg);
if (error)
{
errno = error;
perror(s);
exit(EXIT_FAILURE);
}
puts(s);
}
The output should look similar to this:
PID 4887: About to fork.
PID 4887: Successfully created child carrying PID 4888.
PID 4887: Sleeping for 3s.
PID 4888: Hello world. I am the new child.
PID 4888: About to fork.
PID 4888: Successfully created child carrying PID 4889.
PID 4888: Sleeping for 3s.
PID 4889: Hello world. I am the new child.
PID 4889: About to fork.
PID 4889: Successfully created child carrying PID 4890.
PID 4890: Hello world. I am the new child.
PID 4890: About to fork.
PID 4889: Sleeping for 3s.
PID 4890: Successfully created child carrying PID 4891.
PID 4890: Sleeping for 3s.
PID 4891: Hello world. I am the new child.
PID 4891: Sleeping for 3s.
PID 4888: Waiting for child to end.
PID 4890: Waiting for child to end.
PID 4891: Child ended, terminating as well.
PID 4890: Child ended, terminating as well.
PID 4887: Waiting for child to end.
PID 4889: Waiting for child to end.
PID 4889: Child ended, terminating as well.
PID 4888: Child ended, terminating as well.
PID 4887: Child ended, terminating as well.
The difference with my code above compared to the proposal I made is that it counts upwards to X.

Create new process in separate function [c]

I wanna create spare process (child?) in specific function called eg. void process(). I want just to create that child process and do nothing with it. I just wanna it alive and do nothing while main() of my app will be working as I want.
In some point of my app's main() I will be killing child process and then respawn it again. Any ideas how to do that ?
I have something like that but when I'm using this function to create process I get everything twice. Its like after initiation of process() every statement is done twice and i dont want it. After adding sleep(100) after getpid() in child section seems working fine but I cannot kill it.
int process(int case){
if(case==1){
status=1;
childpid = fork();
if (childpid >= 0) /* fork succeeded */
{
if (childpid == 0) /* fork() returns 0 to the child process */
{
printf("CHILD PID: %d\n", getpid());
}
/* fork() returns new pid to the parent process *//* else
{
}*/
}
else
{
perror("fork");
exit(0);
}
}
else{
if(status!=0){
status=0;
//kill!!!!
system(a); //getting kill -9 PID ; but PID is equal 0 here...
printf("\nkilling child");
}
}
}
how to just spawn new child process and let it just exist, like some sort of worker in C#?
Assuming you are in Linux, here's an example that might clarify your view: parent process spawns a child, the child calls pause() which suspends it until a signal is delivered, and finally parent process kill's the child with SIGKILL.
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if (pid < 0) { perror("fork"); exit(0); }
if (pid == 0) {
printf("Child process created and will now wait for signal...\n");
pause(); //waits for signal
}
else {
//do some other work in parent process here
printf("Killing child (%ld) from parent process!", (long) pid);
kill(pid, SIGKILL);
}
return 0;
}
Please note that fork() returns:
<0 on failure
0 in child process
the child's pid in parent process.

Interprocess Communication fork() - Timing wait() and/or sleep()

I've been asked to develop the consumer (client) side to a producer (server), where the producer creates processes, waits until the consumer has read shared memory and deleted processes, then passes control back to the producer for the killing of processes and the shutting down of the shared memory block.
I've researched the difference between sleep and wait, and realise that as soon as fork() is called, the child process begins running.
The below code is after the creation of processes and checks if they're parent processes. If they are, they wait(0). *Now for my question, how do I know where the code in the consumer starts to be executed, and how do I pass it back? *
else if(pid > 0)
{
wait(0);
}
Below can be seen the main loop the producer uses.
int noToCreate = atoi(argv[2]); // (user inputs on cmd line "./prod 20 10 5" - 20 size of shared mem, 10 process to be created, 5 processes to be deleted)
while(*memSig != 2)
{
while(*memSig == 1) // set memsignature to sleep while..
{
sleep(1);
}
for(B = 0; B < noToCreate; B++)
{
pid = fork();
if(pid == -1)
{
perror("Error forking");
exit(1);
}
else if(pid > 0)
{
wait(0);
}
else
{
srand(getpid());
while(x == 0)
{
if(*randNum == 101)
{
*randNum = rand() % (100 -
1) + 1;
*pidNum = getpid();
printf("priority: %d
Process ID: %d \n", *randNum, *pidNum);
x = 1;
}
else
{
*randNum++;
*pidNum++;
}
}
exit(0);
}
} /* Closes main for loop */
if(*memSig == 0)
{
*memSig = 1;
}
} /* Closes main while loop */
Thanks a bunch guys :)
wait make parent blocked until any child end .You can use waitpid let parent wait specific child.
When a child process end, it will set a signal SIG_CHILD.
The pid is zero for the child process after the fork, so you are in the child process at your call to the srand function.
The other pid is that for the child process which allows he original thread to wait for the child to finish. If you wish to pass data between the processes consider using a pipe. A popen call returns two file descriptors, one to write end and the other to the read end. Set this up before the fork and the two processes can communicate.
wait makes the parent wait for any child to terminate before going on (preferably use waitpid to wait for a certain child), whereas sleep puts the process to sleep and resumes it, as soon as the time passed as argument is over.
Both calls will make the process block.
And it is NOT said that the child will run immediately, this is indeterminate behavior!
If you want to pass data between producer and consumer, use pipes or *NIX sockets, or use the return-value of exit from the child if a single integer is sufficient.
See man wait, you can get the return value of the child with the macro WEXITSTATUS.
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));
} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

how to create two processes from a single Parent

I know I'm going to need to use fork(), but this just creates a single child process. Do i simply call fork again from within the child process? Also, I need them to communicate through a signal or pipe, which is easier to implement and what do i need to know for doing that (functions, etc..)
To create a second process, call fork() again - either within the parent or the child (but not both!). Which you choose depends on whether you want this process to be a child of the original parent or a child of the first child process (it is usual for it to be a child of the original parent).
Communicating through a pipe is much simpler and more reliable than using signals. pipe(), close(), read(), write() and select() are the key functions here.
For example, to have the parent create two child processes, you would do something like:
pid_t child_a, child_b;
child_a = fork();
if (child_a == 0) {
/* Child A code */
} else {
child_b = fork();
if (child_b == 0) {
/* Child B code */
} else {
/* Parent Code */
}
}
Another fancy code using && operator:
pid_t c1_pid, c2_pid;
(c1_pid = fork()) && (c2_pid = fork()); // Creates two children
if (c1_pid == 0) {
/* Child 1 code goes here */
} else if (c2_pid == 0) {
/* Child 2 code goes here */
} else {
/* Parent code goes here */
}
#include <stdio.h>
#include <unistd.h>
void main(){
int pi_d ;
int pid ;
pi_d = fork();
if(pi_d == 0){
printf("Child Process B:\npid :%d\nppid:%d\n",getpid(),getppid());
}
if(pi_d > 0){
pid = fork();
if(pid > 0){
printf("\nParent Process:\npid:%d\nppid :%d\n",getpid(),getppid());
}
else if(pid == 0){
printf("Child Process A:\npid :%d\nppid:%d\n",getpid(),getppid());
}
}
}
output :
Parent Process:
pid:3648
ppid :2379
Child Process B:
pid :3649
ppid:3648
Child Process A:
pid :3650
ppid:3648
You can put the fork in a loop and generate as many child processes as you need.
I did that on a project recently.
for(nSon=0; nSon < nSonsAsked; nSon++) {
Log_Print("Setup son #%.2u ", nSon+1);
if((pid = fork()) == 0) {
/* Do child stuff init, like connect the pipes, close shared handles */
return iTMInChild(...); /* A specific function of the child work */
/* The life of the child should not go beyond that point, i.e. the loop is over
or else the child will spawn even more processes. */
}
else if(pid > 0) {
/* Father process stuff. Here I initialise an array with the pid of the forked */
/* processes, this way I can index with the number of processes.*/
pid[nSon] = pid;
}
else
return Err_Print(ERR_FORK_FAILED, "fork failed. errno=%d \"%s\"\n", errno, strerror(errno));
}
Log_Print() and Err_Print() are internal functions but quite obvious so I let them like they are.
There is one aspect with the variables that has to be explained. nSon and nSonAsked should be declared as globals not as stack variables. This way, their value persists in the forked process. This means that the nSon variable will have a different value in each of the children. This allows it to have a simpler numbering scheme than the ownpid() number.
To get it completely right, there are a lot of details to get right. You will have to set signal handlers in the father process to detect the death of a child, likewise the other way round (only possible on Linux, other Unix (at least Solaris) do not support parent death signals).
You have to be aware that open file descriptors in the father process will be also open in the child after fork and it will be the same one. This opens a lot of concurrency problems if you're not aware of it (the solution is using dup() and close() in the right places).
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
system ("clear");
int i ;
pid_t childa,childb,childa1,childa2,childb1,childb2;
printf("\n \t \t I am the parent process with ID %d \n",getpid());
childa=fork();
if (childa == 0 )
{
printf("\nI am a child A with PID %d and my parent ID is %d\n",getpid(),getppid());
}
else
{
childb = fork();
if (childb == 0)
{
printf("\nI am Child B with ID %d and my parent ID is %d\n",getpid(),getppid());
}
else
{
sleep(1);
}
}
}
In this example they are just sleeping for a few random sec. It also has all the pid, so we can send SIGNAL to communicate... Most of the #includes are commented cause they were useless where I compiled.
#include <stdlib.h> // exit() ...
#include <stdio.h> // printf() ...
// Compile with -lrt -> cc file_name.c -lrt
//#include <fcntl.h>
//#include <sys/stat.h>
//#include <sys/types.h>
//#include <sys/wait.h> // may need this for wait()
//#include <time.h>
//#include <unistd.h> // and this one for fork()
// In the start function you can do whatever you want.
void start (const int azon) {
// For children processes
srand( time(NULL) );
unsigned t = rand()%5; // printf("%d\n", t);
sleep(t);
printf("%d. process reached the end.\n", azon);
exit(0);
}
int main() {
const int N = 5;
pid_t pids[N];
int i;
// The 'for' loop make 'N' process with 'fork()'.
// The children processes will call the start function.
// Since after fork() you will get 2 process. One Parent, and One Child
// The returning value from fork() is saved in "pids" which is an
// integer AND it is (<0) IF something went wrong.
// it is (>0) IF 'we are' in the Parent process,
// because this number is the Child process' ID (pid).
// and Last it is (==0) IF 'we are' in the Child process.
for (i = 0; i < N; i++) {
pids[i] = fork();
sleep(1);
if (pids[i] == 0) start(i+1); // ... OR you can make a switch(..)
}
// This 'for' loop in the wait(NULL) statement ONLY move on when a
// process ended, so it waits until 'N' proc ends.
for (i = 0; i < N; i++)
wait(NULL);
printf("Partent process reached the end\n");
return 0;
}
Just a little contribution, if you want to create 2 childs from the same parent you could use this code below. In which one father create 2 child processes (lazy and active).
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main (){
pid_t lazy_child;
lazy_child = fork();
if(lazy_child == 0){ // This is the lazy child process.
printf("LAZY CHILD:%d\n", getpid());
}
else if(lazy_child > 0){ // This is the father process.
pid_t active_child = fork();
if(active_child == 0){ // This is the active child process.
printf("ACTIVE CHILD:%d\n", getpid());
}
else if(active_child > 0){ // This is the father process.
printf("FATHER:%d\n", getpid());
}
else{ // Fork doesnt work.
printf("fork error\n");
exit(1);
}
}
else{ // Fork doesnt work.
printf("fork error\n");
exit(1);
}
return 0;
}
If you run this code, you should get a similar output:
$ ./a.out
FATHER:14501
ACTIVE CHILD:14503
LAZY CHILD:14502
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t AliceID, BobID;
double n=0;
int i1 =0;
/* fork a child process */
AliceID = fork();
if (AliceID < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (AliceID == 0) { /* child Alice code */
for(int i=1; i<11; i++)
{n = n+i;
i1++; }
double avg1 = n/i1;
printf("From Alice: the average of 1,2, …, 10 is the-average-she-calculated");
printf(" sum = %.2f and avg = %.2f \n",n, avg1);
}
else {
BobID = fork();
if (BobID == 0) { /* Child Bob code */
printf("From Bob: I am born to print this and then die.\n");
} else { /* Parent Code */
/* parent will wait for the child to complete */
wait(NULL);
printf("From parent: AliceID is %d \n", AliceID);
printf("From parent: Bob is %d \n", BobID);
printf("Parent ID %d \n", getpid());
}
}
return 0;
}

Resources