Fourth Chapter process scheduling
4.1 Multi-tasking
1. Multitasking operating system is an operating system that can concurrently execute multiple processes simultaneously.
2. Multitasking operating systems cause multiple processes to clog or sleep, and are not actually put into execution, although they are in memory, but are not in a functioning state.
3, multi-tasking system classification:
(1) Non-preemptive multi-tasking
(2) Preemptive multi-tasking
4, Linux provides a preemptive multi-tasking mode. In this mode, it is up to the scheduler to decide when to stop a process from running so that other processes can get execution opportunities. This mandatory suspend action is called preemption. The time the process is preempted before it can be run is pre-set, called the process's time slice. A time slice is actually the processor time period assigned to each running process.
5. In a non-preemptive multitasking mode, it will execute until the process itself stops running. Processes that actively suspend their operations are called concessions. However, this mechanism has many drawbacks: the scheduler cannot hide from each process how long it takes to make uniform rules, so process exclusive processor time may exceed the user's expectations: Even worse, a suspension process that does not make concessions can crash the system.
4.2 Linux the process scheduling
1. The O (1) Scheduler has a multi-processor-based environment of 10, but lacks an interactive process.
2, inversion stair deadline scheduling algorithm (RSDL), draw the queue theory, fair dispatch. Also known as the Perfect Fair scheduling algorithm (CFS).
4.3 Strategy
1. Decide when the scheduler will let the process run.
4.3.1 I/O consumption-type and processor-consumable processes
1, the process can be divided into:
(1) I/O consumption: Most of the time the process is used to submit I/O requests or wait for I/O requests, often in a running state but with short running times, and eventually blocking when waiting for more requests.
(2) Processor consumption: Most of the time is spent on executing code, unless it is preempted, it will usually run continuously. Because they don't have a lot of I/O requirements. Not part of the I/O driver type.
2, scheduling strategy: To minimize their scheduling frequency, prolong its running time.
3, the scheduling strategy is usually to find a balance between two conflicting objectives:
(1) Fast process scheduling (short response time)
(2) Maximum system utilization (high throughput)
4. Linux tends to prioritize I/O consumption processes.
4.3.2 Process Priority
1, the most basic type of scheduling algorithm is based on priority scheduling, which is based on the value of the process and its demand for processor time to grade the process of thinking.
2, the scheduler always chooses the time slice is not exhausted and the highest priority process runs.
3 . Linux uses two different priority ranges:
(1) Nice
range [ -20,19], the default value is 0;nice value, the higher the priority level is lower;
The nice values in the Linux system represent the proportions of the time slices, and you can view the list of processes in the system using the Ps-el command, which marks the nice value of a column of NI in a timely process.
(2) Real-time priority
Its value can be configured, the default range of changes is [0,99]; the higher the value the higher the priority;
4, the priority of any real-time process is higher than the normal process, that is, real-time priority and nice priority in the disjoint two categories.
5, through the command Ps-eo state,uid,pid,ppid,rtprio,time,comm. View the list of processes in the system and the corresponding real-time priorities (under the Rtprio column), where the process corresponding column displays "-" indicating that it is not a real-time process.
4.3.3 time slices
1. Time slices indicate the time that the process can continue to run before being preempted.
2. The I/O consumption process does not require a long time slice, while the processor consuming process expects the time slice to be longer and better.
3. The CFS scheduler for Linux does not allocate time slices directly to the process, but instead assigns the processor's usage gestures to the process. In this way, the processor time obtained by the process is closely related to the system load. This ratio is affected by the nice value, and the nice value is used as a weight to adjust the processor time use ratio used by the process.
4, the Linux system is preemptive, whether to put a process immediately into operation (that is, to seize the current process), is entirely the priority of the process and whether there is a time slice to decide.
5. CFS Scheduler: The timing depends on how much processor usage is consumed by the new executable program, and if the consumption is smaller than the current process: The new program is immediately put into operation, preemption of the current process, otherwise deferred.
4.3.4 activity of the scheduling policy
1, the text editing program is obviously 1/0 consumption type, because it is most of the time waiting for the user's keyboard input (no matter how fast the user input speed, it is impossible to catch up with the speed of processing) users always want to press the key system can immediately respond.
2, the video coding program is processor consumption type.
3, CFS will always not hesitate to let the text editor be put into operation when needed, and let the video processing program can only run at the time remaining.
4.4 Linux Scheduling Algorithm
4.4.1 Scheduler Class
1, Linux Scheduler is provided in a modular manner, the purpose is to allow different types of processes can be targeted to select the scheduling algorithm. This modular structure is called the Scheduler class, it allows a number of different dynamically added scheduling algorithms coexist, scheduling belongs to their own category of processes.
2. The base Scheduler code is defined in the Kernel/sched.c file.
3, each scheduler has a priority, will be in priority order to traverse the scheduling class, select the highest priority scheduler class.
4. The complete fair dispatch of CFS is a scheduling class for ordinary processes.
4.4.2 Unix process scheduling in the system
1, UNIX use scheduling algorithm is to allocate absolute time slices, so that will trigger a fixed switching frequency, not conducive to fairness. The CFS used by Linux completely abandons the time slice, assigning the process a processor to use the weighting, guaranteeing constant fairness and changing the switching frequency.
4.4.3 Fair Dispatch
1, CFS's timid is to allow each process to run for a period of time, cycle rotation, select the least-run process as the next running process, instead of the allocation to each process time slice of the practice, based on the total number of all running processes to calculate how long a process should run. Rather than relying on nice values to calculate time slices.
2. The nice value is the weight of the processor running in CFS as a process: the higher the Nice value (the lower the priority) the process gets the lower the processor usage weight.
3. Target delay: Approximate value of infinite small dispatch period
4, the minimum granularity: Each process gets the time slice bottom line, the default is 1ms.
5. The processor time obtained by any process is determined by the relative difference of the nice value of its own and all other operational processes.
4.5 Linux implementation of scheduling
1, the implementation of CFS scheduling algorithm:
Four components:
(1) Time accounting
(2) Process selection
(3) Dispatcher entry
(4) Sleep and wake up
4.5.1 Time Billing
1, all the scheduler must be the process run time to do accounting.
2, CFS Use scheduler entity annoying structure (defined in the file struct_sched _entity) to trace the process to run the accounting.
The scheduler entity structure, as a member variable named SE, is embedded within the process descriptor struct task_struct.
2. Virtual Real-time
Vruntime The virtual run time of the variable storage process, which is calculated by standardizing the total number of running processes. The virtual time is in NS, so it is no longer relevant to the timer Street beat. CFS uses the Vruntime variable to record how long a program is running and how long it should run.
Update_curr () Calculates the execution time of the current process and stores it in the variable delta_exec. Then he passes the run time to __update_curr (), which then calculates the run time based on the total number of currently running processes, and finally adds the above weights to the vruntime of the current running process.
Update_curr () is called periodically by the system counter.
4.5.2 Process Selection
The core of the CFS scheduling algorithm: Choosing a process with minimum vruntime worth.
CFS uses a red-black tree to organize a running process queue and use it to quickly find the minimum vruntime worth process.
1. Pick the next task
The process selection algorithm of CFS can be summed up as "the process represented by the leftmost leaf node in the run Rbtree tree." The function to implement this procedure is __pick_next_entity ().
2. Join the process to the tree
Occurs when the process becomes operational (wake-up) or the first time the process is created through a fork () call. The enqueue_entity () function achieves this purpose.
The function updates the run time and some other statistics, and then calls __enqueue_entity () for a heavy insert operation that actually inserts the data item into the red-black tree.
3. Remove a process from the tree
Delete actions occur when a process is blocked or terminated.
4.5.3 Scheduler Entry
The main entry point for process scheduling is the function schedule (), which is the portal that other parts of the kernel use to invoke the process Scheduler: Select which process can run and when it will be put into operation. The only important thing in this function is to call Pick_next_task (), which takes precedence, from high to low, checks each schedule class at a time, and selects the highest-priority process from the highest-priority scheduling class. The core of the function is the for () loop, which implements the traversal.
4.5.4 Sleep and wake up
Hibernate: The process marks itself as dormant, moves out of the executable red-black tree, puts in the wait queue, and then calls schedule () to select and execute a different process.
Wake up: The process is placed in an executable state and then moved from the wait queue to the executable red-black tree.
There are two related process states for hibernation: Task_interruptible and task_uninterruptible. The only difference is that the task_uninterruptible process ignores the signal, and the process of the task_interruptible state receives a signal that wakes up early and rings the signal. The signals in both states are on the same waiting queue, waiting for certain events to run.
1. Waiting queue
The process adds itself to a wait queue by following several steps:
2. Wake up
Through the function wake_up (), it wakes up all the processes on the specified wait queue. It calls the function try_to_wake_up (), which is responsible for setting the process to the task_running state, calling Enqueue_task () to place the process into a red-black tree, setting the need if the awakened process has a higher priority than the currently executing process. _resched logo.
4.6 preemption and Context switching
1, context switch, that is, from one executable process to another executable process, by the definition of KERNEL/SCHED.C in the Context_switch () function is responsible for processing.
2. Schedule () will call this function whenever a new process is selected to be ready to run. It has completed two basic tasks:
(1) Call the SWITCH_MM () declared in , which is responsible for mapping virtual memory from the previous process to the new process.
(2) Call switch_to () declared in <asm/system.h>, which is responsible for switching from the processor state of the previous process to the processor state of the new process. This includes saving, recovering stack information and register information, and any other architecture-related state information that must be managed and saved for each process object.
3. The kernel provides a need_resched flag to indicate if a schedule needs to be re-executed. When a process should be preempted, Scheduler_tick () sets this flag: TRY_TO_WAKE_UP () sets this flag when a high-priority process enters the executable state. The kernel checks this flag to confirm that it is set and calls schedule () to switch to a new process. This flag is a message to the kernel that the youqitajinc should be run and the scheduler should be called as soon as possible. The kernel also checks the flag when it returns to the user space and returns from the interrupt. Each process contains a need_resched flag because the access process describes the value of character faster than accessing a global variable.
4.6.1 User preemption
1. When the kernel is about to return to user space, if the need_resched flag is set, it will cause schedule () to be called, and user preemption will occur at this time.
2, the user preemption in the following situations arise:
(1) When the user space is returned from the system;
(2) When the user space is returned from the interrupt handler;
4.6.2 kernel preemption
1. Linux fully supports kernel preemption.
2. As long as the re-Dispatch is secure, the kernel can preempt the tasks being performed at any time.
3. Kernel preemption can occur in:
(1) The interrupt handler is executing and before the kernel space is returned
(2) The kernel code once again has the time to preempt.
(3) If the task in the kernel explicitly calls schedule ()
(4) If the task in the kernel is blocked (this also causes the call to schedule ()).
4.7 Real-time scheduling strategy
1, Linux provides two kinds of real-time scheduling strategy: Sched_fifo and SCHED_RR. And the normal, non-real-time scheduling strategy is sched_normal.
2, Sched_fifo realizes a simple, first-in first-out scheduling algorithm.
3, SCHED_RR is a sched_fifo with the time alarm, a real-time rotation scheduling algorithm.
4, these two real-time algorithms are implemented by static priority. The kernel does not compute the dynamic priority for real-time processes, which guarantees that a real-time process with a given priority can always preempt a process with a lower priority.
5, soft real-time: Kernel scheduling process, try to make the process before its limited time, but the kernel is not guaranteed to always meet the requirements of these processes.
6, hard real-time: the system to ensure that under certain conditions, can meet any scheduling requirements.
7. Priority Range
(1) Real-time:
Range: 0~[max_rt_prio-1].
Default max_rt_prio=100, so the default real-time priority range is [0,99]
(2) Sched_normal:
Range: [max_rt_prio]~[max_rt_prio+40]
By default, the nice value from 20 to +19 corresponds to a real-time priority range from 100 to 139.
4.8 scheduling-related system calls
4.8.1 system calls related to scheduling policies and priorities
1, Sched_setparam () and Sched__getparam () are used to set and get the real-time priority of the process respectively
2. The nice () function increases the priority of a process by increasing the static priority of a given process by a given amount, and only the superuser can use a negative value when calling it.
3. The nice () function invokes the kernel's set_ user_ nice () function, which sets the Static_prio and Prio values for the task_struct of the process.
4.8.2 system calls related to processor bindings
1, the Linux Scheduler provides a mandatory processor binding mechanism. That is, although it tries to try to make the process run on the same processor as much as possible through a soft affinity, it also allows the user to force the specified "this process must run on these processors anyway". This enforced affinity is stored in the bitmask flag of the cpus_allowed of the process task_struct.
2. The process only runs on the specified processor, and the processor designation is set by the cpus_allowed domain of the process descriptor.
4.8.3 Discard Processor Time
1. Linux is called through the Sched_yieldo system, which provides a mechanism for the process to explicitly cede processor time to other waiting execution processes.
2, kernel code for convenience, you can directly call yield (), first to determine that a given process is indeed in the executable state, and then call Sched__yield ().
3, User space applications directly using the Sched__yield () system call can be.
Linux Kernel Analysis Eighth week reading notes