?? 2.html
字號:
intpthread_attr_getschedparam ( pthread_attr_t *attr, struct sched_param *param)<br> param->priority = attr->priority;<p>2.3.11設置線程調度策略<br>說明:在某些方面,線程的調度策略的確很像線程的屬性,但它卻是可以在調度中被更改的,系統可以調用此函數完成對線程調度策略的重定義。這樣的規定,使得線程調度靈活了許多,當然這種靈活是用增加系統開銷的代價換回來的,但卻是值得的。<br>intpthread_attr_setschedpolicy ( pthread_attr_t *attr, int policy )<br> switch(policy) {<br> case SCHED_FIFO: /* 先到先處理 */<br> caseSCHED_RR: /* 時間片輪轉 */<br> case SCHED_EDF /* 先死先處理 */<br> caseSCHED_RMS: /* 效率優先 */<br> attr->policy = policy;<br>break;<br> case SCHED_DECAY:<br> printf("pthread_attr_setschedpolicy:"<br> "SCHED_DECAY not supported yet\n");<br> }<p>2.3.12得到線程調度策略<br>說明:負責調度的線程通過該函數得到被調度線程的調度策略,然后再根據此時系統內的情況,決定是否改變其調度算法。<br>intpthread_attr_getschedpolicy ( const pthread_attr_t *attr, int *policy)<br> *policy = attr->policy;<p>2.3.13設置堆棧地址<br>說明:調用此函數,可以實現對線程屬性堆棧的底層操作,即設置指向該堆棧的指針,并保存起來,為以后的操作奠定基礎。<br>intpthread_attr_setstackaddr ( pthread_attr_t *attr, oskit_u32_t stackaddr)<br> attr->stackaddr = stackaddr;<p>2.3.14 得到堆棧的地址<br>說明:返回指向線程屬性堆棧的指針。<br>intpthread_attr_getstackaddr(const pthread_attr_t *attr, oskit_u32_t*stackaddr)<br> *stackaddr = attr->stackaddr;<p>2.3.15設置堆棧的大小<br>說明:由于系統中的線程功能、大小各不相同,所以其屬性堆棧的大小也不盡相同,調用此函數可以設置線程屬性堆棧大小。<br>intpthread_attr_setstacksize ( pthread_attr_t *attr, size_t stacksize)<br> attr->stacksize = stacksize;<p>2.3.16 得到堆棧的大小<br>說明:返回某個線程堆棧的大小。<br>int pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize )<br> *stacksize =attr->stacksize;<p>2.3.17設置線程的優先級<br>說明:在操作系統的線程調度中,優先級調度的使用最為廣泛,OSKit定義了下面的函數來規定線程的優先級。<br>intoskit_pthread_attr_setprio ( pthread_attr_t *attr, int pri)<br> attr->priority = pri;<p>2.3.18準備接受調度<br>說明:由于多態性原因,不是所有的線程都要參與調度,只是某些線程參加,所以,系統必須調用此函數,告訴該線程準備參加調度,而被調度的方式在上邊的幾個函數里已經規定好了。<br>intpthread_attr_setopaque ( pthread_attr_t *attr, oskit_u32_t opaque)<br> attr->opaque = opaque;<p>2.3.19 聲明要進行調度的線程<br>說明:調用此函數是為了告訴系統,哪些線程是要被調度的。<br>intpthread_attr_setscheduler ( pthread_attr_t *attr, pthread_t tid)<br> attr->scheduler = tid;<p>2.3.20設置mutex的屬性<br>說明:在OSKit中,廣泛使用了mutex,主要是為了更好的使用臨界資源,有效地避免了死鎖,換句話說,mutex就像臨界資源的數量一樣,線程對其進行PV操作。而當一個線程占有了一個mutex,并且在沒釋放它之前該線程又創建了子線程,此時,子線程理所當然地從父線程手中繼承了mutex的所有權,OSKit定義了下面的函數來實現所敘述的功能。<br>intpthread_mutexattr_init ( pthread_mutexattr_t *attr)<br> attr->priority_inherit = PTHREAD_PRIO_NONE; /* THREAD_PRIO_NONE=0 */<p>2.3.21撤銷mutex的屬性<br>說明:當占有mutex的線程放棄了它的時候,調用該函數來撤銷mutex的屬性。<br>intpthread_mutexattr_destroy ( pthread_mutexattr_t *attr )<br> memset((void *)attr, -1, sizeof(*attr));<p>2.3.22設置muxtex的協議<br>說明:mutex的使用并不是簡單的占用與撤銷,OSKit還提供了更加完善的mutex協議,它根據inherit的不同,將mutex多樣化。<br>intthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr, int inherit)<br> switch (inherit) {<br> case PTHREAD_PRIO_NONE:<br> casePTHREAD_PRIO_INHERIT:<br> attr->priority_inherit =inherit;<br> break;<br> default:<br> returnEINVAL;<br> }<br>注:在線程調度時,根據mutex協議產生mutex變量,將線程按照優先級排隊<p>2.3.23 得到線程調度的mutex協議<br>說明:好像對協議的解析一樣,調用此函數,可以返回該線程的mutex。<br>intpthread_mutexattr_getprotocol ( const pthread_mutexattr_t *attr, int*inherit)<br> *inherit = attr->priority_inherit;<p>2.3.24設置mutex的種類<br>說明:mutex在OSKit中是可以多種多樣的,通過調用下面的函數,可以規定線程到底占用了哪種mutex。<br>intpthread_mutexattr_settype ( pthread_mutexattr_t *attr, int type )<br> switch(type) {<br> case PTHREAD_MUTEX_NORMAL: /* 普通 */<br> casePTHREAD_MUTEX_ERRORCHECK: /* 錯誤檢查 */<br> case PTHREAD_MUTEX_RECURSIVE: /* 遞歸*/<br> case PTHREAD_MUTEX_DEFAULT: /* 默認 */<br> attr->type =type;<br> break;<br> default:<br> return EINVAL;<br> }<p>2.3.25得到mutex的類型<br>說明:當系統想要知道某個線程占用的是什么類型的mutex時,調用此函數來返回mutex的類型。<br>intpthread_mutexattr_gettype ( const pthread_mutexattr_t *attr, int *type)<br> *type = attr->type;<p><br>本 章 小 結<p>本章從線程的創建、存儲和數據結構到各種屬性以及對它們的操作(設置、撤銷和得到)入手,系統地闡述了OSKit線程機制的根源--線程初始化。<p>在第一節主要從三個角度歸納了OSKit中線程所涉及的概念,它們是創建、存儲以及線程的數據結構。第二節中以源代碼中的/pthreads/pthread_creat.c 為例,說明了第一節中概念的具體實現。第三節以源代碼中的 /pthreads/pthread_attr.c為例,說明了Oskit對線程屬性的全部操作,包括線程初始化的數據結構、屬性的撤銷、線程間關系、對mutex的操作以及對屬性堆棧的操作等。<p><p><center><A HREF="#Content">[目錄]</A></center><hr><br><A NAME="I560" ID="I560"></A><center><b><font size=+2>第三章 線程通信分析</font></b></center><br>《OSKit的線程機制 第三章》<p><p><br>OSKit的線程機制 第三章2000年12月25日22:11<p><br>作 者: 湯海京<p><br>導師:陳朔鷹<p><br>第三章 線程通信分析<p><br>眾所周知,在Linux中,進程為了能在同一項任務上協調工作,彼此之間必須能夠進行通信。例如,在一個shell管道中,第一個進程的輸出必須傳輸到第二個進程,這樣沿著管道傳遞下去。因此在需要通信的進程之間,應該使用一種結構較好的通信方式。<p>Linux支持許多不同形式的進程間通信機制,在特定的情況下,它們各有自己的優缺點,如利用管道進行通信的最大缺點就是,只有成為系統調用pipe的進程的子孫后代的進程才可以使用管道,因此,相互無關的進程不能通過管道通信。<p>OSKit的開發人員們充分考慮了各種通信方式的利弊,揚長避短,采用了如下的兩種線程間通信方式:消息隊列和信號量。雖然這還有很多不足之處,但較之SystemV以有所改進。<p><br>3.1 線程間通信<p>3.1.1消息隊列<p>OSKit提供的消息隊列機制于UNIX十分相似,一個和多個線程可向消息隊列寫入消息,而一個或多個線程可從消息隊列中讀取消息,這種線程間通信的機制就像客戶機/服務器一樣,客戶機向服務器發送請求消息,服務器讀取消息并執行相應的請求。<p>OSKit將消息描述成在內核地址空間的一個內部鏈表,每一個消息隊列由一個IPC標識號唯一的標識。<p>3.1.2信號<p>盡管大多數線程間通信是計劃好的,但是同時還需要處理不可預知的通信問題。例如,用戶使用文本編輯器要求列出一個大文件的全部內容,但隨即他認識到該操作并不重要,這是就需要一種方法來中止編輯器的工作,比如說,我們可以按DEL鍵來實現。按DEL鍵實際上是向編輯器發送一個信號,編輯器收到此信號便立即停止打印文件的內容。信號還可以用來報告硬件捕獲到的特定的中斷,如非法指令和浮點運算溢出、超時也通過信號實現的。<p>在OSKit中,信號是一種重要的線程間通信機制,線程通過信號知道系統中正在出現的事件。信號的一個特點就是它的異步性,這表示線程在它的執行期間的任何時候都可以接受到信號,甚至可能當線程正在執行系統調用的時候接到信號,因此,線程必須隨時為相應信號作好準備。<p>下面我們再談談信號的生成與交付,當引起信號的事件首次出現時,就認為信號為線程而生成,也就是說信號被發送到線程。這類事件的例子,包括:時間片到時,終端激活,硬件故障的檢測,kill()的調用。在某些情況下,一個事件為多個可以為多個線程生成信號。每個線程采用樣應的動作來響應系統定義的每種信號(見信號量表3.1)。<p>在信號的生成與交付之間,該信號被掛起,但在用戶一級是檢測不到這個間隔的。每個線程都擁有一個信號掩碼(sig_mask),它規定了當前被阻塞而不能交付給線程的信號集。線程的信號掩碼是從父線程繼承而來的。我前面提到sigaction(),sigprocmask( )和sigsuspend( )函數,都是對信號掩碼的操作。<p>信號的動作與信號有關的動作分為三種:SIG_DFL,SIG_IGN或指向函數的指針。在最開始,進入main()之前,所有信號都將被置成SIG_DFL或SIG_IGN。<p>(1)SIG_DFL信號專用的默認動作:<br> (a)如果默認動作是暫停線程,則該線程的執行被暫時掛起。當線程暫停期間,發送給線程的任何附加信號都不交付,直到該線程開始執行,但是SIGKILL除外。<br> (b)把掛起信號的信號動作設置成SIG_DFL,且其默認動作是忽略信號(SIGCHLD)。<p>(2)SIG_IGN忽略信號<br> (a)該信號的交付對線程沒有影響<br> (b)系統不允許把SIGKILL或SIGTOP信號的動作設置為SIG_DFL<p>(3)指向函數的指針--捕獲信號<br> (a)信號一經交付,接收線程就在指定地址上執行信號捕獲程序。在信號捕獲函數返回后,接受線程必須在被中斷點恢復執行。<br> (b)用C語言函數調用的方法進入信號捕捉程序:<br> void func(signo)<br> int signo;<br> func()是指定的信號捕捉函數,signo是正被交付信號的編碼<br> (c)如果SIGFPE,SIGILL或SIGSEGV信號不是由C標準定義的kill()或raise()函數所生成,則從信號SIGFPE,SIGILL,SIGSEGV的信號捕獲函數正常返回后線程的行為是未定義的。<br> (d)系統不允許線程捕獲SIGKILL和SIGSTOP信號。<br> (e)如果線程為SIGCHLD信號建立信號捕獲函數,而該線程有未被等待的以終止的子線程時,沒有規定是否要生成SIGCHLD信號來指明那個子線程。<p>每一種信號都被OSKit給予了一個符號名,對于32位的i386平臺而言,一個字32位,因而信號有32種。下面的表給出了常用的符號名、描述和它們的信號值。<p>符號名 信號值描述 是否符合POSIX<br>SIGHUP 1 在控制終端上檢測到掛斷或控制線程死亡 是<br>SIGINT 2 交互注意信號 是<br>SIGQUIT3 交互中止信號 是<br>SIGILL 4 檢測到非法硬件的指令 是<br>SIGTRAP5 從陷阱中回朔 否<br>SIGABRT6 異常終止信號 是<br>SIGEMT 7 EMT指令 否<br>SIGFPE 8 不正確的算術操作信號 是<br>SIGKILL9 終止信號 是<br>SIGBUS 10 總線錯誤 否<br>SIGSEGV 11檢測到非法的內存調用 是<br>SIGSYS 12 系統call的錯誤參數 否<br>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -