First, the Linux clock system
1. Clock hardware
Most PCs have two clock sources, RTC (real-time clock) and OS (System clock). RTC is also called a CMOS clock, which is a chip on the PC motherboard. OS clock generated on the PC motherboard timing/counting chip, the operating system control the work of the chip, the basic unit of the OS clock is the count cycle of the chip. The OS is initialized with RTC when the system is power-up. The OS clock is only valid at boot time and is fully controlled by the operating system, so it is also referred to as a soft clock or system clock. The most typical timing/counting chip used by the OS clock is the 8253/8254 programmable timing/counting chip. So of course the pulse is counted, the period of the output pulse is called a "clock tick", the time in the computer is the clock tick units, each time the clock ticks, the system time will be added 1. The operating system can get other time formats in seconds or milliseconds, depending on the number of ticks in the current clock.
650) this.width=650; "src=" Https://s4.51cto.com/wyfs02/M02/08/26/wKiom1nc7JDyv9AjAAAskULi-o0043.png "title=" haha. png "alt=" Wkiom1nc7jdyv9ajaaaskuli-o0043.png "/>
2. Clock operation mechanism
650) this.width=650; "src=" Https://s1.51cto.com/wyfs02/M02/08/26/wKiom1nc7M-AgBFmAAEDKBEgcRo105.png "title=" Gaga. png "alt=" Wkiom1nc7m-agbfmaaedkbegcro105.png "/>
Second, clock interrupt
The physical cause of the Linux OS clock is the programmable timing/counter output pulse, which is fed into the CPU and can trigger an interrupt request signal, which we call the clock interrupt.
Each clock ticks, and the clock interrupts are executed. Clock interrupt execution is very high: 100 times/second, the main task of clock interruption is to process all information about time and decide whether to execute the scheduler. All information related to time includes the system time, the time slice of the process, the time of the CPU, the various timers, the time slice after the process update provides the basis for the process scheduling, and then decides whether to execute the scheduler when the clock interrupt returns.
Third, Linux scheduling program-schedule
1. Scheduling principle
Process operation requires a variety of system resources, such as memory, files, printers and the most valuable CPU, so the essence of scheduling is the allocation of resources.
A good scheduling algorithm (time-slice rotation scheduling algorithm, priority scheduling algorithm, multilevel feedback queue scheduling, real-time scheduling) should consider the following aspects.
(1) Fairness: Ensure that each process gets a reasonable CPU time.
(2) Efficient: Keep the CPU busy, that is, there is always a process running on the CPU.
(3) Response time: The response time of the interactive user is as short as possible.
(4) Turnaround time: Enables batch processing users to wait for the output as short as possible.
(5) Throughput: Make as many processes as possible within a unit of time.
Obviously, five can not be satisfied at the same time, so each scheduling algorithm is to meet one or more of them.
2.Linux Process Scheduling Timing
(1) Time of Process state transition: Process termination, process sleep;
(2) When the time slice of the current process is exhausted (current->counter=0);
(3) device driver program;
(4) The process is returned to the user state from interrupts, exceptions, and system calls.
3. The basis of process scheduling
When the scheduler runs, it is time to select the most worthwhile process to run in all the processes that are in a running state. What is the basis of the selection process? There are 5 items in the TASK_STRUCT structure of each process:need_resched, nice, counter, policy, and Rt_priority are described in the previous process concept, for normal processes, The main basis for the selection process is counter and nice. For real-time processes, Linux uses two scheduling strategies, FIFO (first-come-first service scheduling) and RR (Time-slice rotation scheduling). Because real-time processes have a degree of urgency, it is a relatively fixed standard for Linux to measure whether a real-time process should run. The counter of a real-time process is only used to represent the remaining tick count of the process, not as a criterion to measure whether it is worth running, which is different from the normal process.
Like other operating systems, the time unit of Linux is also "clock ticking", except that different operating systems define a clock tick differently (the Linux designer defines a "clock tick" as 10ms). Here, we call counter the time slice of the process, but in fact it's just the number of ticks in the clock.
4. Measurement of the operational level of the process
The function goodness () is used to measure the degree to which a process in a running state is worth running. This function synthesizes the 5 items we mentioned above, assigning a weighted value (weight) to each process that is in a working state, and the scheduler uses this weight as the sole basis for the selection process.
Static inline int goodness (struct task_struct * p, int this_cpu, STRUCT MM_STRUCT *THIS_MM) { int weight; if (p-> ;; policy ! = sched_other) {/* If it is a real-time process, the */ weight = 1000 + p->;;rt_ priority; goto out; } /* assigns the value of counter to weight, This gives the process a approximate weight, and the value in counter indicates that the process is within a time slice, leaving the time remaining to run .*/ weight = p->; ;counter; if (! Weight) /* weight==0, indicating that the time slice of the process has run out, go directly to the label out*/ goto out; # ifdef __smp__ /* in SMP cases, it is most advantageous if the CPU the process is going to run is the same as the CPU of the process last run, so, If the CPU of the last run of the process is the same as the current CPU, the weight is added to the proc_change_penalty, and the macro is defined as 20. */ if (P->;;PROCESSOR == THIS_CPU) weight += proc_change_penalty; #endif if (p->;;mm == this_mm) /* process p with the current running process, is a different thread of the same process, or a different process for the shared address space, priority selection, weighted value plus 1*/ weight += 1; weight += p->;;priority; /* weight Plus process priority */ out: return weight; /* return value as the only basis for process scheduling, whose weights are large, dispatch who runs */}
* This is the 2.4 version, 2.6 After No goodness, also do not use this way to dispatch, about 2.6 later look.
5. Implementation of Process scheduling
The scheduler is a functionin the kernel, the function of theschedule () function is to select a suitable process to execute on the CPU, it only works according to ' Goodness '. In the case of SMP, in addition to calculating the weighted average run time for each process, other SMP-related parts are mainly represented by the goodness () function.
Asmlinkage void schedule (void) { struct task_struct *prev, * Next, *p; /* prev represents the process before scheduling, next represents the dispatch after */ struct list_head *tmp; int this_cpu, c; if (!CURRENT->ACTIVE_MM) bug ()/* If the current process's active_mm is empty, an error */ need_resched_back: prev = current; /* Let prev Become the current process */ this_cpu = prev->processor; if (In_interrupt ()) {/* If schedule is executed inside the interrupt service program, an error has occurred */        PRINTK (" Scheduling in interrupt\n "); bug (); } release_kernel_lock (PREV, THIS_CPU) /* release the global kernel lock and open the THIS_CPU interrupt */ spin_locK_IRQ (&runqueue_lock); /* locks the running queue and shuts down the interrupt */ if (prev->policy ==  SCHED_RR) /* will run out of time slices SCHED_RR real-time goto move_rr_last; The process is placed at the end of the queue */ move_rr_back: switch (prev->state) {/* according to prev State to do the corresponding processing */ case task_interruptible: /* This state indicates that the process can be signaled by a signal interrupt */ if (signal_pending (prev)) { /* If the process has a signal that is not processed, let it prev->state = TASK_RUNNING; to operational status */ break; } default: /* if it is an interruptible wait state or zombie state */ del_from_runqueue (prev); /* remove */ case from the run queue task_running:;/* if it is a running state, continue processing */ } prev->need_resched = 0; /* The following is the body of the scheduler */ repeat_schedule: /* Really start choosing a process that is worth running */ next = idle_task (THIS_CPU); /* Select Idle process by default */ c = -1000; if (prev->state == task_running) goto still_running; still_running_ Back: list_for_each (tmp,&runqueue_head) { /* traversal run queue */ p =&nbSp;list_entry (tmp, struct task_struct, run_list); if (Can_schedule (P, THIS_CPU)) { /* single cpu, this function always returns 1*/ int weight = goodness (P, THIS_CPU, PREV->ACTIVE_MM); if (weight > c) c = weight, next = p; } } /* if C is 0, the weight of all processes in the run queue is 0, that is, the time slices assigned to each process have been the time slice */ if (!c) for each process needs to be recalculated {  STRUCT TASK_STRUCT *P;        SPIN_UNLOCK_IRQ (& Runqueue_lock);/* Lock the Run queue */ read_lock (&tasklist_lock); / * locked process doubly linked list */ &Nbsp; for_each_task (p) /* */ for each process in the system p->counter = (p->counter >> 1) + nice_to_ticks (P- >nice); read_unlock (&tasklist_lock);      SPIN_LOCK_IRQ (&runqueue_lock);  GOTO REPEAT_SCHEDULE;    }    SPIN_UNLOCK_IRQ (&runqueue _lock);/* Unlock the Run queue and open interrupt */ if (prev == next) { /* If the selected process is the original process */ prev->policy &= ~SCHED_YIELD; goto same_process; } /* The number of times to start the process switch */ kstat.context_swtch++; /* statistics context Switch */ { struct mm_struct *mm = next->mm; struct mm_struct *oldmm = prev->active_mm; if (!mm) { /* If it is a kernel thread, borrow prev 's address space */ if (NEXT->ACTIVE_MM) bug (); next->active_mm = oldmm; } else { /* If it is a generic process, switch to next user space */ if (NEXT->ACTIVE_MM != MM) bug ();    SWITCH_MM (OLDMM, MM, NEXT, THIS_CPU); } if (!PREV->MM) { /* if the kernel thread is switched out */ prev->active_mm = null;/* returns the address space it borrowed */ Share count minus in mmdrop (OLDMM); /*mm_struct 1*/ } } switch_ to (Prev, next, prev); /* process Real switch, that is, the stack switching */ __schedule_tail (prev); /* prev->policy SCHED_YIELD for 0 */ same_process: reacquire_kernel_lock (current);/* for SMP*/ if (current-> need_resched) /* If the dispatch flag is set */ goto need_resched_back; /* Restart dispatch */ return;}
This article from "Three days not reading, IQ than pig!" "blog, declined reprint!"
Simple summary of process scheduling and switching