Interrupt handling of the Linux Kernel Design Foundation (i)

Source: Internet
Author: User

Suppose that the kernel periodically polls the device. In order to deal with the equipment, that would do a lot of useless, it would be a smart way to let the device proactively notify the kernel when it needs the kernel, which is the interruption.

In response to a specific interrupt, the kernel runs a function-interrupt handler.

The difference between an interrupt handler and other kernel functions is that the interrupt handler is called by the kernel to respond to interrupts, and they run in a special context that we call the interrupt context.

We expect the interrupt handler to run fast. and want to let it over the workload, the two goals of each other constraints, how to solve-the upper and lower half of the mechanism .

We cut the interrupt handling into two halves. We use a network card to explain these two halves.

Notifies the kernel when the NIC accepts a packet, triggering an interrupt. The top half of the so-called is to read the packet to memory in time. It is a very urgent task to prevent loss due to delays. When the memory is read, the processing of the data is no longer urgent, when the kernel can run the program before the interruption, and the processing of the network packets to the next half of processing.

Let's take a look at the first half of the process.

Registration and logoff of interrupt handlers

The device driver uses REQUEST_IRQ () to register the interrupt handler. and activates the given medium break.

int REQUEST_IRQ (unsigned int IRQ,                         irq_handler_t handler,                         unsigned long flags,                         const char *name,                         void *dev)

The IRQ represents the interrupt number, and handler is a pointer to the interrupt handler. REQUEST_IRQ () successfully returns 0 when a non-0 value is returned, indicating that an error occurred and that the interrupt handler will not be registered.

when uninstalling a device driver, you need to unregister the corresponding interrupt handler and release the disconnection. The call to free_irq--assumes that there is no interrupt handler on the given interrupt line, and the handler for the response is unregistered. and disable the disconnection.

Interrupt handling mechanism


The lower half is strictly not an interrupt handler (since the interrupt returns and then runs the lower part), which is the split handler used to reduce its own work.

Upper and lower half division principle

(1) Suppose a task is very sensitive to time. Put it in the interrupt handler to run;

(2) Assume that a task is related to the hardware, put it in the interrupt handler to run;

(3) Assume that a task is guaranteed not to be interrupted by another interrupt. Put it in the interrupt handler to run;

(4) All other tasks. Consider placing in the lower half of the run.

The meaning of the upper and lower half part

The top half is simple and high speed. The runtime disables some or all interrupts. The lower half runs later and can respond to all interrupts during the run. Such a design can improve the system's responsiveness by keeping the system as short as possible when it is in an interrupt-blocking state.

Soft interrupt of realization mechanism in the second part

Triggering soft interrupts in an interrupt handler is the most common form. In such a case. The interrupt handler runs the related operation of the hardware device. The corresponding soft interrupt is then triggered and the last exit.

After the kernel runs the interrupt handler, the DO_SOFTIRQ () function is called immediately, and the soft interrupt starts running the rest of the task that the interrupt handler left for it to finish.

Soft interrupt registration methods such as the following:

OPEN_SOFTIRQ (NET_TX_SOFTIRQ, net_tx_action);

The previous number of references is the index of the soft interrupt. The following is the handler function. The soft interrupt handler is run. Consent to the interruption of the response, but it cannot hibernate itself.

The tasklet of the realization mechanism of the lower half part

Tasklet is implemented by soft interrupts, so it is also a soft interrupt itself.

first declare your own Tasklet,declare_tasklet (name, func, data) when the Tasklet is dispatched. The given function func is run. Its parameters are given by data. Next, define the Tasklet handler void Tasklet_handler (unsigned long data) and start the dispatch. the Tasklet is dispatched by Tasklet_schedule () and Tasklet_hi_schedule ().

Tasklet_schedule () Run the steps:

(1) Check whether the status of Tasklet is tasklet_state_sched. The assumption is that the tasklet has been passed and the function returns immediately.

(2) Call _tasklet_schedule ().

(3) Save the interrupt state, and then disable the local interrupt. When we run the Tasklet code, this ensures that when tasklet_schedule () processes these tasklet, the data on the processor is not messed up.

(4) Add the tasklet that need to be dispatched to each processor one of the Tasklet_vec linked list or Tasklet_hi_vec linked table header.

(5) Wake the TASKLET_SOFTIRQ or HI_SOFTIRQ soft interrupt so that the Tasklet is run the next time you call DO_SOFTIRQ ().

(6) The recovery is interrupted to its original state and returned.

Work queue for the lower half of the implementation mechanism

Assume that a task that runs backwards needs sleep. Then choose a work queue, assuming you don't need to sleep, then choose soft Interrupts or Tasklet.

The work queue can run in the process context, which delegates the work to a kernel thread. We use struct workqueue_struct to represent worker threads, and worker threads are implemented with kernel threads. And the worker thread is how to run the deferred work--there is such a list. It is composed of structural work_struct, and this work_struct describes a work, once the work is run out. The corresponding Work_struct object is removed from the list, and the worker thread continues to hibernate when there are no more objects on the list. These logic is implemented through the function Worker_thread ():

(1) The thread sets itself to hibernate. and add yourself to the waiting queue.

(2) Assume that the work list is empty. The thread calls the schedule () function into hibernation.

(3) If there is an object in the linked list, the thread does not hibernate. Instead. It will be out of the waiting queue.

(4) Assuming that the list is not empty, call Run_workqueue () to run the deferred work.

In addition, cpu_workqueue_struct represents a worker thread. Instead, workqueue_struct represents a class of worker threads.

Create worker thread, declare_work (name, void (*FUNC) (void *), void *data) or init_work (struct work_struct *work, void (*func) (void *), V OID *data), which is statically created, which is created by a pointer at run time.

The worker thread is created, and next you should define the function Work_handler it will run. The Schedule_work (&work) is then used to dispatch the worker thread for wake-up and hibernation.

Interrupt handling of the Linux Kernel Design Foundation (i)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.