Processes

Problem 1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
   int p, i;
   p=fork();
   if (p == -1) {perror("fork impossible!"); exit(1);}
   if (p == 0) {
       for (i = 0; i < 10; i++)
            printf("Child: i=%d pid=%d, ppid=%d\n", i, getpid(), getppid());
            exit(0);
   } else {
       for (i = 0; i < 10; i++)
            printf("Parent: i=%d pid=%d ppid=%d\n", i, getpid(), getppid());
            wait(0);
  }
  printf("Finished; pid=%d ppid=%d\n", getpid(), getppid());
}

a) Run as is. How many lines are printed?
b) Comment the exit(0) call. What happens if you run the program now?
c) Comment the wait(0) call. What happens now?
d) Comment both exit and wait and change the number of iterations in the for statements to be different (e.g. 5 and 7, 20 and 7)

 


Problem 2
--------
Write a program in C which implements a hierarchy of processes in which the main program is
grand-grandparent of the youngest process (each process creates a child).
Each process will print their PID and the parent PID, waiting for the child process to terminate
and then it will terminate.

Possible solution
----------------

int main() {


     printf("A %d %d\n", getppid(), getpid());
     if(fork() == 0) {
           printf("B %d %d\n", getppid(), getpid());
           if(fork() == 0) {
                 printf("C %d %d\n", getppid(), getpid());
                 if(fork() == 0) {
                          printf("D %d %d\n", getppid(), getpid());
                          exit(0);
                 }
                 wait(0);
                 exit(0);
        }
        wait(0);
       exit(0);
}
wait(0);
return 0;

}

-------------------------------


a) Modify the program to print logs before waiting for a child process, when the child waiting for signals exit and just before it exits.
b) What happens if we comment one or more of the wait(0) calls?


==========================================================================
pid_t waitpid(pid_t pid, int *stat_loc, int options);

The waitpid() function shall be equivalent to wait() if the pid argument is (pid_t)-1 and the options argument is 0.
Otherwise, its behavior shall be modified by the values of the pid and options arguments.


To avoid zombies use this before creating new processes:
#include <signal.h>
- - -
signal(SIGCHLD, SIG_IGN);

int (*signal(int sig, void (*func)()))() -- that is to say the function signal() will call the func functions if the process receives a signal sig.
Signal returns a pointer to function func if successful or it returns an error to errno and -1 otherwise.
func() can have three values:

SIG_DFL
-- a pointer to a system default function SID_DFL(), which will terminate the process upon receipt of sig.
SIG_IGN
-- a pointer to system ignore function SIG_IGN() which will disregard the sig action (UNLESS it is SIGKILL).
A function address
-- a user specified function.
SIG_DFL and SIG_IGN are defined in signal.h (standard library) header file.
Thus to ignore a ctrl-c command from the command line. we could do:
signal(SIGINT, SIG_IGN);
TO reset system so that SIGINT causes a termination at any place in our program, we would do:
signal(SIGINT, SIG_DFL);

 

for UNIX BSD
#include <signal.h>
- - -
void waiter(){ // Functie de manipulare a apelurilor signal
wait(0); // Sterge fiul recent terminat
signal(SIGCHLD, waiter); // Reinstalare handler signal
}// waiter
- - -
signal(SIGCHLD, waiter); // Plasat în partea de initializare


int kill(int pid, int signal) - a system call that send a signal to a process, pid.
If pid is greater than zero, the signal is sent to the process whose process ID is equal to pid.
If pid is 0, the signal is sent to all processes, except system processes.
kill() returns 0 for a successful call, -1 otherwise and sets errno accordingly.

 

Examples: https://www.geeksforgeeks.org/zombie-processes-prevention/
==========================================================================


Problem 3

Write a C program to execute the shell commands:

 

Possible solutions:

Program 3.1:
#include <stdio.h>
#include <unistd.h>
int main() {
    char* argv[3];
    argv[0] = "/bin/ls";
    argv[1] = "-l";
    argv[2] = NULL;
    execv("/bin/ls", argv);
}

