ULK --- Chap 4: ksoftirqd kernel threads (Note)

In recent kernel versions, each CPU has its own ksoftirqd/n kernel thread (where n is the

logical number of CPU). Each ksoftirqd/n kernel thread runs the ksoftirqd() function, which

essentially executes the following loop:

for (;;) {
     set_current_state(TASK_INTERRUPTIBLE);
     schedle();
     while(local_softirq_pending()) {
             preempt_disable();
             do_softirq();
             preempt_enable();
             cond_resched();
     }
}

When awakened, the kernel thread checks the local_softirq_pending() softirq bit mask and invokes,

if necessary, do_softirq(). If there are no softirqs pending, the function puts the current process

in the TASK_INTERRUPTIBLE state and invokes then the cond_resched() function to perform

a process switch if required by the current process (flag TIF_NEED_RESCHED of the current

thread_info set).

The ksoftirqd/n kernel threads represent a solution for a critical trade-off problem.

Softirq functions may reactivate themselves; in fact, both the networking softirqs and the tasklet

softirqs do this. Moreover, external events, such as packet flooding on a network card, may

activate softirqs at very high frequency.

The potential for a continuous high-volume flow of softirqs creates a problem that is solved by introducing

kernel threads. Without them, developers are essentially faced with two alternative strategies:

The first strategy consists of ignoring new softirqs that occur while do_softirq() is running. In 

other words, the do_softirq() function could determine what softirqs are pending when the 

function is started and then executes their functions. Next, it would terminate without rechecking the

pending softirqs. This solution is not good enough. Suppose that a softirq function is reactivated during

the execution of do_softirq(). In the worst case, the softirq is not executed again until the next timer

interrupt, even if the machine is idle. As a result, softirq latency time is unacceptable for networking

developers.

The second strategy consists of continuously rechecking for pending softirqs. The do_softirq() function

could keep checking the pending softirq and would terminate only when none of them is pending. While

this solution might satisfy networking developers, it can certainly upset normal users of the system: if a

high-frequency flow of packets is received by a network card or a softirq function keeps activating itself,

the do_softirq() function never returns, and the User Mode program are virtually stopped.

The ksoftirqd/n kernel thread try to solve this difficult trade-off problem. The do_softirq() function

determines what softirqs are pending and executes their functions. After a few internations, if the flow of

softirqs does not stop, the function wakes up the kernel thread and terminates. The kernel thread has low

priority, so user programs have a chance to run; but if the machine is idle, the pending softirqs are executed

quickly.

原文地址:https://www.cnblogs.com/miaoyong/p/5014911.html