How to Read Child Process Errno From Parent
Process management
One of the philosophies behind Unix is the motto do ane matter and practise it well. In this spirit, basic process management is done with a number of system calls, each with a single (simple) purpose. These organization calls can and so exist combined to implement more complex behaviors.
The post-obit organisation calls are used for basic process direction.
- fork
- A parent process uses fork to create a new child process. The child process is a copy of the parent. After fork, both parent and child executes the aforementioned program merely in separate processes.
- exec
- Replaces the program executed by a process. The child may apply exec after a fork to replace the process' memory space with a new programme executable making the child execute a different program than the parent.
- get out
- Terminates the process with an exit status.
- wait
- The parent may use wait to suspend execution until a child terminates. Using await the parent can obtain the go out condition of a terminated child.
Parent and child
The process invoking fork is called the parent. The new process created as the result of a fork is the child of the parent.
Subsequently a successful fork, the kid procedure is a re-create of the parent. The parent and child processes executes the same programme but in separate processes.
Fork
The fork system call is the master (and historically, only) method of procedure creation in Unix-like operating systems.
#include <unistd.h> pid_t fork ( void ); - Render value
- On success, the PID of the child procedure is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set up appropriately.
Fork returns twice on success
On success fork returns twice: in one case in the parent and once in the kid. Afterwards calling fork, the program tin use the fork return value to tell whether executing in the parent or kid.
- If the return value is
0the program executes in the new kid process. - If the render value is greater than naught, the programme executes in the parent process and the render value is the process ID (PID) of the created child process.
- On failure
forkreturns-1.
Template program
In the file module-ii/examples/src/fork-template.c you find a template for a typical program using fork.
1 #include <stdio.h> // perror() 2 #include <stdlib.h> // get out(), EXIT_SUCCESS, EXIT_FAILURE 3 #include <unistd.h> // fork() iv 5 int chief ( void ) { half-dozen 7 pid_t pid; viii 9 switch (pid = fork()) { 10 11 case - 1 : 12 // On error fork() returns -1. 13 perror( "fork failed" ); 14 exit(EXIT_FAILURE); 15 16 case 0 : 17 // On success fork() returns 0 in the child. eighteen nineteen // Add lawmaking for the child process hither. xx 21 get out(EXIT_SUCCESS); 22 23 default : 24 // On success fork() returns the pid of the child to the parent. 25 26 // Add together code for the parent process here. 27 28 go out(EXIT_SUCCESS); 29 } thirty } On lines 1-3 a number of header files are included to get access to a few functions and constants from the C Standard library.
pid_t
I line seven the variable pid of blazon pid_t is declared. The pid_t data type is the data type used for process IDs.
fork
On line 9 the parent procedure calls fork and stores the return value in the variable pid.
switch
On line 9 a switch-argument is used to check the return value of fork.
Error (example -i)
On failure fork returns -1 and execution continues in the case -1 branch of the switch statement (line 11). The operating system was not able to create a new process. The parent uses perror to print an error message (line xiii) and then terminates with exit condition EXIT_FAILURE (line 14).
Kid (instance 0)
On success fork returns 0 in the new child process and execution continues in the instance 0 co-operative of the switch statement (line 16). Any code to exist executed only past the child is placed here (line nineteen). The child terminates with exit status EXIT_SUCCESS (line 21).
Parent (default)
If the value fork returned by fork was neither -1 (error) nor 0 (child), execution continues in the parent process in the default co-operative of the switch statement (line 23). In this example, the value returned past fork is the process ID (PID) of the newly created child process.
A kickoff fork case
In the file module-2/examples/fork.c you find a program with the post-obit main function.
int main ( void ) { pid_t pid; switch (pid = fork()) { case - 1 : // On mistake fork() returns -1. perror( "fork failed" ); get out(EXIT_FAILURE); example 0 : // On success fork() returns 0 in the child. kid(); default : // On success fork() returns the pid of the child to the parent. parent(pid); } } The code for the child is in the function child and the code for the parent in the office parent.
void kid () { printf( " CHILD <%ld> I'thousand alive! My PID is <%ld> and my parent got PID <%ld>. \due north " , ( long ) getpid(), ( long ) getpid(), ( long ) getppid()); printf( " Kid <%ld> Goodbye! \n " , ( long ) getpid()); leave(EXIT_SUCCESS); } void parent ( pid_t pid) { printf( "PARENT <%ld> My PID is <%ld> and I spawned a child with PID <%ld>. \northward " , ( long ) getpid(), ( long ) getpid(), ( long ) pid); printf( "PARENT <%ld> Goodbye! \north " , ( long ) getpid()); exit(EXIT_SUCCESS); } Both parent and child prints two letters and then terminates. Navigate to the directory module-2/examples. Compile using make.
Run the program.
You should see output like to this in the final.
PARENT <87628> Spawned a child with PID = 87629. PARENT <87628> Goodbye. Kid <87629> I'thou alive and my PPID = 1. Kid <87629> Goodbye. Run the program multiple times and expect specifically at the PPID value reported by the child. Sometimes the child reports PPID = 1 merely sometimes it is equal to the PID of the parent. Conspicuously the PID of the parent is non 1? Why doesn't report the "correct" PPID value all the fourth dimension?
Orphans
An orphan procedure is a process whose parent process has terminated, though it remains running itself. Whatsoever orphaned process will exist immediately adopted by the special init system process with PID one.
Processes execute concurrently
Both the parent process and the kid process competes for the CPU with all other processes in the system. The operating systems decides which process to execute when and for how long. The procedure in the organisation execute concurrently.
In our instance programme:
- most frequently the parent terminates before the child and the kid becomes an orphan process adopted past init (PID = 1) and therefore reports PPID = 1
- sometimes the child process terminates before its parent and and so the child is able to report PPID equal to the PID of the parent.
Await
The wait system call blocks the caller until one of its child process terminates. If the caller doesn't have any child processes, wait returns immediately without blocking the caller. Using await the parent tin can obtain the leave status of the terminated child.
#include <sys/types.h> #include <sys/wait.h> pid_t wait ( int * status); - status
- If
conditionis not Nada,waitstore the get out status of the terminated child in the int to whichstatuspoints. This integer tin exist inspected using theWIFEXITEDandWEXITSTATUSmacros. - Render value
- On success,
waitreturns the PID of the terminated child. On failure (no child),waitreturns-ane.
WIFEXITED
#include <sys/types.h> #include <sys/wait.h> WIFEXITED(status); - status
- The integer condition value set by the
waitsystem call. - Return value
- Returns true if the child terminated usually, that is, by calling
leaveor past returning frommain.
WEXITSTATUS
#include <sys/types.h> #include <sys/wait.h> int WEXITSTATUS (condition); - status
- The integer condition value gear up by the
looksystem call. - Render value
- The exit status of the kid. This consists of the least pregnant 8 $.25 of the condition argument that the child specified in a call to
exitor as the statement for a render statement inmain. This macro should be employed merely if WIFEXITED returned true.
Example using await
In the module-two/examples/fork_exit_wait.c example program the parent execute the parent office.
1 void parent ( pid_t pid) { ii 3 printf( "PARENT <%ld> Spawned a child with PID = %ld. \due north " , 4 ( long ) getpid(), ( long ) pid); five half-dozen wait(Zip); 7 8 printf( "PARENT <%ld> Child with PID = %ld terminated. \north " , ix ( long ) getpid(), ( long ) pid); ten 11 printf( "PARENT <%ld> Bye. \n " , 12 ( long ) getpid()); 13 14 exit(EXIT_SUCCESS); 15 } On line 6 the parent calls wait(Nil) to wait for the kid process to cease.
Compile and run the program. Now the parent should always wait for the child to stop before terminating itself. As a consequence the child should:
- newer be adopted by init
- new report PPID = 1
- always report PPID equal to the PID of the parent.
Example using wait to obtain the get out status of the kid
In the module-2/examples/fork_exit_wait_status.c case program the parent execute the parent function.
one void parent ( pid_t pid) { ii int condition; three four printf( "PARENT <%ld> Spawned a kid with PID = %ld. \n " , 5 ( long ) getpid(), ( long ) pid); 6 7 wait( & status); viii 9 if (WIFEXITED(status)) { 10 printf( "PARENT <%ld> Child with PID = %ld and get out condition = %d terminated. \n " , xi ( long ) getpid(), ( long ) pid, WEXITSTATUS(status)); 12 } 13 14 printf( "PARENT <%ld> Goodbye. \n " , 15 ( long ) getpid()); 16 17 exit(EXIT_SUCCESS); eighteen } One line ii the parent creates the variable condition. On line 7 the parent calls expect(&condition) to wait for the child process to finish. The & is the address-of operator and &condition returns the address of the condition variable. When the child terminates the exit condition of the child will be stored in variable condition.
Compile using make.
Run the program.
$ ./bin/fork_exit_wait_status In the output you should be able to see that the parent obtained the exit status of the kid.
PARENT <99340> Spawned a child with PID = 99341. Child <99341> I'k alive and my PPID = 99340. CHILD <99341> Goodbye, leave with status 42. PARENT <99340> Kid with PID = 99341 and get out condition = 42 terminated. PARENT <99340> Good day. Zombies
A terminated procedure is said to exist a zombie or defunct until the parent does wait on the child.
- When a process terminates all of the retentiveness and resource associated with it are deallocated so they can exist used past other processes.
- However, the exit status is maintained in the PCB until the parent picks up the exit status using
waitand deletes the PCB. - A child process e'er first becomes a zombie.
- In virtually cases, under normal organization operation zombies are immediately waited on by their parent.
- Processes that stay zombies for a long time are generally an mistake and cause a resource leak.
An example with a zombie process
In the module-two/examples/fork_zombie.c example plan the kid terminates before the parent does look on the child and becomes a zombie process. The parent execute the parent function.
i void parent ( pid_t pid) { 2 three printf( "PARENT <%ld> Spawned a child with PID = %ld. \north " , 4 ( long ) getpid(), ( long ) pid); 5 half-dozen printf( "PARENT <%ld> Press whatever key to reap a zombie! \n " , 7 ( long ) getpid()); 8 9 getchar(); 10 xi pid = wait(NULL); 12 13 printf( "PARENT <%ld> Zombie kid with PID = %ld" , fourteen ( long ) getpid(), ( long ) pid); fifteen sixteen exit(EXIT_SUCCESS); 17 } On line nine the parent uses getchar to block itself until the user presses a key on the keyboard.
When the child terminates, the get out status of the kid is stored in the child process command cake (PCB). The operating system deallocates all retentivity used by the child but the PCB cannot be deallocated until the parent does look on the child.
Compile using brand.
Run the program.
In the output you should be able to see that the child terminates and that the parent blocks waiting for a keypress.
PARENT <4636> Spawned a child with PID = 4637. PARENT <4636> Press any key to reap a zombie! Kid <4637> I'm alive and my PPID = 4636. Child <4637> Cheerio. The child process has terminated simply the parent has yet not read the go out status of the kid using await. The child process has now go a zombie procedure.
Monitor
Open a second concluding and navigate to the module-ii directory. The module-2/tools/monitor tool can exist used to view process condition data about process. Use the --assistance flag to come across the documentation.
This is the built in documentation for the monitor tool.
Usage: monitor [-s delay] [-p pid] cmd A top-similar command that just lists USER, PID, STAT and COMM for the current user and and proceses with a control proper name with a grep match of cmd. Options: -s delay Delay in seconds between refresh, default = ane. -p pid Include process with PID pid. The cmd argument is the name of the program executed by the processes nosotros want to monitor. Use the monitor tool to view process condition information for the parent and child, both executing the fork_zombie program.
$ ./tools/monitor fork_zombie On Linux you should see something similar to this.
Monitoring processes matching: fork_zombie Press Ctrl-C to exit USER PID PPID S Control abcd1234 4636 4311 S fork_zombie abcd1234 4637 4636 Z fork_zombie <defunct> In the PID column yous see the PID of the listed processes. The commencement line shows information near the parent and the second line shows data about the child.
The Southward column prove the status of the process.
- The parent got condition
South(sleep) significant the procedure is waiting for an event to complete. In this case the parent is blocked waiting for the child to cease. - The child got status
Z(zombie) significant the process terminated only not yet reaped by its parent.
Some other proper name used for a zombie process is defunct.
Reap the zombie
From the terminal used to run the fork_zombie programme, press whatsoever key to make the parent practice wait on the child.
PARENT <4636> Spawned a child with PID = 4637. PARENT <4636> Press any cardinal to reap a zombie! CHILD <4637> I'1000 alive and my PPID = 4636. Child <4637> Cheerio. PARENT <4636> Zombie child with PID = 4637 reaped! PARENT <4636> Printing any key to finish! In the terminal used to run monitor the zombie process should have disappear, leaving but the parent procedure.
Monitoring processes matching: fork Printing Ctrl-C to exit USER PID PPID S Control abcd1234 4636 4311 South fork_zombie The parent is now blocked, waiting for user input.
Terminate the parent
From the terminal used to run the fork_zombie plan, printing any key to brand the parent terminate.
PARENT <4636> Spawned a child with PID = 4637. PARENT <4636> Printing any key to reap a zombie! CHILD <4637> I'm alive and my PPID = 4636. Kid <4637> Goodbye. PARENT <4636> Zombie kid with PID = 4637 reaped! PARENT <4636> Press any key to terminate! PARENT <4636> Goodbye! Execute a new program in the child
If you don't want to execute the aforementioned program in both the parent and the child, you will need to use a system call of the exec family unit. The exec system calls will supersede the currently executing program with a new executable.
In module-ii/examples/src/child.c yous this pocket-size programme.
#include <stdio.h> // puts(), printf(), perror(), getchar() #include <stdlib.h> // exit(), EXIT_SUCCESS, EXIT_FAILURE #include <unistd.h> // getpid(), getppid() int main ( void ) { printf( " Child <%ld> I'thousand alive and my PPID = %ld. \n " , ( long ) getpid(), ( long ) getppid()); printf( " Kid <%ld> Printing any cardinal to brand me end! \north " , ( long ) getpid()); getchar(); printf( " CHILD <%ld> Bye! \northward " , ( long ) getpid()); exit( 127 ); } Compile using make.
Run the program.
First this plan simply prints two letters to the terminal and so wait for a central-press.
Kid <33172> I'one thousand alive and my PPID = 81166. Kid <33172> Press whatsoever key to make me terminate! Subsequently you lot press any key in the terminal the program terminates.
Child <33172> I'm live and my PPID = 81166. Kid <33172> Printing whatsoever primal to brand me terminate! CHILD <33172> Goodbye! The module-2/examples/src/fork_exec.c program uses execv to brand the child process execute the module-2/examples/bin/child executable. After fork the kid executes the child functions.
i void child () { two char * const argv[] = { "./bin/child" , Goose egg}; iii iv printf( " Child <%ld> Press any key to make me call exec! \due north " , 5 ( long ) getpid()); 6 7 getchar(); viii 9 execv(argv[ 0 ], argv); ten 11 perror( "execv" ); 12 exit(EXIT_FAILURE); thirteen } On line 2 the needed argument vector is constructed. On line 7 the child waits for a key-press. After the key-press, on line ix, the child use execv to supercede the program executed past the child process past the child executable. If execv is successful control volition never exist returned and lines eleven and 12 should not exist reached.
Compile using make.
Run the plan.
PARENT <33422> Spawned a kid with PID = 33423. Child <33423> Press whatever key to brand me phone call exec! Open a second final and apply the ps control with the -p option to run into data virtually the kid procedure.
$ ps -p 33206 PID TTY Fourth dimension CMD 33423 ttys023 0:00.00 ./bin/fork_exec Annotation that the child process currently is executing the .bin/fork_exec executable.
In the first terminal, press any primal.
Kid <33423> I'thou alive and my PPID = 33422. CHILD <33423> Press whatsoever key to brand me terminate! From the other terminal and employ the ps command with the -p option to meet information about the child process.
$ ps -p 33206 PID TTY TIME CMD 33423 ttys023 0:00.00 ./bin/child Note that the kid procedure at present executes the ./bin/child executable.
In the first concluding, printing whatsoever key to make the kid process terminate. Now the parent performs await on the kid and reports the kid exit status.
Kid <33423> Adieu! PARENT <33422> Child with PID = 33423 and exit status = 127 terminated. PARENT <33422> Goodbye! Source: http://www.it.uu.se/education/course/homepage/os/vt18/module-2/process-management/
0 Response to "How to Read Child Process Errno From Parent"
Post a Comment