實時調度:操作系統在有限的時間內提供特定水平的服務能力。受限制的響應時間不一定是塊的反應,意味着可預知的響應速度。如果系統定義_POSIX_THRAED_PRIORITY_SCHEDULING,它為線程指派實時調度優先級提供支持。支持_POSIX_THRAED_PRIORITY_SCHEDULING的系統必須提供至少包括成員seched_priority的struct sched_param結構體的定義,seched_priority的標准策略是SCHED_FIFO和SCHED_RR使用的唯一參數。
影響實時調度:調度策略,參數,競爭范圍和分配域
實時調度在某種程度上不一定很快,實時調度可能會變得很慢,因為它包含了更多搶占檢查的開銷特別是在一台多處理機上
固定優先級調度可能會導致優先級倒置,優先級倒置——低優先級線程阻塞高優先級線程運行,他是調度和同步之間一個不干凈的相互作用的結果。調用要求一個線程運行,但是同步要求運用另行的線程,所以兩個優先級好像顛倒。如:一個低優先級線程獲互斥資源,並且被一個隨后在同樣資源阻塞的高優先級線程搶占時,優先級發生倒置,在只有兩個線程被允許運行時,低優先級線程被先執行,然后釋放互斥量,如果在他們之間有第三個線程准備好時,他能阻塞低優先級線程運行,因為低優先級線程擁有高優先級線程擁有的互斥量,中間優先級線程阻止了高優先級線程的執行
優先級調度不完全可移植。如:使用系統競爭范圍時,你的線程可以直接與操作系統內核線程相競爭,提高自定義線程的優先級可能會阻止內核I/O驅動在系統上的一些工作
確實需要使用優先級調度時(一般避免使用,因為相比解決問題,他會引起更多的問題),應記住:
- 進程競爭范圍比系統競爭范圍“更好”,因為你不會阻止其他進程或內核中的某個線程運行
- SCHED_RR比SCHED_FIFO“更好”,並且具有可移植性,因為SCHED_RR線程將在具有相同優先級線程共享可用處理器時間間隔中被搶占
- 對SCHED_FIFO和SCHED_RR而言,低優先級比高優先級更好,因為能更少的妨礙另外重要的東西
//1.設置的最高和最低優先級,policy: 可以取三個值(SCHED_FIFO、SCHED_RR、SCHED_OTHER) int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); //2.設置和獲取優先級 //param是struct sched_param類型的指針,它僅僅包含一個成員變sched_priority,指明所要設置的靜態線程優先級。 int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param); param.sched_priority = 51; //設置優先級 struct sched_param { int __sched_priority; // 所要設定的線程優先級 }; //3.改變策略(靜態改變策略和設置優先級) int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_getschedpolicy(pthread_attr_t *attr, int policy); //4.繼承調度屬性,該屬性控制了你創建的線程從創建線程那繼承調度信息,schedpolicy和schedparam顯示設置調度信息 //我手動設置了調度策略或優先級時,必須顯示的設置線程調度策略的inheritsched屬性,因為pthread沒有為inheritsched設置默認值 //所以在改變了調度策略或優先級時必須總是設置該屬性。 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched); /* 第一個函數中inheritsched的取值為:PTHREAD_INHERIT_SCHED 或者 PTHREAD_EXPLICIT_SCHED。 前者為繼承創建線程的調度策略和優先級,后者指定不繼承調度策略和優先級,而是使用自己設置的調度策略和優先級。 無論何時,當你需要控制一個線程的調度策略或優先級時,必須將inheritsched屬性設置為PTHREAD_EXPLICIT_SCHED。 */ //5.置正在運行的線程的調度策略和優先級(動態設置線程的調度策略和優先級) //前面的那些函數只能通過線程的屬性對象 pthread_attr_t 來設置線程的調度策略和優先級,不能夠直接設置正在運行的線程的調度策略和優先級 int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param); int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param); //在成功完成之后返回零。其他任何返回值都表示出現了錯誤。如果出現以下任一情況,pthread_setschedparam() 函數將失敗並返回 //相應的值--EINVAL所設置屬性的值無效。ENOTSUP--嘗試將該屬性設置為不受支持的值。 //int pthread_setschedparam:thread參數所指向的線程不存在 //int pthread_getschedparam:1.參數policy或同參數policy關聯的調度參數之一無效; //2.數policy或調度參數之一的值不被支持; //3.調用線程沒有適當的權限來設置指定線程的調度參數或策略 //4.參數thread指向的線程不存在;5.實現不允許應用程序將參數改動為特定的值
- SCHED_OTHER(是Linux默認的分時調度策略):它是默認的線程分時調度策略,所有的線程的優先級別都是0(不使用sched_param結構體的sched_priority成員),如果系統使用這種調度策略,程序將無法設置線程的優先級。這種調度策略也是搶占式的,當高優先級的線程准備運行的時候,當前線程將被搶占並進入等待隊列。這種調度策略僅僅決定線程在可運行線程隊列中的具有相同優先級的線程的運行次序。(使用此方式的代碼不可移植)
- SCHED_FIFO:它是一種實時的先進先出調用策略,且只能在超級用戶下運行。這種調用策略僅僅被使用於優先級大於0的線程。使用SCHED_FIFO的線程運行到有更高級的線程准備好或者願意自己阻塞為止;當有一個線程准備好時,除非有平等或更高級的線程准備好,否則他將很快運行自己。如果有若干相同優先級的線程等待執行,然而最早執行的線程無終止或者阻塞動作,那么其他線程是無法執行的,除非當前線程調用如pthread_yield之類的函數,所以在使用SCHED_FIFO的時候要小心處理相同級別線程的動作。
- SCHED_RR:若有一個此類的線程運行超過一定的時間沒有阻塞,而另外的SCHED_RR或SCHED_FIFO策略相同優先級的線程准備好時,運行的線程將被槍占意識准備好的線程運行。
- 對於 SCHED_OTHER 策略,sched_priority 只能為 0。對於 SCHED_FIFO,SCHED_RR 策略,sched_priority 從 1 到 99。
- 調度策略和優先級是分開來描述的。前者使用預定義的SCHED_RR、SCHED_FIFO、SCHED_OTHER,后者是通過結果體struct sched_param給出的。
- 這些設置調度策略和優先級的函數操作的對象是線程的屬性pthread_attr_t,而不是直接來操作線程的調度策略和優先級的。函數的第一個參數都是pthread_attr_t。
- 當pthread_setschedparam函數的參數 policy == SCHED_RR 或者 SCHED_FIFO 時,程序必須要在超級用戶下運行
- pthread_setschedparam 函數改變在運行線程的調度策略和優先級肯定就不用調用函數來設置inheritsched屬性了:pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED); 因為該函數設置的對象是pthread_attr_t
- 當在對象屬性中設置調度策略或優先級時,必須同時設置inheritsched屬性
- 改變線程屬性中調度策略和參數時是兩個操作,修改調度策略和修改參數
- 不能獨立於線程的參數來修改一個可執行線程的調度策略,為了調度正確操作,參略和參數一定是一致的,每個調度策略有一個優先級的唯一范圍,並且一個線程不能對一個對當前調度策略而言無效的優先級執行。
競爭范圍和分配域
int pthread_attr_getscope(pthread_attr_t *attr, int *scope); /* 返回值:若是成功返回0,否則返回錯誤的編號 形 參: attr 指向一個線程屬性的指針 scope 返回線程的作用域 */ //指定了線程與誰競爭資源 int pthread_attr_setscope(pthread_attr_t *attr, int scope); /* 返回值:若是成功返回0,否則返回錯誤的編號 attr 指向一個線程屬性的指針 guardsize 線程的作用域,可以取如下值 PTHREAD_SCOPE_SYSTEM 與系統中所有進程中線程競爭 PTHREAD_SCOPE_PROCESS 與當前進程中的其他線程競爭 */
競爭范圍:描述了線程為處理資源而競爭的方式,系統競爭范圍意味着線程與進程之外的線程競爭處理器資源,一個進程內的高優先級系統競爭范圍線程能阻止其他進程內的系統競爭范圍運行。競爭范圍指的是僅僅在同一進程內相互競爭。
分配域:系統內線程可以為其他競爭的處理器的集合。一個系統可以有一個以上的分配域,每個包含一個以上的處理器,在一個單處理器的處理機上,各個分配域可以包含從一個處理器到系統中所有的處理器。(沒有實現該接口)
- 競爭范圍內的線程可以共享一個核實體
- 系統競爭范圍線程之間的環境切換通常要求至少一次內核調用
- 競爭范圍在優先級調度上沒有給你真正的控制——高優先級的線程可以優先於進程內的其他線程運行
- 當一個線程被分配超過一個處理機的分配域時,應用程序不能完全依靠可預知的調度行為;如:高優先級和低優先級可以同時運行,調度程序不允許因為一個高優先級的線程正在運行而是處理及閑置,單處理機行為在一台多處理機上沒什么意思。
核實體
線程:調用pthread_create創建的一個線程,類行為pthread_t的一個標識符代表,使用pthreads接口可控制
處理機:物理硬件
核實體:線程和處理機間的一層附加抽象,可能是一個傳統的UNIX進程。
線程與核實體的交互方式:多對一(用戶級),一對一(內核級),多對少