.

Program 3.2:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // system
int main() {
     //uncomment each of these lines one by one - only one of the 5
     //execl("/bin/ls", "/bin/ls", "-l", NULL);
     // execlp("ls", "ls", "-l", NULL);
     // execl("/bin/ls","/bin/ls","-l","p1.c","execl.c", "fork1.c", "xx", NULL);
     // execl("/bin/ls","/bin/ls","-l","*.c", NULL); //will not be interpreted as expected  
     system("ls -l *.c");
}

 

 


Problem 4

Write a program that reads from the command line (arguments) a list of text files.
Modify these files such that each word is capitalized. Use a separate process for each file.

 Possible solution using sed for capitalising words:

 

capit.sh ---------------

#!/bin/sh
sed "s/\<\([a-z]\)/\u\1/g" $1 > ${1}_temp

 

Implement a different solution for the capitalization program (that receives as argument a file name), either in C or using a different shell command/program. 

 

Problem 5 

SIGNAL and KILL

Write a program that creates three child processes that just loop forever. When the parent process gets SIGUSR1 it
sends SIGUSR2 to the child processes. When the parent process gets SIGUSR2, it sends SIGKILL to the child processes.
The child processes should report the signals received. Note in the solution below that the child process does not
override the SIGKILL handler, as it will not have any effect.

Explanations and how to run this code: YOUTUBE: https://youtu.be/RlfFTrn3x3U

 

 

Problem 6

Write a program that gets programs as command line arguments, and executes them using fork and exec. In case execfails or the program it executes exits with an error code, report the relevant details standard error. Notice in the solution below, the usage of strerror, errno, wait and WEXITSTATUS in the solution above. Read the UNIX manual to understand what they do.

 

 

 

HOMEWORK : Practice by solving the following problems:
==================================
Other problems (fork and exec): Write a program that:

5. compares 2 or more numbers as arguments and returns 0 if all are equal, 1 otherwise. This program is called by a C program which reads several numbers and prints if they are equal or not (the main program call the comparing program for pairs of numbers and checks if the exit status of the child processes is 1 for all cases).

6. receives as arguments a filename and a string and writes in the file the reversed string. This program is called by a C program which reads several strings and concatenates them in reverse in the file (using the first program).

7. receives as arguments 2 numbers and a filename and prints in the file the lowest common multiple of the two numbers. This program is called by a C program which reads a string of natural
numbers and prints the lowest common multiple of all. Use the exit status.

8. receives as arguments 3 filenames, the first two contain a sorted array of numbers, and prints in the third the sorted merge of the two arrays. This program is called by a C program which
reads an array of integer numbers, sorts them and writes the sorted array. You may use merge sort (split the array in files with one number each, then merge all files into one).

9. receives as arguments two file names and adds the contents of the first at the end of the second. This program is called by a C program which receives as arguments filenames and concatenates the first n-1 files into the nth file.

Other problems (signal and kill):

10. Write a program that creates three child processes that loop forever printing their ID in the form “PID is running”. The parent process suspends the execution of each child and then prints the PID of each child  created, prompting the user to choose which one should continue next. Parent process reads the PID from stdin and then resumes the execution of the child having PID for the next three seconds, after which it suspends it again and prompts the user to choose a new PID that will run for the next 3 seconds etc in a continuous loop. When the user sends Ctrl+C signal, the program will prompt the user to choose which of the three child processes should be terminated and will read the PID of the child that will be terminated with a message. When there are no child processes running, the parent process will also terminate with a message.

=======================================

11. Wrie a program that receives as command line arguments any number of strings. For each argument, it creates a new process that launches a C or Shell program that checks if the argument is a prime number, then it returns that number as int, if it's a number not prome it returns zero, if it's a string it returns the length of the string, sending these numbers to the main program using a pipe. The main program receives these numbers, prints them and computes they sum.

Solution for the main program:

 

The additional C program used to process each argument (compiled with gcc -Wall prog.c -o prog):