Fork
Given the following source code:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
printf("Staring program...\n");
int pid = fork();
if (pid == -1) {
printf("Error while creating child process using fork: %s", strerror(errno));
return EXIT_FAILURE;
}
if (pid > 0) {
printf("Hello World from parent process. Parent PID: [%d] Process PID: [%d] Returned PID: [%d]\n",
getppid(), getpid(), pid);
sleep(2);
printf("Goodbye from parent process. Parent PID: [%d] Process PID: [%d] Returned PID: [%d]\n",
getppid(), getpid(), pid);
}
if (pid == 0) {
printf("Hello World from child process. Parent PID: [%d] Process PID: [%d]\n", getppid(), getpid());
printf("Goodbye from child process. Parent PID: [%d] Process PID: [%d]\n", getppid(), getpid());
}
printf("Bye from process id [%d]\n", getpid());
return EXIT_SUCCESS;
}
First steps with forks
- When is the child process created ?
- Is a new process descriptor created ?
- How the child process can be identified from the parent process ?
Create a grand child
- Modify the source code to create a new process from the current child process.
- Make the new process display a new message.
Parent process management
What is the purpose of the sleep(2) ?
Modify the program have the following termination sequence:
- The parent process ends first.
- Then the child process ends.
- Then the grand child process ends.
What is happening ?
Execve
Execve basic execution
Write the following program source code inside two separated files.
Main program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
printf("Trying to run execve system call...");
//remplacez ci-dessous "/home/jean" par le chemin du fichier executable.
char *args[] = {
"Execve ran program",
"My Name",
NULL
};
if (execve("<REPLACE_BY_THE_PATH_TO_THE_EXECUTED_PROGRAM>", args, NULL) == -1) {
perror("Error returned by execve: ");
} else {
printf("Error in system call");
}
return EXIT_SUCCESS;
}
Executed program
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("I am ran by an execve system call.\nProgram: %s\nWell done %s!\n", argv[0], argc > 1 ? argv[1] : "dear");
return EXIT_SUCCESS;
}
- Compile the executed program using gcc (
gcc executed.c -o executed-program). - Compile the main program using gcc.
- Execute the main program and describe what is happening.
- What is the executed program name
argv[0]when executed byexecve? - Execute the executed program inside a bash prompt and compare the program name with the previously obtained value.
- What is the executed program name
- Modify the main program source code to launch the
execvesystem call inside a fork. - Modify the main program source code again to add an infinite loop after the
execvesystem call. Describe what is happening.
File descriptor duplication
Given the following source code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int text_file_descriptor = open("text.txt", O_RDONLY);
if (text_file_descriptor == -1) {
perror("Unable to open text.txt file: ");
return EXIT_FAILURE;
}
printf("File is opened\n");
// Closing STDIN
close(STDIN_FILENO);
int val = dup(text_file_descriptor);
if (val == -1) {
fprintf(stderr, "Unable to execute file descriptor %d duplication: %s \n", val, strerror(errno));
close(text_file_descriptor); // Don't bother of the return code, just attempt to clean.
return EXIT_FAILURE;
}
printf("Duplication of STDIN is made\n");
char tab[200];
fgets(tab, sizeof(tab) / sizeof(char), stdin);
printf("Read data from STDIN: %s\n", tab);
if (close(text_file_descriptor)) {
perror("Unable to close text.txt:") ;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
- Compile the source code and create a file named
"text.txt"next to the binary. Explain what the source code is doing. - What’s the result of
close(0)? - Modify the source code to redirect the standard output (1) to a file named
output.txt. What is displayed when executing program ? Explain.
Wait system call
Using man pages of the wait system call write a program that:
- Create 3 child processes
- Each child process waits for a different time then exits returning the time spent sleeping.
- Writes to STDOUT when a child ends a message like
"Process XXX ended with return code X." - Writes to STDOUT when all child are ended a message like
"All child ended".
Forked processes will sleep for X seconds (different for each child) then return the time spent sleeping.