Read thin "Linux kernel design and Implementation" (4)-Interrupts and synchronization

Source: Internet
Author: User

This article is part IV of the article "reading thin"linux core design and implementation ", which focuses on the following issues: concepts and implementation principles of interrupt and interrupt handlers, the lower half of Linux, and the kernel synchronization method.

0x00 Interrupt and Interrupt handler I interrupt
    • Interrupt is a special electrical signal, from the hardware to the processor, when the processor receives an interrupt, the box will be immediately reflected in the operating system, processed by the OS. Interrupts can be generated at any time, so the kernel can be interrupted at any time due to a new outage.

    • Different devices have different interrupts, each with a unique digital ID, often referred to as interrupt request (IRQ) lines.

II Interrupt Handling Program
    • The interrupt handler becomes an interrupt processing routine (ISR), which is a function that the kernel executes when the response is interrupted.

    • One interrupt handler corresponds to one interrupt, and one device may emit multiple interrupts

    • For external devices, the interrupt handler is part of the device driver

    • In Linux, interrupt handlers and C functions differ little, but have their own specifications, primarily the runtime needs to be in the context of the interrupt

0x01 Interrupt handling mechanism I register interrupt handler

A driver can request_irq() register an interrupt handler (linux/interrupt.h) through a function

int request_irq(unsignedint irq,                irqhandler_t handler,                long falgs,                constchar *name,                void *dev)
    • irq:Represents the interrupt number to be assigned

    • handler:A pointer to the actual interrupt handling function that handles this interrupt

typedef irqhandler_t(*irq_handler_t)(intvoid*);
II Release Interrupt Handler

When uninstalling the driver, you need to unregister the response interrupt handler and release the break.

void free_irq(unsignedintvoid *dev);

If the specified interrupt line is not shared, the function deletes the handler while the interrupt line is disabled, and the interrupt line is shared, and only the dev corresponding handler is deleted, and the interrupt line itself is disabled only when the last handler is deleted.

III prohibition and activation of interrupts
local_irq_disable();local_irq_enable();
IV Upper half and lower part

and want to interrupt the processing program to run fast, and want to interrupt the process to complete a lot of work, these two purposes are obviously inconsistent, so the interruption processing is divided into two parts:

    • The interrupt handler is the top half, receives an interrupt, it starts execution immediately, but only works with strict deadlines, such as some work that can only be done if the interrupt is disabled

    • Work that can be allowed to be done later will be postponed from 2 to the lower half, after which, at the right time, the lower part will be interrupted.

Q1: Why do you want to split the top half and the lower half? {% ENDCQ%}

    • The interrupt program executes asynchronously, possibly interrupting the execution of important operations, as soon as possible.
    • The interrupt handler masks other sibling interrupts, so the faster the execution the better
    • Interrupt handlers often require hardware operations, often with a high time-frame requirement
    • The interrupt handler does not run in the context of the process, so it cannot block

Q2: How to separate the top and bottom halves? {% ENDCQ%}

    • If a task is sensitive to time, put it in the top half;
    • If a task is related to hardware, put it in the top half;
    • If a task is guaranteed not to be interrupted by another interrupt, place it in the top half;
    • All other tasks are considered to be placed on the lower half.
0x02 the lower half of the

The second part of the task is to perform work that is closely related to terminal processing but the interrupt handler itself does not perform. We expect the interrupt handler to put as much work as possible into the lower half of the execution to quickly return from the interrupt.

I lower half realization mechanism a. Soft interrupt

The soft interrupts here are different from the int 80H used by the system call and are supported by the operating system, statically allocated during compilation

Implementation of soft interrupts
    • Defined linux/interrupt.h in:
