当前位置: 代码迷 >> 综合 >> Interfupt Handling
  详细解决方案

Interfupt Handling

热度:58   发布时间:2023-12-14 22:48:26.0

Although some devices can be controlled using nothing but neither I/O regions, most real devices are a bit more complicated than that. Devices have to deal with the external world. Which often includes things such as spinning]?sp?n??旋转】disks, moving tape, wires to distant places, and so on. Much has to be done in a time frame that is different form, and far slower than, that of the processor. Since it is almost always undesirable to have the processor wait on external events, there must be a way for a device to let the processor know when something has happened.

 

That way, of course, is interrupts. An interrupt is simply a signal that the hardware can send when it wants the processor’s attention. Linux handles interrupts in much the same way that is handles signals in user space. For the most part, a driver need only register a handler for its device’s interrupts, and handle them properly when they arrive. Of course, underneath that simple picture there is some complexity; in particular, interrupt handlers are somewhat limited in the actions they can perform as a result of how they are run.

 

It is difficult to demonstrate the use of interrupts without a real hardware device to generate them. Thus, the sample code used in this chapter works with the parallel port. Such ports are starting to become scarce on modern hardware, but, with luck, most people are still able to get their hands on a system with an available port. We’ll be working with the short module from the previous chapter; with some small additions it can generate and handle interrupts from the parallel port. The module’s name, short, actually means short int (it is C, isn’t it?) to remind us that it handles interrupts.

 

Before we get into the topic, however, it is time for one cautionary note. Interrupt handlers, by their nature, run concurrently with other code. Thus inevitably raise issues of concurrency and contention to pass over the discussion in Chapter 5, we understand. But we also recommend that you turn back and have another look now. a solid understanding of concurrency control techniques is vital when working with interrupts.

 

Preparing the parallel port

Although the parallel interface is simple, it can trigger interrupts, this capability is used by the printer to notify the lp driver that it is ready to accept the next character in the buffer.

Like most devices, the parallel port doesn’t actually generates an interrupts before it’s instructed to do so; the parallel standard states that setting bit 4 of port 2 (0x37a, 0x27a, or whatever) enables interrupt reporting. A simple outb call to set the bit is performed by short at module initialization.

 

Once interrupts are enabled, the parallel interface generates an interrupt whenever the electrical signal at pin 10(the so-called ACK bit) changes from low to high. The simplest way to force the interface to generate interrupts (short of hooking up a printer to the port) is to connect pins 9 and 10 of the parallel port connector on the back of your system creates this connection. The pinout of the parallel port is show in figure 9-1.

Pin 9 is the most significant bit of the parallel data byte. If you write binary data to /dev/short0, you generate several interrupt. Writing ASCII text to the port won’t generate any interrupts, though, because the ASCII character set has no entries with the top bit set.

If you’d rather avoid wiring pins together, but you do have a printer at hand, you can run the sample interrupt handler using a real printer, as show later. However, note that the probing functions we introduce depend on the jumper between pin 9 and 10 being in place, and you need it to experiment with probing using our code.

 

Installing an Interrupt Handler

If you want to actually ‘see’ interrupts being generated, writing to the hardware device isn’t enough; a software handler must the configured in the system. If the Linux kernel hasn’t been told to expect you’re your interrupt, it simply acknowledges and ignores it.

Interrupt lines are a precious and often limited resource, particularly when there are only 15 or 16 of them. The kernel keeps a registry of interrupt lines, similar to the registry of I/O ports, a module is expected to request an interrupt channel(or IRQ, for interrupt request) before using it and to release it when finished. In many situations, modules are also expected to be able to share interrupt lines with other drives, as we will see. The following functions, declared in <linux/interrupt.h>, implement the interrupt registration interface:

Int request_irq(unsigned int irq,

             Irqreturn_t(*handler)(int, void *, struct pt_regs *)

             Unsigned long flags,

             Const char *dev_name,

              Void *dev_id);

Void free_irq