Summary of Linux Scheduling Policies
----------------------------------
Here, I will only make a summary of some problems encountered. The POSIX thread library is detailed in reference to Sun's multi-thread programming guide.
By water-Aug, 17th. 2010.
----------------------------------
Thread Scheduling Policies include sched_other, sched_fifo, and sched_rr.
Sched_otherA non-real-time-sharing scheduling policy with a thread priority of 0;
Test result (mont2.6 montavista 5.0): Each thread cannot occupy other threads, but the thread is limited by the time slice, not because the thread does not actively exit (including being blocked ), it will remain in use.
However, in Sun's multi-threaded programming manual, it said that threads will always be occupied in this case.
Sched_fifoIt is a real-time first-in-first-out scheduling policy, that is, when the CPU is occupied, the thread runs continuously unless it is blocked or terminated or has a higher priority. The thread priority is 1-99;
Threads are divided into different queues based on different priorities. Threads with the same priority are scheduled by FIFO.
Sched_rrIt is a real-time-based scheduling policy, which does not occupy the CPU all the time. After running a time slice, the CPU will be given to the thread with the same priority. In factSched_rr is similar to sched_fifo, but the former will be limited by time slices. Threads with the same priority are scheduled by time slices. In the case of FIFO, the running thread will not be forcibly occupied by other threads with the same priority unless it exits or is blocked. Therefore, when using the FIFO policy, do not use a thread that has been occupied (do not actively exit or have no pending conditions). Otherwise, other threads with the same priority will never run. In this case, it is best to use the RR policy.
Note: sched_other does not support priority, while sched_fifo and sched_rr support priority. They are 1 and 99, respectively. A larger value indicates a higher priority. The real-time scheduling policy preemptible is a non-real-time scheduling policy. That is, as long as there are two threads of the real-time scheduling policy sched_fifo or sched_rr, threads like sched_other will not run, unless the threads of all real-time scheduling policies are blocked or terminated.
The following test program thread_attr_test.c is used to test the default attributes of a thread;
// Thread_attr_test.c
# Include <stdio. h>
# Include <stdlib. h>
# Include <pthread. h>
# Include <unistd. h>
# Include <sched. h>
Void * thrd_fun (void * Arg)
{
Int my_policy;
Struct sched_param my_param;
Int status;
Pid_t PID;
PID = getpid ();
Printf ("My PID is % d \ n", pid );
Status = pthread_getschedparam (pthread_self (), & my_policy, & my_param );
Printf ("thread_routine running policy is % s, priority is % d \ n", (my_policy = sched_fifo? "FIFO"
: (My_policy = sched_rr? "RR"
: (My_policy = sched_other? "Other"
: "Unkown "))),
My_param.sched_priority );
}
Int main (INT argc, char * argv [])
{
Pthread_t thread_id;
Pthread_attr_t thread_attr;
Int thread_policy;
Struct sched_param thread_param;
Int status, rr_min_priority, rr_max_priority;
Int inherit;
Int detachstate;
Int policy;
Int scope;
Struct sched_param Param;
Pid_t PID;
PID = getpid ();
Printf ("Main PID is % d \ n", pid );
Status = pthread_attr_init (& thread_attr );
Status = pthread_attr_getschedpolicy (& thread_attr, & thread_policy );
Status = pthread_attr_getschedparam (& thread_attr, & thread_param );
Printf ("Default policy is % s, priority is % d \ n", (thread_policy = sched_fifo? "FIFO"
: (Thread_policy = sched_rr? "RR"
: (Thread_policy = sched_other? "Other"
: "Unkown "))),
Thread_param.sched_priority );
Pthread_attr_getinheritsched (& thread_attr, & inherit );
If (inherit = pthread_explicit_sched)
Printf ("pthread_explicit_sched \ n ");
If (inherit = pthread_inherit_sched)
Printf ("pthread_inherit_sched \ n ");
Pthread_attr_getdetachstate (& thread_attr, & detachstate );
If (detachstate = pthread_create_detached)
Printf ("pthread_create_detached \ n ");
If (detachstate = pthread_create_joinable)
Printf ("pthread_create_joinable \ n"); // non-separated
Pthread_attr_getschedpolicy (& thread_attr, & Policy );
If (Policy = sched_other)
Printf ("sched_other \ n ");
If (Policy = sched_fifo)
Printf ("sched_fifo \ n ");
If (Policy = sched_rr)
Printf ("sched_rr \ n ");
Pthread_attr_getscope (& thread_attr, & scope );
If (scope = pthread_scope_system)
Printf ("pthread_scope_system \ n ");
If (scope = pthread_scope_process)
Printf ("pthread_scope_process \ n ");
Pthread_attr_getschedparam (& thread_attr, & PARAM );
Printf ("Priority: % d \ n", Param. sched_priority );
# If defined (_ posix_thread_prioriy_scheduling)
Printf ("supports ");
# Else
Printf ("not supports \ n ");
# Endif
// Struct sched_param Param;
Param. sched_priority = 1;
Pthread_attr_setschedpolicy (& thread_attr, sched_fifo );
Pthread_attr_setschedparam (& thread_attr, & PARAM); // you must set the priority after setting the real-time policy. Otherwise, the thread will fail to be created.
Pthread_attr_setinheritsched (& thread_attr, pthread_explicit_sched); // you must change the inheritance attribute to pthread_explicit_sched to be valid.
// Otherwise, the parent process policy will be inherited.
Status = pthread_create (& thread_id, & thread_attr, thrd_fun, null );
If (status! = 0)
{
Printf ("can't creat! \ N ");
Exit (1 );
}
Status = pthread_join (thread_id, null );
Return 0;
}
The running result is (FC12-2.6.31.5 kernel ):
Main PID is 4318
Default policy is other, priority is 0
Pthread_inherit_sched
Pthread_create_joinable
Sched_other
Pthread_scope_system
Priority: 0
Not supports
My PID is 4318
Thread_routine running policy is FIFO, priority is 1
The running result is (kernel 2.4.18 on the arm Development Board ):
Main PID is 111
Default policy is other, priority is 0
Pthread_explicit_sched is different from the kernel attribute in 2.6 ??
Pthread_create_joinable
Sched_other
Pthread_scope_system
Priority: 0
Not supports
My PID is 113
Thread_routine running policy is FIFO, priority is 1
From the result, we can conclude that the default attribute is:
Other is a non-real-time scheduling policy with a priority of 0 (no priority );
Is an inherited property (2.6) not inherited (2.4 );
Non-separated attribute;
To bind a property, that is, to compete with all threads in the system (including threads of other processes.
After pthread_attr_setschedpolicy is set, the scheduling policy of the sub-thread is set to FIFO and the priority is 1. The priority range must be between the maximum and minimum values. It can be obtained through sched_get_priority_max and sched_get_priority_min. This program is just a simple test.
Note that:
If you modify the scheduling policy to real-time (FIFO or RR), you must set the priority for it; otherwise, the thread creation will fail; remember to change the inheritance attribute to pthread_explicit_shed, otherwise, the sub-thread will continue to inherit the policies of the parent thread, making the policy settings invalid.
Problems:
Some systems need to define _ posix_thread_priority_scheduling to set the thread scheduling policy. However, in this test, the system is not defined. Some systems need to define _ posix_thread_priority_scheduling, but the thread scheduling policy can still be set.
Verification of scheduling policies:
Next facing sched_fifoIs a real-time first-in-first-out scheduling policy, that is, when the CPU usage, unless you block or end or have a higher priority thread, it will continue to run; this policy is verified.
The test program thread_shed_test.c is as follows:
# Include <stdio. h>
# Include <pthread. h>
# Define export o_test
Void * funthread1 (void * Arg)
{
Int I, J;
Int policy;
Struct sched_param Param;
Pthread_getschedparam (pthread_self (), & Policy, & PARAM );
If (Policy = sched_other)
Printf ("sched_other \ n ");
If (Policy = sched_rr)
Printf ("sched_rr \ n ");
If (Policy = sched_fifo)
Printf ("sched_fifo \ n ");
For (I = 1; I <500; I ++)
{
For (j = 1; j <50000; j ++)
{
}
// While (1); // The time slice is limited when you call this function to test the FIFO.
Printf ("thread 1 \ n ");
}
Printf ("thread1 exit \ n ");
}
Void * funthread2 (void * Arg)
{
Int I;
// For (I = 1; I <5000; I ++)
Sched_yield ();
Sched_yield ();
Printf ("thread2 exit \ n ");
}
Void * funthread3 (void * Arg)
{
Int I;
// For (I = 1; I <5000; I ++)
Sched_yield ();
Sched_yield ();
Printf ("thread3 exit \ n ");
}
Int main ()
{
Int I;
Pthread_t ppid1, ppid2, ppid3;
Struct sched_param Param;
Pthread_attr_t ATTR, attr2;
I = getuid ();
If (I = 0)
Printf ("the current user is Root \ n ");
Else
Printf ("the current user is not Root \ n ");
Param. sched_priority = 1;
Pthread_attr_init (& ATTR );
Pthread_attr_init (& attr2 );
Pthread_attr_setschedpolicy (& attr2, sched_fifo );
Pthread_attr_setschedparam (& attr2, & PARAM );
Pthread_attr_setinheritsched (& attr2, pthread_explicit_sched); // newly added, specifying that the parent thread scheduling policy is not inherited
# Ifdef export o_test
Pthread_create (& ppid1, & attr2, funthread1, null );
# Else
Pthread_create (& ppid1, null, funthread1, null );
# Endif
Pthread_create (& ppid2, & ATTR, funthread2, null );
Pthread_create (& ppid3, & ATTR, funthread3, null );
Pthread_join (ppid1, null );
Pthread_join (ppid2, null );
Pthread_join (ppid3, null );
Pthread_attr_destroy (& ATTR );
Pthread_attr_destroy (& attr2 );
Return 0;
}
The running result is (FC12-2.6.31.5 kernel ):
Sched_fifo
Thread 1
Thread 1
Thread 1
.
.
.
.
Thread 1
Thread 1
Thread 1
Thread1 exit
Thread2 exit
Thread3 exit
In the main function, when a thread is created, its scheduling policy is set to sched_fifo, the priority is 1, the scheduling policy of thread 2 and thread 3 is sched_other, and the priority is 0, the correct result should be that thread 2 and thread 3 will be the turn of the first thread to end running. The running results seem to be correct, but please refer to the following text;
If you use the other method (comment out '# define except o_test'), the result is:
Sched_other
Thread 1
Thread 1
Thread 1
.
.
.
.
Thread 1
Thread2 exit
Thread 1
Thread 1
.
.
.
.
Thread 1
Thread 1
Thread3 exit
Thread 1
Thread 1
.
.
.
.
Thread 1
Thread 1
Thread1 exit
In this case, it is time-based scheduling. All three threads have time slice restrictions, and the time slice is replaced by other threads. The result is correct.
But does thread 1 (FIFO Policy) not occupy thread 2 or 3 as long as it does not backend or block itself ??
Add the while (1) endless loop to funthread1 () and test again.
Running result: (FC12-2.6.31.5 kernel ):
The current user is root
Sched_fifo
Thread2 exit
Thread3 exit
--
It is found that thread 1 of FIFO can still be executed after running for a period of time. This proves that even a FIFO thread in the system is restricted by a time slice. When the time slice specified by the system is reached, it must be transferred to other threads for execution. Otherwise, the fc12 system on the PC won't be able to do anything else (obviously not ). However, at this time, we can clearly find that the fc12 system on the PC has a slow response to other operations (such as the mouse. This proves that this so-called time slice should be relatively long.
But run this program on the arm Development Board:
The running result is (kernel 2.4.18 on the arm Development Board ):
The current user is root
Sched_fifo
------
The results show that they are fully consistent with the FIFO theory, that is, when a CPU usage occurs, it will continue to run unless it blocks or ends or has a higher priority thread.
The two platforms have different causes:
The time slice may be added to fc12 on the PC, so the system will not crash easily. Linux on the arm Development Board does not handle the issue.