Multitasking
fork() spawns new process -> Called once, returns twice
exit() terminates own process -> Called once, never returns / Puts it into "zombie" status
wait() and waitpid() wait for and reap terminated children
execve() runs new program in existing process -> Called once, never returns
Sending Signals
Sending signals from the keyboard
-> Typing ctrl-c (ctrl-z) sends a SIGINT (SIGTSTP) to every job in the foreground process group
int kill(pid_t pid, int sig)
Can be used to send any signal to any process group or process
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#define N 10
int main(void) {
pid_t pid[N];
int i, child_status;
for (i = 0; i < N; i++){
if ((pid[i] == fork()) == 0) {
while(1); /* Child infinite loop */
}
}
/* Parent terminates the child processes */
for (i = 0; i< N; i++) {
printf("Killing process %d\n", pid[i]);
kill(pid[i], SIGINT);
}
/* Parent reaps terminated children */
for (i = 0; i < N; i++) {
pid_t wpid = wait(&child_status);
if (WIFEXITED(child_status))
printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminated abnormally\n", wpid);
}
return 0;
}
sighandler_t signal (int sig, sighandler_t handler)
The signal function modifies the default action associated with the receipt of signal sig
void int_handler(int sig)
{
printf("Process %d received signal %d\n", getpid(), sig);
exit(22);
}
int main(void) {
pid_t pid[N];
int i, child_status;
signal(SIGINT, int_handler);
for (i = 0; i < N; i++){
if ((pid[i] == fork()) == 0) {
while(1); /* Child infinite loop */
}
}
/* Parent terminates the child processes */
for (i = 0; i< N; i++) {
printf("Killing process %d\n", pid[i]);
kill(pid[i], SIGINT);
}
/* Parent reaps terminated children */
for (i = 0; i < N; i++) {
pid_t wpid = wait(&child_status);
if (WIFEXITED(child_status))
printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminated abnormally\n", wpid);
}
return 0;
}
Handling Signals
#define N (10)
pid_t pid[N];
int ccount = 0;
void handler (int sig) {
pid_t id;
while((id = waitpid(-1, NULL, WNOHANG))>0) {
ccount--;
printf("Received signal %d from pid %d\n", sig, id);
}
}
int main(void) {
int i;
ccount = N;
signal(SIGCHLD, handler);
for (i = 0; i < N; i++){
if ((pid[i] = fork()) == 0) {
exit(0); /* child */
}
}
while (ccount > 0)
sleep(5);
return 0;
}
Sender
Receiver
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
pid_t sender, receiver;
int total_number_of_signals = 0;
int total_received_signals = 0;
int total_acked_signals = 0;
//int total_sending_signals = 0;
void sigalrm_handler(int sig)
{
//This function is called upon receiving the signal SIGALRM
//See how many acks are received
//Send the signals again for the remaining number
if(total_acked_signals < total_number_of_signals){
for(int i= 0; i < total_number_of_signals - total_acked_signals; i++)
kill(receiver, SIGUSR1);
alarm(1);
}
else exit(0);
//kill(receiver, sig);
}
void sigusr1_handler(int sig)
{
//receive the signal
//increase the number of received one
//send the ack back to the parent
total_received_signals++;
//kill(sender, sig);
printf("receiver: received #%d signal and sending ack\n", total_received_signals);
kill(sender, SIGUSR2);
}
void sigusr2_handler(int sig)
{
//upon receiving the ack, increase the number of acks
//if equals the number of total signals send SIGINT to the child
total_acked_signals++;
printf("sender: total remaining signal(s): %d\n", total_number_of_signals - total_acked_signals);
if (total_acked_signals == total_number_of_signals)
{
kill(receiver, SIGINT);
}
}
void sigint_handler(int sig)
{
//upon receiving this signal just terminate
printf("sender: all signals have been sent\n");
printf("receiver: total received signals(s): %d\n", total_received_signals);
exit(0);
}
int main(int argc, char* argv[])
{
signal(SIGUSR1, sigusr1_handler);
signal(SIGINT, sigint_handler);
signal(SIGALRM, sigalrm_handler);
signal(SIGUSR2, sigusr2_handler);
if(argc != 2){
printf("please input total number of signals\n");
return -1;
}
total_number_of_signals = atoi(argv[1]);
printf("total number of signal(s): %d\n", total_number_of_signals);
sender = getpid();
if((receiver = fork()) == 0){
while(1){}
}
else{
for(int i = 0; i < total_number_of_signals - total_acked_signals; i++){
kill(receiver, SIGUSR1);
}
alarm(1);
}
while(1);
}