Reputation: 619
When a program issues an INT command the OS takes over and handles the request right?.I dont understand the opposite of this i..e how the control is transfered from the OS to processes when signals are sent and acted on. Okay the OS sends the signal to the process. How exactly is it even done? When it comes to packets and sockets I can understand the flow of control. Im assuming that the sending signal bit is essentially writing something to a register and setting the program counter to a certain point and moving the machine state back to protected mode. I read a bit about how to register the error handlers with the OS and such things. And that did make some sense . When there is an error simply ask the OS to move the program counter to some point in the user space code which would be the error handling routine. But a lot of it is still very hazy for me. What is the role of the signal? How does the process know that the signal has arrived to be handled?
Could someone explain the low level flow of control during the signal sending and handling process ?
Upvotes: 2
Views: 809
Reputation: 11688
What is the role of the signal?
To let you know that something on the system with enough privileges has sent you a signal, each signal had a disposition
ie a default action that unless caught will do something ie in lots of cases terminate your process or generate a core dump etc.
Okay the OS sends the signal to the process. How exactly is it even done?
The OS can do whatever it wants. I could call arbitrary functions in your program if it wanted, in the case of a signal it checks to see if you have a signal handler set and if so it calls that with the signal number. If not it does what ever the default is for that system.
How does the process know that the signal has arrived to be handled?
You can set a handler that lets you know when it arrives. If you don't set a handler a default action will occur.
In the following code compile it and run it then use CTRL-c
to terminate it or use kill to send it various signal numbers. This demonstrate catching signals.
CAVEAT. The following code has been run on Mac and Linux and makes a lot of assumptions about the integer values if the signals, it's certainly not portable it's here as an example on how you can use signal to set up a signal_handler function only.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
extern char *taunts[];
int taunt();
void sig_handler(int signo) {
switch(signo) {
case SIGHUP: printf("\t%s %d\n", taunts[taunt()], SIGHUP);break;
case SIGINT: printf("\t%s %d\n", taunts[taunt()], SIGINT);break;
case SIGQUIT: printf("\t%s %d\n", taunts[taunt()], SIGQUIT);break;
case SIGILL: printf("\t%s %d\n", taunts[taunt()], SIGILL);break;
case SIGTRAP: printf("\t%s %d\n", taunts[taunt()], SIGTRAP);break;
case SIGABRT: printf("\t%s %d\n", taunts[taunt()], SIGABRT);break;
case SIGFPE: printf("\t%s %d\n", taunts[taunt()], SIGFPE);break;
case SIGKILL: printf("\t%s %d\n", taunts[taunt()], SIGKILL);break;
case SIGBUS: printf("\t%s %d\n", taunts[taunt()], SIGBUS);break;
case SIGSEGV: printf("\t%s %d\n", taunts[taunt()], SIGSEGV);break;
case SIGSYS: printf("\t%s %d\n", taunts[taunt()], SIGSYS);break;
case SIGPIPE: printf("\t%s %d\n", taunts[taunt()], SIGPIPE);break;
case SIGALRM: printf("\t%s %d\n", taunts[taunt()], SIGALRM);break;
case SIGTERM: printf("\t%s %d\n", taunts[taunt()], SIGTERM);break;
default: printf("\tMerde\n");
}
#ifdef __linux__
if (signal(signo, sig_handler) == SIG_ERR) {
printf("Merde: %d\n", signo);
}
#endif
}
int main(void) {
srand(time(NULL));
int i = 0;
for(i = 0; i < 15; i ++) {
if (signal(i, sig_handler) == SIG_ERR) {
printf("Merde: %d\n", i);
}
}
while(1) {
sleep(10);
}
return 0;
}
int taunt() {
return rand() % 12;
}
char *taunts[13] = {
"\n No, now go away or I shall taunt you a second time! With youri\n rubbish signal... ",
"\n You don't frighten us, English pig dogs with your daft signal... ",
"\n Go and boil your bottoms, you sons of a silly person and your\n \
nincompoop signal... ",
"\n I blow my nose at you, so-called \"Arthur King,\" you and all\n \
your silly English K-nig-hts. With your silly signal... ",
"\n I'm French. Why do you think I have this outrageous accent, you\n \
silly king? With your silly signal... ",
"\n Mind your own business With your ludicrous signal... ",
"\n You don't frighten us with your silly knees-bent running around\n \
advancing behavior! With your silly signal... ",
"\n How you English say, I one more time-a unclog my nose in your\n"
" direction, sons of a window-dresser! With your weak signal... ",
"\n No chance, English bedwetting types. With your outrageous signal... ",
"\n Yes, depart a lot at this time and cut the approaching any more\n \
or we fire arrows at the tops of your heads and make castanets\n \
out of your testiclesi already! With your stupido signal.."
"\n And now remain gone illegitimate faced buggerfolk! and your farty\n signal... ",
"\n And, if you think you got nasty taunting this time, you ain't\n heard nothing yet! I signal in your general direction... ",
"\n Daffy English kniggets! Thpppt!... ",
};
Upvotes: 1
Reputation:
This is totally not how it works.
int 0x80 (and the like) is an old method and unused on amd64 (there is a dedicated instruction 'syscall'). This has no relation to the problem though.
In short, threads traverse kernel<->userspace boundary all the time (syscalls, exceptions (e.g. page faults) or simply by being scheduled out). As the thread gets back to userspace it simply checks if there are any signals pending.
What is known as signal delivery is simply about storing an information somewhere that a signal is pending and waking up the target thread to handle it. Woken up thread gets back to userspace boundary, where it does aforentioned stuff.
Actual mechanism required to invoke a signal handler and clean up afterwards is more involved and I can only recommend you get a book on operating systems.
Upvotes: 2