struct softirq_action{    void (*action)(struct//待执行的函数    void//传递的参数}
    • A maximum of 32 soft interrupts, defined inkernel/softirq.c
staticstruct softirq_action softirq_vec[NR_SOFTIRQS];
Soft interrupt handlers
void softirq_handler(struct//传递整个结构体
Perform soft interrupts

A registered soft interrupt must be marked before the following is performed, and the pending soft interrupt is checked and executed:

    • In the KSOFTIRQD kernel thread
    • In code that explicitly checks and executes the soft interrupt to be processed (such as the network subsystem)

Soft interrupts are performed regardless of the timing of the execution do_softirq

Using soft interrupts
    • Allocation index: linux/interrupt.h A new soft interrupt is declared by one of the enumeration types in

    • Registration handler: Registers a soft interrupt handler at run time by calling, open_softirq() with two parameters, soft interrupt and handler function

    • Trigger Soft Interrupt: The raise_softirq() function can set a soft interrupt to suspend, allowing it to run the next time the do_softirq() function is called

B.tasklet

Soft interrupt-based implementation, but its interface is simpler and lock protection is less demanding

The realization of Tasklet
    • Tasklet Structural Body (linux/interrupt.h)
struct tasklet_struct{    struct tasklet_struct *next;    //链表    unsignedlong state;    //tasklet 状态    //引用计数器    void (*funx)(unsignedlong);    //taklet 处理函数    unsignedlong//给处理器函数传递的参数}
Dispatch Tasklet

The soft interrupts that are triggered are stored in 2 data structures:, both tasklet_vec task_hi_vec of these data structures are composed task_struct of linked lists, tasklet_schedule() and are dispatched by, and the task_hi_schedule() scheduling steps are as follows:

(1) Check the Tasklet status and TASK_STATE_SCHED return if
(2) Call _tasklet_schedule()
(3) Save interrupt State, prohibit local interrupt
(4) Add the Tasklet to or from the list to be dispatched tasklet_vec tasklet_hi_vec
(5) TASKLET_SOFTIRQ invoke or HI_SOFTIRQ soft interrupt, the next call do_softirq() will execute the Tasklet
(6) Resume interrupt

    • Soft Interrupt Handler: tasklet_action() or task_hi_action() [core of Tasklet processing ]:
      • (1) No interruption
      • (2) Set the list header on the current processor to NULL
      • (3) Allow interrupts
      • (4) Cyclic traversal of tasklet to be processed on the linked list
      • (5) If it is multiple processors, check TASKLET_STATE_RUN to see if the Tasklet is running on the other processor, and if so, jump to laugh a tasklet
      • (6) If no, setTASKLET_STATE_RUN
      • (7) Check if Count is 0, make sure Tasklet is not forbidden, if forbidden, skip to next Tasklet
      • (8) Execution of Tasklet processing procedures
      • (9) After execution, clearTASKLET_STATE_RUN
      • (10) Repeated execution of the next Tasklet
Use Tasklet to declare your own Tasklet:
    • Static: 2 macros in Linux/interrupt.h:
DECLARE_TASKLET(name,func,data);DECLARE_TASKLET_DIASBLED(name,func,data);
    • Dynamic: A pointer is assigned to a dynamically created Tasklet_struct:
tasklet_init(t, takslet_handler, dev);
Write your own Tasklet handler
void tasklet_handler(unsignedlong data)

Note: You can no longer use semaphores or other blocking functions in Tasklet

Dispatch your own tasklet.
tasklet_schedule(&my_tasklet);tasklet_enable(&my_tasklet);tasklet_disable(&my_tasklet);
Ksoftirqd

KSOFTIRQD is a kernel thread, each processor has one that handles soft interrupts in the idle processor

for(;;){    if(!softirq_pending(cpu))        schedule();    set_current_state(TASK_RUNNING);    while(softirq_pending(cpu)){        do_softirq();        if(need_resched())        schedule();    }    set_current_sdtate(TASK_INTERRUPTIBLE);}

As long as the soft interrupt remains to be processed, the thread will process

C. Work queue

The work queue mechanism gives the next half function to the kernel county to execute, the thread context, can sleep

Implementation of the Task Force column
    • Provides an interface to create worker threads
    • Provides default worker threading to work in the lower half of the queue
    • Provide the interface to the queue for tasks that need to be pushed out.
Processing mechanism
    • The thread sleeps itself and adds to the wait queue (task_interruptible)
    • If the work list is empty, thread calls schedule() , hibernate
    • If not empty, set yourself asTASK_RUNNING
    • Call run_workqueue() to perform deferred work

This function loops through each of the pending work on the list:

    • When the list is not empty, select the next Node object
    • Get the functions and arguments to execute
    • Pending the node from the linked list, zeroing the position
    • Calling functions
    • Repeated execution
Use of Task Force columns
    • Create a deferred job:

Static:

void(*func)(voidvoid *data);

Dynamic:

INIT_WORK(structvoid(*func)(voidvoid *data);
    • Work Queue processing functions
void work_handler(void *data)
    • Scheduling of the work
schedule_work(&work);schedule_delayed_work(&work, delay);
    • Refresh operation
void flush_scheduled_work(void);
comparison of 3 lower half mechanisms
mechanism Context Sequential Execution Assurance
Soft interrupt Interrupt No
Tasklet Interrupt Same type cannot be executed concurrently
Work queue Process Not (as the process context is dispatched)

Q: What kind of mechanism do we choose? {% ENDCQ%}

If you have hibernation requirements, select the work queue; otherwise, it is best to use tasklet; If you have to focus on performance improvements, select soft interrupts

II lock between the lower half
    • If the process context and a lower half share data, you need to suppress the processing of the lower half and get the lock right before accessing the data.

    • If the interrupt context and a lower half share the data, you need to disable the interrupt and get the lock right before accessing the data

0x03 Core Sync I critical section

A critical section is a code snippet that accesses and operates shared resources, and must be guaranteed to be executed atomically to ensure security.

II Plus Lock

Ensure that there is only one in the county where the critical section is executed

III Causes of concurrency
    • Interrupt

    • Soft interrupts and Tasklet

    • Kernel preemption

    • Synchronization of sleep and user space

    • Symmetric multi-processing

IV Deadlock Generation conditions
    • To have one or more execution threads and one or more resources

    • Each thread waits for one of the resources

    • All the resources are occupied

    • All the counties are waiting for each other, but they will never release the resources they already possess.

V Kernel Synchronous Method Atomic operation
    • Atomic integer Manipulation (asm/atomic.h)
atomic_dec_and_test(atmoic_t, *v)
    • Atomic bit operation (ASM/BITOPS.H)
set_bit(0, &word)
Spin lock
    • Spin locks can only be held by an executable process

    • The process is busy (rotated) if a occupied lock is contended

    • Spin lock can not be used for a long time, otherwise the efficiency is low

This article's copyright belongs to the author Luo voyage All, uses Attribution-noncommercial 3.0 License. Any person may reproduce, share, but not be used without permission for commercial purposes; reprint please specify the source. Thanks for cooperating!

Read thin "Linux kernel design and Implementation" (4)-Interrupts and synchronization

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.