Hello and welcome!
In this video session we will see a demo program how to use the user defined signal sig user one and
sig user two.
Here in this demo, let's communicate between a parent and a child process using sig user.
So in this program let's open the first program here.
This is a program one dot c.
And here we include the required header files.
And the program begins from the execution of main.
And here if you observe the program one has created a fork call.
And because of fork we have two processes now in memory.
That is the parent process and a child process.
And if the fork creation is failed then we exit the program.
And if you observe here the PID equal to zero, this means this is the part of the child process.
The yields section is the parent process.
So the main thing in this program is after a fork we are doing a execl and we are doing a cycle of a
second program.
So we have two programs program one and program two now.
So the child process virtual memory is being replaced by the program two now.
And just we pass some arguments.
Argument one and two.
This is not required.
But just for more demo purpose we are passing some arguments to show how to pass the arguments as we
have discussed this in the previous video session also.
So after the Execl is successful, we will not be seeing this print because the child process now is
being overridden by the new program.
Two so in the else part This is the parent process and the parent is registering the signal sig user
one with the signal handler.
And if the signal returns sig error, that means there is an error using the signal system call and
we print the same on STD error.
Steady error is nothing but the output standard error, which is nothing but the output or the screen,
and we exit the program.
If the signal is successful, it enters here.
And now we have registered the signal handler.
Let's go to the signal handler function.
So now the signal handler is a function pointer.
And the function pointer has been defined here.
So here we have to say for which signal we are handling.
And uh as we have mentioned before signal handler returns void.
And if signal number is sig user one only then we are handling something.
This is just for demo.
So we are uh just putting some prints based on the different use cases.
One can use, uh, different program here.
Uh, after this.
But this is only for demo purpose.
So we are showing that how we are handling the signals.
Then later, the parent process, uh, prints the cpp id, uh, the child process created by a parent
is.
So the child process, uh, process ID is being printed by the parent, and then the parents lives for,
uh, two seconds.
Then if you observe here, kill is the system call that is used to send a signal from one process to
the other.
So in this case we the first parameter is the process id to which we are sending the signal.
So here cpp id is nothing but the uh the cpp ID or the process which the parent has created.
And here it uh, is nothing but the child process and we are sending sig user to to the child process
after sending the signal to child process.
The program two should handle the sig user two.
Let's see the program in the.
Let's see the code in program two.
So after that the parent process does a wait.
So once we call a wait until the child process exit.
These lines are not executed.
So once the child process exits then only these three lines will be executed.
And here we print the, uh, parent ID and the child process ID and the status in which it is, uh,
exited.
So these are just for reference purpose.
So now let's see how to handle sig user two in the second program.
That is that is nothing but the program two.
So now let's open the program two dot c file.
So here we have program to dot c file.
And we include the required header file.
And as we have mentioned before the execl will replace the child's process virtual memory by the virtual
memory of program two.
So when the program two begins it begins from the main.
So now we have a print saying that, uh, whatever we see here, Child colon is of, uh, print coming
from program two.
And the print here, Parent Colon is coming from the first program, program one or nothing but the
parent process.
So now if you observe here, the program two has a signal handler of for sig user two and main and the
function which will be called when this program receives a signal signature to its signal handler.
So this is the signal handler.
And if signal is sig user two, then we print some, uh, message on the screen.
And uh, this is just for, uh, our reference purpose that the arguments that are passed from the program
one, these are the arguments passed, even though this doesn't make any sense here.
Uh, like, we are just showing a demo to say how the arguments are also passed.
And then the child process sleeps for five seconds, and now the child process also sends a signal called
as sig user one.
So in the this is the child process.
The child process sends sig user one to the parent process.
So get PID gives the process id of the parent.
So this sig user one goes to the parent process.
And since it is handled here.
Sigusr1.
This function should be called and whenever the parent process calls, this API calls the user to uh
and it sends to the child process this sig.
User two uh will be interrupted and it jumps to this execution.
So let's say the any process it is executing in some instruction, whenever it receives a signal based
on the delivery of the signal, the kernel delivers the signal to the required process and the current
instruction, whatever is executing will be executed.
Then it jumps to the signal handler.
Then it does the execution of whatever is specified, the code specified in the signal handler, and
it and it jumps back to the place where it was previously executing the instruction.
So now, uh, I hope, uh, the program is, uh, clear.
Let's, uh, execute, uh, compile this and execute in order to see the, uh output.
Let's compile the code.
Program one we are compiling.
Now let's compile program two as well.
Now we have program one and program two.
Let's see this.
So we have program one and program two.
So let's execute program one here.
So what we can expect the output is the program.
One is a it is a new process.
We can call it as a parent process.
And this program one it forks a new child.
And that child is being because of X.
It is being replaced by the program two virtual memory.
And now we have we'll be having two processes in memory the parent process running program one and the
child process running program two.
And program one sends signal Sigusr1 to program two.
And program two sends user two to program one.
That is nothing but a sending of signals from child to parent and parent to child.
Let's execute this.
And let this run.
Then we will explain the code.
So it's waiting here.
This is waiting for some seconds that is mentioned.
Okay.
So now let's see.
So at this point at this point the execution was waiting for some time.
So if you see here, um, when the program one ran, it printed the print that was present in the uh,
program one.
So parent executing before wait child process created by parent is 11439.
So 11439 is the process ID of the child that is created by the parent.
So this is coming from this line.
Let's see this.
This is the one.
So in the else part the parent executes and we see this.
So after that the parent sleeps for two seconds and when it sleeps for two seconds.
Meanwhile the child is being created and the new program two starts running.
And if you see here the program two starts running from this point.
So I am a new process called bicycle.
Uh, I am a new process called bicycle.
My new program ID is 1.439.
So this is the child's process ID.
And if you see here 1.439 and this is same.
So in the parent process the process ID of the child and the process ID in the program two are same.
Now these are the arguments.
This is of uh just for reference purpose.
Now if you see this court see user two in child.
So after sleeping for two seconds the parent wakes up the parent process wakes up and sends a signal
called as sig user two.
So sig user one and sig user two are the user defined signals, and these are not generated by the kernel.
So now the parent process sends a signal sig user two to the child.
And this the child process which was running uh maybe it was sleeping for five seconds here.
So when it was sleeping for five seconds here, meanwhile it got a signal called as SIG user two, and
it would have jumped to this line.
And this line is printed.
Yeah.
This is what we can see here.
Got sick user to child.
So this print is coming from here.
So whenever a signal is sent from the parent to the child, uh, after handling the required signal,
it jumps to the signal handler and executes the code specified in the signal handler.
Now if you go forward, we can see sending sig user one to parent.
So now, after sleeping for five seconds, child is about to send user one to parent and now it sends
to the parent's process ID that is, get PID.
Specifies the parent's process id and sends sig user one.
Now in.
Now the sig user one is being handled here.
So since the sig user one is being handled in the parent, for example.
Uh let's see this.
This is the handler of user one.
This is because we have uh we have given the signal system call and handle the handle the sig user one.
After receiving sig user one in the parent process it prints this line.
So this line is coming from the parent process.
If you see here parent got sig user one in parent then later child exits.
After sending the process signal to the parent process, it will sleep for 10s and exits after exiting
Um, the parent is in fact waiting for the child here, and it collects the exit status.
And then after the child exits, the parent process prints these three lines.
That is nothing but these.
So it prints this line, and it it prints the, uh, process ID of parent, and it prints the wait.
Uh, the wait returns the process ID for which it was waiting.
That is nothing but the child process ID and the parent, uh, in the parent, the status is zero.
So since it returned a zero, the exit status is zero here.
So by this demo, we can see how the user defined signal can be sent between related processes or like
between a child and a parent process.
So in turn this user one and two can be used for synchronization between the process