Interrupts and interrupt handlers
- interrupts can occur at any time, interrupting CPU execution and CPU switching to processing interrupts.
- Different devices correspond to different interrupts, each with a unique digital flag.
- These interrupt values are called interrupt request (IRQ) lines , and each IRQ line is associated with a numeric value.
- Interrupt handlers
- When the response is interrupted, the kernel executes a function, the interrupt handler/Interrupt Service routine ISR, and the interrupt handler for a device is part of his device driver.
- IO resources include: interrupts, I/O ports, shared RAM,DMA. The driver requires administrative registration to release these resources.
Top half : Immediately after receiving an interrupt, only work with strict deadlines, such as an interrupt answer or reset hardware.
Lower half : The work that can be allowed to be completed later is deferred to the lower part.
- Registering an interrupt handler
- REQUEST_IRQ (UINT IRQ, irq_handlet_t handler, ulong flasgs,void* Dev) registers an interrupt handler to activate the given interrupt line; This function may sleep, not in the interrupt context/ Other code that does not allow blocking is executed.
- When uninstalling the driver
- Unregisters the corresponding interrupt handler and releases the disconnection. void Free_irq (UINT IRQ, void* Dev);
- Linux interrupt handlers do not need to be re-entered, and a given interrupt handler will be blocked on all processors when executed.
Interrupt context: No fallback process, no sleep. The interrupt handler interrupts the other code.
Implementation of interrupt processing mechanism
- The device interrupts and sends the electrical signal to the interrupt controller via the bus
- If the interrupt line is active, the interrupt controller sends an interrupt to the processor (processor-specific pin)
- If the processor does not disable the interrupt, the processor stops what it is doing to shut down the interrupt system and switches to the pre-defined interrupt handler entry.
- Each interrupt line is transferred to a unique location. The initial entry point holds this line break, the value that holds the register is called DO_IRQ ()
- Calculates the interrupt number, interrupts the interrupt response, and disables the interrupt delivery on this line
- Make sure that there is a valid handler on this interrupt line that has been started but not executed.
- Call the interrupt handler in the Handle_irq_event () call to install the disconnection.
- Disables the interrupt and returns to DO_IRQ.
- Do cleanup work, return to the initial entry point, jump to Ret_from_intr ()
- Check whether the schedule hangs; restore registers; the kernel reverts to the point of interruption.
Disables current processor interrupts and activation interrupts,
Local_irq_disable (); local_irq_enable ();
Unsigned long flags; Local_irq_save (flags); Local_irq_restore (flags);
Prohibit specified interrupts
DISABLE_IRQ (int); Disables interrupts to all processors.
The logical allocation principle is processed on the interrupt handler and the next half step:
- Top half:
- Task is very sensitive to time
- Task and hardware related
- Mission guaranteed not to be interrupted by other interrupts, not concurrent, not blocked
- Bottom half:
- Not sensitive to time
- and hardware Independent
- Can be interrupted by other interrupts, can sleep, can be concurrent
The top half of Linux is an interrupt handler, and the lower half has several mechanisms:
Soft interrupt
A soft interrupt is a set of statically defined lower-half interfaces, 32 of which can be executed concurrently on all processors, the same type, or statically registered at compile time.
Realize:
struct//<linux/interrupt.h> 表示软中断 void (*action)(struct softirq_action*);}
32 of the 6 are currently used.
staticstruct softirq_action soft_irq_vec[NR_SOFTIRQS];//kernel/softirq.c软中断数组
- Interrupt handler: Executes the action function when the kernel runs the soft interrupt handler.
A soft interrupt does not preempt another soft interrupt. The only thing that can preempt a soft interrupt is an interrupt handler. Other soft interrupts even the same type can be executed concurrently on other processors
- Software Interrupt execution: A registered software interrupt is executed after the token is marked, which is called a triggering interrupt.
The interrupt handler marks the soft interrupt before returning.
When: Hardware interrupt code is returned; in KSOFTIRQ kernel thread; Display check performs soft interrupts, pending soft interrupts are checked and executed
Soft interrupts are performed in DO_SOFTIRQ
u32 pending;pending = local_sofqirq_pending();if(pending){ struct softirq_action* h; set_softirq_pending(0); h = softirq_vec; do{ if1){ h->action(); } h++; pending >>=1; }while(pending);}
Using soft interrupts
Soft interrupts are reserved for the most demanding and important lower half of time. Currently only the network, SCSI using kernel timers and tasklet are built on soft interrupts.
- Static declaration of soft interrupts by enumeration type and allocation of indexes
- Registering a handler
- OPEN_SOFTIRQ (net_tx_softirq,net_tx_action); When the program executes in a soft interrupt, it allows the response to be interrupted, but not sleep. Because only the current processor is banned from running, other processors can run handlers at the same time, requiring lock protection.
- RASE_SOFTIRQ (NET_TX_SOFTIRQ) sets the soft interrupt to the pending state, which is executed the next time the DO_SOFTIRQ is called.
Tasklet
Based on software interrupt implementation, the flexible, dynamic creation of the lower half of the implementation mechanism. Two different types of tasklet can be run on different processors, but the same is not possible. You can register dynamically through code.
Implementation: Based on soft interrupts
struct tasklet_struct { struct tasklet_struct *next; unsignedlong sate;//(0/TASKLET_STATE_SCHED/TASKLET_STATE_RUN) atomic_t count;/*引用计数器,0允许执行,否则禁止*/ void (*func)(unsignedlong);/*执行函数*/ unsignedlong data;//func的参数};
scheduling : Each processor has a tasklet_vec and TASKLET_HI_VEC structure, with low, high priority tasklet_strucu linked lists, respectively
Dispatched by Tasklet_schedule () and Tasklet_hi_schdule ()
- Check if Tasklet is tasklet_state_sched. If it is returned
- Call _tasklet_schedule
- Save interrupt State, prohibit local interrupt
- Add the processor that needs to be dispatched to the head of the Tasklet_vec or Tasklet_hi_vec list
- Evoke TASKLET_SOFTIRQ or TASKLET_HI_SOFTIRQ soft interrupts
- Resumes the interrupt state and returns
Soft Interrupt Handler:
Tasklet_action (), Operation of Tasklet_hi_action ()
- Disable interrupts
- Set the current processor to null to empty the list
- Allow interrupts
- Loop through the list of each tasklet to be processed
- If it is a multiprocessor system, determine if it is tasklet_state_sched, if it is running, skip.
- If not in execution, set Tasklet_state_run.
- Check count==0, otherwise tasklet is forbidden, skip.
- Execute tasklet, empty Tasklet_state_run flag
- Perform the next Tasklet
Using Tasklet
- Statement Tasklet:
- Declare_tasklet (Name,func,data) declare_tasklet_disabled (.)
Tasklet_init (t, Tasklet_handler, Dev);
- Write handlers: Because they are implemented by soft interrupts, handlers cannot sleep. Tasklet allow response interrupts.
- Call Tasklet_schedule (&my_tasklet), dispatch Tasklet, is actually marked/suspended, as long as there is a chance, My_tasklet will execute as soon as possible.
Tasklet_disable (&my_tasklet); Tasklet_enable (&my_tasklet); prohibited and activated
Compromise
Frequent interruptions or tasklet occur frequently: as soon as possible, the user process is not responding, lag execution, interrupt processing is also unpleasant.
= = "uses a low-priority core process to handle soft interrupt ksoftirqd/n
for(;;){ if(!softirq_pending(cpu)){ schedule(); } set_current_state(TASK_RUNNING); while(softirq_pending(cpu)){ do_softirq(); if(need_schdule())schedule(); }}
Work Queue:
The lower half of the function is left to the kernel thread, which has a thread context and can sleep.
Provides an interface for creating worker threads, which provides an interface to queue tasks that need to be deferred, providing default worker threading to work in the lower half of the queue.
Implementation: Data structure
- Each worker thread has a WORKQUEUE_STRUCT structure
- There's a nr_cpus in there. A worker thread that corresponds to each processor cpu_work_queue_strcut
- Work is represented by Work_struct, which contains an execution function fuc, each CPU worker thread corresponds to a work_struct linked list.
The core of Worker_thread () is a dead loop
- The thread places itself in a dormant state
- If the linked list is empty, hibernate
- Not NULL, call the Run_workqueue function to perform the work.
- Loop execution when the linked list is not empty
- Select the next node object to get the execution function and parameters
- Pending Flag Clear 0
- Calling functions
- Repeated execution
Use:
- Create a deferred job
Declare_work (name, void (func) (void), void*data), static
Init_work (Strut work_struct* task,...); Dynamic
- Work Queue processing functions
Runs in the process context, allowing the response to be interrupted, not holding the lock, and can sleep. Unable to access user space
- Scheduling a job
Schedule_work (&work); submit to worker process
Schedule_delay_work (&work,delay)
- Refresh operation
Flush_scheduled_work (), the function waits for all objects in the queue to be executed later to return
- Create a new Work queue
If the default queue does not meet your needs, you should create a new work queue and a corresponding worker thread.
Comparison of the various mechanisms
| the lower half of the |
Context |
Sequential Execution Assurance |
| Soft interrupt |
Interrupt |
No |
| Tasklet |
Interrupt |
Same type cannot be executed concurrently |
| Work queue |
Process |
Not (as with the process context, is dispatched) |
If the task needs to be pushed backwards to the process context to complete, there is a need to hibernate the work queue
Task queue interface is simple, same type cannot execute Tasklet simultaneously
Soft interrupts provide minimal assurance of execution serialization and must be taken with extreme care to ensure that data is shared
Linux kernel design and implementation learn notes-interrupts, interrupt handlers