/>
pid_t fork(void)
================
DESCRIPTION
fork creates a child process that differs from the parent process only in
its PID and PPID, and in that resource utilizations are set to 0.
RETURN VALUE
Parent: PID of child process is returned to the parent
Child: 0 is returned in the child's thread.
Failure: -1 will be returned in the parent's context, no child
process will be created, and errno will be set
ERRORS
EAGAIN
fork cannot allocate sufficient memory to copy the parent's page tables
and allocate a task structure for the child.
ENOMEM
fork failed to allocate the necessary kernel structures because
memory is tight.
#include <stdio.h> // simplefork
#include <unistd.h> // << need this
int main(void)
{
int x = 0;
fork();
x++;
printf("I am process %ld and my x is %d\n", (long)getpid(), x);
return 0;
}
-> How many kids are created here?
-> How can this program report whether it is the parent or a child?
-> How do we know if there is an error?
-> What is the value of x in the parent? the child?
PREDICTION??
#include <stdio.h> // simplefork
#include <unistd.h> // << need this
#include <iostream>
int main( void )
{
pid_t r = fork();
printf("I am process %ld and my return code is %d\n", (long)getpid(), r);
for(int i=0;i<100;i++) // 1000??
std::cout << i << " ";
return 0;
}
PREDICTION??
#include <stdio.h> // simplefork
#include <unistd.h> // << need this
#include <iostream>
int main(void)
{
pid_t r = fork();
printf("I am process %ld and my return code is %d\n", (long)getpid(), r);
if (r==0)
for(int i=0;i<500;i++)
std::cout << i << " ";
else
for(int i=0;i<500;i++)
std::cout << "_" << i << "_";
return 0;
}
differentiating parent & child...
use return code from fork()
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
pid_t childpid;
childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
return 1;
}
/* child code */
if (childpid == 0)
printf("I am child %ld\n", (long)getpid());
/* parent code */
else
printf("I am parent %ld\n", (long)getpid());
return 0;
}
both procs report same RANDOM value of x - WHY?
want each process to get it's OWN RANDOM value for random y,
but it doesn't - WHY?
I am process 4882 and my x is 15008 and y is 345
I am process 4883 and my x is 15008 and y is 345
could values of y ever be different?? Explain...
#include <iostream>
#include <cmath>
#include <unistd.h> // needed for system calls
using namespace std;
int main() {
int x, y, childpid;
srand(time(0));
x = rand();
childpid = fork();
/** 2 processes here **/
srand(time(0)); // each process seeds independently (?)
y = rand(); // both procs get random # here
// report
cout << "I am proccess " << long(getpid()) << " and my x is "
<< x << " and my y is " << y << endl;
return 0;
}
FIX!!
==== /** 2 processes here **/
change -> srand(getpid());
child process
-------------
Starts processing from point of fork
Inherits all data and values (environment, privs) from parent except:
return value of fork()
pid
parent pid
cpu usage time – zero
no locks or alarms
=> Why do parent and child both report the same pid?
#include <stdio.h> // ch3 badprocessID.c
#include <unistd.h>
#include <sys/types.h>
int main(void) {
pid_t childpid;
pid_t mypid;
mypid = getpid();
childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
return 1;
}
if (childpid == 0) /* child code */
printf("I am the child. ID = %ld which is the same as ID = %ld\n",
(long)mypid, (long)getpid( ) );
else /* parent code */
printf("I am the parent. ID = %ld which is the same as ID = %ld\n",
(long)mypid, (long)getpid( ) );
return 0;
}
perror() produces a message on the standard error output, describing the
last error during a call to a system or library function.
If s not NULL, the argument string s is printed, followed by the message.
The error number is taken from the external variable errno, which is set
when errors occur but not cleared when non-erroneous calls are made.
The global error list sys_errlist[] indexed by errno can be used to obtain
the error message.
EXAMPLE: fork error
Failure: -1 will be returned in the parent's context, no child
process will be created, and errno will be set
^^^^^
CHAIN: children of children... creates a chain of n processes where n is a command line arg -------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main ( int argc, char *argv[] ) { pid_t childpid = 0; // IMPORTANT HERE!!! int i, n; /* check for # of command-line arguments which should be two args: the name of the program (simplechains) and n */ if ( argc != 2 ) /* error */ { fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } /* get n (number of procs) from user and loop n times */ n = atoi( argv[1] ); for ( i = 1; i < n; i++ ) if ( childpid = fork() )/* non-zero means this is parent */ break; /* if this is parent, leave the loop and print*/ /* parent prints each time it breaks out of loop last time through it prints without forking (child pid is 0) stderr is unbuffered (stdout is buffered) */ fprintf( stderr, "i:%d PID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid ); // (long) cast on childpid caused the zero to be a '1' return 0; }
jupiter/export/home/wyatt/private/opsys/UNIXSysProg/ch3$ simplechain 4 i:1 process ID:13478 parent ID:13362 child ID:13479 (original process) i:4 process ID:13481 parent ID:13480 child ID:0 i:3 process ID:13480 parent ID:13479 child ID:13481 i:2 process ID:13479 parent ID:13478 child ID:13480 shell = 13362 i =1, proc = 13478, child =13479 i =2, proc = 13479, child =13480 i =3, proc = 13480, child =13481 i =4, proc = 13481, child =0 value of i when it leaves the loop 1 is parent of 2 2 is parent of 3 3 is parent of 4 4 has no child
FAN: siblings creates a fan of n processes where n is a command line arg ------------------------------------------------------------- #include <stdio.h> // simplefan.c #include <stdlib.h> #include <unistd.h> int main ( int argc, char *argv[] ) { pid_t childpid = 0; int i, n; if ( argc != 2 ){ /* check for # of command-line arguments which should be two args: the name of the program (simplechains) and n */ fprintf( stderr, "Usage: %s processes\n", argv[0] ); return 1; } n = atoi( argv[1] ); /* get the number of procs from user */ for ( i = 1; i < n; i++ ) if ( childpid = fork() <= 0 ) /* non-zero means this is parent */ break; /* if this is child, leave the loop and print*/ /* the child prints each time it breaks out of loop and the last time through it prints without forking */ fprintf( stderr, "i:%d PID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(),(long)childpid ); // (long) cast on childpid caused the zero to be a '1' return 0; }
12177 (i=4) 12178 (i=1) 12179 (i=2) 12180 (i=3)
i:1 process ID:12178 parent ID:12177 child ID:0 i:3 process ID:12180 parent ID:12177 child ID:0 i:2 process ID:12179 parent ID:12177 child ID:0 i:4 process ID:12177 parent ID:18743 child ID:12180 (original process)