Signals and interrupts a comparison

2019-01-29 17:40发布

问题:

Based on various references, my subjective definition of signals in Linux is "The triggers that are used to notify the processes about an occurrence of a specific event.Event here may refer to a software exception.Additionally signals may also be used for IPC mechanisms." The questions I have are

  • I presume only exceptions (software interrupts) are notified via signals.What about the case of hardware interrupts.
  • What are the various sources of the signal? To me it looks like kernel is always the source of a signal.(except when used for IPC)
  • Difference between the signal handler and the ISR?.
  • Difference between signal blocking and interrupt masking?

回答1:

Interrupts can be viewed as a mean of communication between the CPU and the OS kernel. Signals can be viewed as a mean of communication between the OS kernel and OS processes.

Interrupts may be initiated by the CPU (exceptions - e.g.: divide by zero, page fault), devices (hardware interrupts - e.g: input available), or by a CPU instruction (traps - e.g: syscalls, breakpoints). They are eventually managed by the CPU, which "interrupts" the current task, and invokes an OS-kernel provided ISR/interrupt handler.

Signals may be initiated by the OS kernel (e.g: SIGFPE, SIGSEGV, SIGIO), or by a process(kill()). They are eventually managed by the OS kernel, which delivers them to the target thread/process, invoking either a generic action (ignore, terminate, terminate and dump core) or a process-provided signal handler.



回答2:

I presume only exceptions (software interrupts) are notified via signals.What about the case of hardware interrupts.

Where to begin ? There's lots of different cases. Keep in mind that interrupts are the hardware calling the cpu. Interrupts essentially consist of "hardware needs attention" and a number between 0 and 255. Signals are similar but have 2 parameters : destination process id and an int (32 bit or 64 bits, depending on arch). Hardware interrupts are always handled in kernel space, whereas signals are user-space only things. The kernel uses hardware interrupts for various reasons.

One example of a hardware interrupt that has nothing to do with signals is the VM subsystem. You know that on modern operating systems you can allocate more memory than actually exists on the system. So how does this work ? Well it works by exploiting hardware interrupts. When you allocate memory, the kernel takes a note of it, but doesn't actually do anything at all. Then, when you try to access the allocated memory, the cpu is going to complain "but this memory doesn't exist", which will generate a hardware interrupt. The kernel will go and look through it's notes, find that you indeed requested that memory, clear some memory it has free, and tell the cpu to "map" that memory in the expected location. After which the kernel resumes your program at the point just before the hardware interrupt occured and this time the process will find the memory just fine.

Multitasking is also implemented through exploiting a hardware interrupt. All drivers generally work by interpreting interrupts.

Signals are used to communicate between processes. Something very "signal-y" would be the common behaviour for linux daemons to reload their configuration on SIGHUP, loved and hated by sysadmins all over the places. When you modify, say, an apache config, the process does not automatically start using the new config. You might terminate and restart the process, but that means that 4-5 seconds your http server is going to be out of the air. So instead you might "killall -HUP apache". This is going to call a subroutine in the apache process, which will make it re-read it's config file.

Process suspending is implemented through signals (ctrl-z), process interrupting (ctrl-c), process quitting (ctrl-), terminal disconnects (sighup), ... a more complete list can be found here : http://en.wikipedia.org/wiki/Unix_signal.

One conclusion might be that they're sort-of similar, but they operate at a different level : hardware interrupts are, well, the hardware crying for attention, and the lowest level software obliges. Generally the kernel handles all hardware, and informing processes is done somewhat independant of the hardware interrupts. For a number of signals default handling is provided (e.g. ctrl-z, ctrl-c, ...), for others the implementation is very application dependant (e.g. SIGHUP).

When it comes to signals, well these are just software-defined. They do whatever you may want them to do, and linux comes with convenient methods to call these subroutines. In some cases the kernel might call a signal routine (e.g. SIGSEGV, SIGCHILD, ...), but it hardly ever involves hardware. They're just a convenient way to trigger a specific routine in an application.

There used to be a special case : the "OS" interrupt, in DOS 21h. This is no longer used (though still works), but the idea is this. A program can trigger a specific interrupt to ask the kernel to perform specific actions. The actions being the syscalls (opening a file, closing a socket, what have you). As I said, interesting, but no longer really used.

What are the various sources of the signal? To me it looks like kernel is always the source of a signal.(except when used for IPC)

A signal either comes from the process itself (SIGABRT), from the kernel (SIGSEGV, ...) or from other processes, like the shell for example (ctrl-z, ctrl-c, ctrl-\, ...) or from kill. But they can come from any other program through using the kill libc function :

   #include <sys/types.h>
   #include <signal.h>

   int kill(pid_t pid, int sig);

Difference between the signal handler and the ISR?.

The main difference is that ISRs live in kernel space and have to take into account that the entire computer is frozen during their execution. This means that they can have interrupted any process, and anything in the kernel. They also "stop the world". While an interrupt is being handled, nothing else will happen. So if an interrupt handler waits for something, the machine freezes. If an interrupt handler goes into a loop, your only option is rebooting the machine.

ISRs are REALLY hard to get right. There's lots of theory on them, on linux they have top half and bottom half sections, with all sorts of priority handling, special memory allocation, ... and it's a minefield. One step in the wrong direction in an ISR will kill the machine. A bug in an ISR will cause dataloss, maybe even outright hardware failure. In fact speaking from experience, merely raising suspicion that you might be planning to do something wrong in an ISR immediately results in completely unpredictable machine behavior.

You can't use any kernel facilities in ISRs. Opening a file, forget it. Allocating memory, forget it. Calling any other part of the kernel, forget it (with a few, but only a few, exceptions). The list goes on.

Signals are just functions in specific processes getting called. A signal can block (e.g. ctrl-z) and this will stop the process from making progress, but for example your shell session will still respond. The process needs to take into account that any part of the program may have been interrupted of course, but it's still normal user space. You can block, you can loop, you can open files, allocate memory, ... whatever you want.

Difference between signal blocking and interrupt masking?

They're quite similar. Except signal blocking is done on a per-process basis. In both cases there are unblockable signals, and there is a NMI (non maskable interrupt) (both indicate serious errors).

In the end signals and interrupts are sending a number, either to the kernel or to a specific processes. Signal blocking and interrupt masking just means telling the system to ignore specific numbers.

One difference is that interrupt masking is implemented in hardware.



回答3:

Signals and interrupts behave in pretty similar ways. The difference is that signals happen to a process (which lives in a virtual environment), while exceptions are system-wide.

Certain faults are flagged by the CPU as an exception, and then mapped to a signal that is delivered to the process by the kernel. The kernel can choose to hide any exception from the process (for example, accesses to unmapped memory are silently fixed up by paging).

Hardware interrupts are simply a kind of exception, which the kernel may choose to map to a signal (for example, if you use alarm(2)).

The kernel generates signals in response to various events, among them exceptions, I/O completion, explicit userspace requests, ...

Signal handlers behave similarly to ISRs -- they can be invoked at any time, so they cannot make any assumptions about the state of the program, just like ISRs -- and blocking signals behaves the same way inside the virtual address space as masking interrupts does on the physical machine.