Amount of process - c

Do I understand correctly that 2 processes are created in the code below? Since one fork () call creates one thread. There are two such calls in the code, therefore, the process is created 2?
#include <stdio.h>
#include <stdlib.h>
int main() {
int x,y;
pid_t pidl, pid2;
x = 2;
y = 3;
printf ("Single process, x=$d\n",x);
pidl = fork();
if(pidl == 0) {
printf ("New, x=%d\n",x);
exit (0);
}
if(pid1 < 0){
printf("Cannot create");
exit (1);
}
pid2=fork();
if(pid2 == 0) {
printf ("New, y=%d\n",y);
exit (0);
}
if(pid2 < 0){
printf("Cannot create");
exit (1);
}
return 0;
}

Yes. This code create two child process.
However you do not make the relation between parent and child processes by using wait function.
Therefore result of code change variously.
Child process 1 can print result before / after parent process terminated.
Child process 2 can print result before / after parent process terminated.
Maybe this variable result confuse you.

Related

Parent process not terminating

I have a parent and child process both counting upto 50 and then terminate. The parent process waits till the child process has counted upto 50 and then exits. I have written the code but it is going in infinite loop :
int main()
{
long int T_Child = 0, T_parent = 0;
pid_t procid = fork();
int T = 0;
if(procid < 0)
{
printf("\nFailed");
exit(0);
}
else if(procid == 0)
{//child
while(T_Child < 50)
{
printf("\nCHILD : %ld",T_Child);
delay(2);
T_Child++;
}
exit(1);
}
else if(procid > 0)
{//parent
while(T_parent < 50)
{
printf("\nPARENT : %ld",T_parent);
delay(2);
T_parent++;
}
while(T_Child < 50)
{//to ensure parent exits after child
delay(1);
}
exit(1);
}
return 0;
}
I'm a novice in this field. Please help!
Forking is not the same as threading. A fork creates a copy of the process. The
values of the variables in the child process would have the same as the
variables of the parent process at the time of the fork(). That means that
the child variables inherit the values from the parent, but changes of the
child variables are not visible by the parent.
If the parent needs to wait for the child to exit, it must call
wait or waitpid. Also if the parent needs to get a value from the child, the parent and the child
should comunicate with each other, for example using a pipe.
The following code shows how parant and child communicate with each other and
how the parent should wait for a child to exit:
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
int comm[2];
// create pipe
if(pipe(comm) < 0)
{
perror("Could not create pipe");
return 1;
}
pid_t pid = fork();
if(pid < 0)
{
perror("Could not fork");
close(comm[0]);
close(comm[1]);
return 1;
}
if(pid == 0)
{
// CHILD
// closing reading end of the pipe
close(comm[0]);
do_some_work();
int result = 50;
// write to the parant through the pipe
write(comm[1], &result, sizeof result);
// closing writing end
close(comm[1]);
exit(0);
}
// PARENT
// close writing end of pipe
close(comm[1]);
puts("Now waiting for the child to exit...");
// parent waits for child to exit
int child_status;
if(waitpid(pid, &child_status, 0) < 0)
{
perror("Could not wait");
close(comm[0]);
return 1;
}
// if child exited without any error
if(WIFEXITED(child_status) && WEXITSTATUS(child_status) == 0)
{
// read answer from the child
int answer;
read(comm[0], &answer, sizeof answer);
printf("Child answered with %d\n", answered);
}
// closing reading end of pipe
close(comm[0]);
return 0;
}
The child process and the parent process run in separate memory spaces. At the time of fork() both memory spaces have the same content.
There is concept called Copy on Write (CoW); it's good to have knowledge about it-
Copy on Write is an optimization where the page tables are set up so that the parent and child process start off sharing all of the same memory, and only the pages that are written to by either process are copied when needed.
[Above is copied from my own answer to an old thread]
In your program you are doing:
while(T_Child < 50)
{//to ensure parent exits after child
delay(1);
}
The T_Child is initialized with 0 before fork. Because the address spaces are separate, when the child process modifies the value of T_Child, CoW creates a copy of its page — but the parent copy of T_Child still has the initial value 0. The parent process is not making any change in the value in T_Child. So, the while loop condition T_Child < 50 will always true and the loop will execute infinitely.
Instead, you should wait for child process to exit using waitpid system call. In place of while(T_Child < 50){.. loop, you should do:
waitpid(procid,&status,0);
This will make parent process wait till child process exits.

how fork() process works (operating system)

I am confused about fork(). For example, what will be the output of the following code?
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int value = 5;
int main() {
pid_t pid;
pid = fork();
if (pid == 0) { value += 15; return 0; }
else if (pid > 0>) { wait (NULL); printf (“Value = %d”, value); return 0}
}
The function fork() creates a new process that is a complete copy of the original process. The new process has its own memory and its own copy of all variables.
In the new child process the returned pid value is zero. The child adds 15 to its variable value and exits in the line:
if (pid == 0) { value += 15; return 0; }
The value is 5 in the original process. The original parent process has pid greater than zero and it goes to:
else if (pid > 0) { wait (NULL); printf("Value = %d", value); return 0; }
This line prints: Value = 5
The output will be "Value = 5".
The fork function will create a new process (child process) with its own address space. The child process will receive a copy of the parents process data region, heap and stack. Therefore, modifying the variable value in the child process won't affect the variable value in the parent process.
Probably you don't know or don't quite understand what fork does. Like Orest Hera and reffox both said, fork() spans a new process.
You should also know that the parent process (the once actually calling fork) will get the pid of the child process as a result from fork.
The child process starts at the point, where fork finished and returns 0 instead, thus giving the processes the chance to check, who they are:
var x = 7;
pid = fork();
if(pid < 0)
{
perror("failing to create a child process");
return SOME_ERROR;
}
if(pid == 0)
{
/* I'm the child process */
x = 9;
/* only I see that, my dad doesn't even notice that this happened */
...
} else {
/* I'm the parent process */
...
/* waiting for my child to die,
otherwise a zombie will be created,
and I DO mean a zombie */
wait(0);
/* the child is gone, now I can do whatever I want to */
}

Forking in Linux and the use of setsid()

I have a sample code and I'm at loss in understanding how to figure out what's happening.
I'm only showing relevant parts. The problem is make_daemon().
From what I understand about forking is that code from close(0) onwards is executed by the child which should have a pid == 0.
What happens when the code hits return -1? Does the code return to the parent or does it exit? Does the child p process code execute if(share) in Monitor()?
This code is an extract from Monitor.c in mdadm.
Thanks in advance for any help.
int Monitor( struct mddev_dev *devlist,
char *mailaddr, char *alert_cmd,
struct context *c,
int daemonise, int oneshot,
int dosyslog, char *pidfile, int increments,
int share )
{
if (daemonise) {
int rv = make_daemon(pidfile);
if (rv >= 0)
return rv;
}
if (share)
if (check_one_sharer(c->scan))
return 1;
/* etc .... */
}
static int make_daemon(char *pidfile)
{
int pid = fork();
if (pid > 0) {
if (!pidfile)
printf("%d\n", pid);
else {
FILE *pid_file;
pid_file=fopen(pidfile, "w");
if (!pid_file)
perror("cannot create pid file");
else {
fprintf(pid_file,"%d\n", pid);
fclose(pid_file);
}
}
return 0;
}
if (pid < 0) {
perror("daemonise");
return 1;
}
close(0);
open("/dev/null", O_RDWR);
dup2(0,1);
dup2(0,2);
setsid();
return -1;
}
fork can return three types of return values:
a positive number: this only happens in the parent: it is the pid of a successfully created child.
zero: this is only returned in the child and indicates that this code now executes in the child. This is not the pid of the child, use getpid to obtain the pid of the child.
a negative value (commonly -1). This is also only ever returned in the parent and indicates that fork failed for whatever reason and no child was created.
As to what your code does: yes the child will continue at close(0); provided that a child was indeed created.
When your cild hits return -1 it will return to whatever function called make_daemon back in the parent and will continue execution at that point. Normally forked children would do whatever they are supposed to do and then call exit in order not to mess up what the parent was doing.

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