實時調度:操作系統在有限的時間內提供特定水平的服務能力。受限制的響應時間不一定是塊的反應,意味著可預知的響應速度。如果系統定義_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 與當前進程中的其他線程競爭 */ 競爭范圍:描述了線程為處理資源而競爭的方式,系統競爭范圍意味著線程與進程之外的線程競爭處理器資源,一個進程內的高優先級系統競爭范圍線程能阻止其他進程內的系統競爭范圍運行。競爭范圍指的是僅僅在同一進程內相互競爭。
分配域:系統內線程可以為其他競爭的處理器的集合。一個系統可以有一個以上的分配域,每個包含一個以上的處理器,在一個單處理器的處理機上,各個分配域可以包含從一個處理器到系統中所有的處理器。(沒有實現該接口)
競爭范圍內的線程可以共享一個核實體 系統競爭范圍線程之間的環境切換通常要求至少一次內核調用 競爭范圍在優先級調度上沒有給你真正的控制——高優先級的線程可以優先于進程內的其他線程運行 當一個線程被分配超過一個處理機的分配域時,應用程序不能完全依靠可預知的調度行為;如:高優先級和低優先級可以同時運行,調度程序不允許因為一個高優先級的線程正在運行而是處理及閑置,單處理機行為在一臺多處理機上沒什么意思。 ?相關優先級互斥量 不僅避免實時調度可以避免優先級倒置,而且用互斥量加鎖協議也可以避免優先級倒置
#if defined (_POSIX_THREAD_PRIO_PROSTECT) \||
defined (_POSIX_THREAD_PRIO_INHERIT)
int pthread_mutexattr_getprotocol(
const pthread_mutexattr_t *attr,
int *
protocol);
int pthread_mutexattr_setprotocol(
const pthread_mutexattr_t *attr,
int protocol);
#endif #if defined _POSIX_THREAD_PRIO_PROTECT
int pthread_mutexattr_getprioceiling(
const pthread_attr_t *attr,
int *
prioceiling);
int pthread_mutexattr_setprioceiling(
const pthread_attr_t *attr,
int prioceiling); int pthread_mutex_getprioceiling(
const pthread_attr_t *attr,
int *
prioceiling);
int pthread_mutex_getprioceiling(
const pthread_attr_t *attr,
int prioceiling);
#endif 加鎖或等待這些屬性之一的某個互斥量可以改變線程的優先級——或另外優先級的到來,來保證互斥量的線程不能被需要鎖住相同互斥量的其他線程搶占。 _POSIX_THREAD_PRIO_PROSTECT和_POSIX_THREAD_PRIO_INHERIT這些宏定義在<unistd.h>中,對應用進行條件編譯,活用sysconf來檢查。 一旦創建了使用這些屬性之一的互斥量,就能對任何其他互斥量一樣來枷鎖和解鎖互斥量,使用pthread_mutex_init就能變換創建的互斥量 如果定義_POSIX_THREAD_PRIO_PROSTECT,則它支持“優先級ceiling協議”和prioceiling屬性,通過調用pthread_mutexattr_setprotocol設置協議屬性,如果將協議屬性設置為_POSIX_THREAD_PRIO_PROSTECT,則可以通過設置prioceiling屬性使用屬性對象創建互斥量優先級設置ceiling。 調用pthread_mutexattr_setprioceiling設置prioceiling屬性,當任何線程鎖住與該屬性對象相關定義的一個互斥量時,線程的優先級將被設置為互斥量的優先級ceiling,除非線程的優先級已經是相同或更高,在高于互斥量優先級ceiling的線程內加鎖該互斥量會被打破協議,失去對優先級倒置的保護 優先級繼承:當一個線程再由另個低優先級線程擁有的互斥量上等待時,后者優先級將被增加到等待線程的優先級。 如果定義_POSIX_THREAD_PRIO_INHERIT他就支持協議屬性,如果將屬性設置為_POSIX_THREAD_PRIO_INHERIT,那么保持互斥量的線程就不能被另外的與等待互斥量的線程相比優先級低的任何線程搶占,當任何線程加鎖互斥量,同時一個低優先級的線程擁有互斥量時,只要它擁有互斥量,當前擁有互斥量的線程的優先級將被提高到等待線程的優先級 優先級ceiling互斥量 當使用優先級ceiling創建一個互斥量時,指定的線程鎖住互斥量時可以擁有最高的優先級,任何鎖住互斥量的線程將自動將它的優先級值提高到那個值,這允許在他被任何另外試圖加鎖該互斥量的線程搶占以前,完成對互斥量的操作。
一個優先級ceiling互斥量在一個庫函數中無法使用。
如果有任何比ceiling高的優先級運行的線程鎖住優先級ceiling互斥量,協議將被破壞。
優先級繼承互斥量 當一個線程鎖住互斥量時,線程的優先級就被互斥量控制,當另外的線程在那個互斥量上阻塞時,他會查看擁有互斥量的線程優先級,如果擁有互斥量的線程比試圖在互斥量上阻塞的線程優先級低,則擁有互斥量的線程的優先級將被提升到阻塞線程的優先級。
除非等待的線程也被搶占,提高優先級確保擁有互斥量的線程不能被搶占;擁有互斥量的線程代表的是高優先級工作的線程,當線程互斥量解鎖時,線程的優先級被自動降到他原來的優先級,高優先級等待線程將被喚醒,如果又有一個高優先級線程在互斥量上阻塞,擁有互斥量的線程將再次增加優先級。
核實體 線程:調用pthread_create創建的一個線程,類行為pthread_t的一個標識符代表,使用pthreads接口可控制
處理機:物理硬件
核實體:線程和處理機間的一層附加抽象,可能是一個傳統的UNIX進程。
線程與核實體的交互方式:多對一(用戶級),一對一(內核級),多對少
轉載于:https://www.cnblogs.com/tianzeng/p/9192706.html
總結
以上是生活随笔 為你收集整理的pthread调度策略,优先级和竞争范围 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。