天天看點

Linux實時性測試

對于Linux實時性測試,目前我們用了以下方法:

1.寫了測試程式,用于測試線程排程時間,主程序和線程的priority都設定為最高,截取如下代碼:

 struct sched_param sp;

        memset(&sp,0,sizeof(struct sched_param));

        sp.sched_priority = 99;

        sched_setscheduler(getpid(),SCHED_RR,&sp);

        int policy;

        pthread_attr_getschedpolicy(&ThreadAttr , &policy);

        printf("1:SCHED_FIFO = %d, SCHED_OTHER = %d, SCHED_RR = %d,policy = %d\n",SCHED_FIFO,SCHED_OTHER,SCHED_RR,policy);

        pthread_attr_setschedpolicy(&ThreadAttr , SCHED_RR);

        pthread_attr_getschedpolicy(&ThreadAttr , &policy);

        printf("2:SCHED_FIFO = %d, SCHED_OTHER = %d, SCHED_RR = %d,policy = %d\n",SCHED_FIFO,SCHED_OTHER,SCHED_RR,policy);

其中,說明兩點,第一,sched_setscheduler()函數将pid所指定程序的排程政策和排程參數分别設定為param指向的sched_param結構中指定的policy和參數。sched_param結構中的sched_priority成員的值可以為任何整數,該整數位于policy所指定排程政策的優先級範圍内(含邊界值)。policy參數的可能值在頭檔案中定義。

      如果存在pid所描述的程序,将會為程序ID等于pid的程序設定排程政策和排程參數。

      如果pid為零,将會為調用程序設定排程政策和排程參數。

      如果程序pid含多個程序或輕量程序(即該程序是多程序的),此函數将影響程序中各個子程序。

      更改其他程序的排程參數需要有相應的特權。調用程序必須具有相應的特權,或者是具有PRIV_RTSCHED權限的組的成員,猜能成功調用sched_setscheduler()。如果sched_setscheduler()函數成功地将pid所指定排程政策和排程參數分别設定為policy和結構param指定值 ,則該函數調用成功。

第二,需要了解程序排程,設定為  SCHED_RR,如果設定為SCHED_FIFO,線程就會一直被執行:

      程序排程指的是系統對程序的多種狀态之間轉換的政策。Linux下的程序排程有3種政策:SCHED_OTHER、SCHED_FIFO和SCHED_RP。

      SCHED_OTHER是用于針對普通程序的時間片輪轉排程政策。這種政策中,系統給所有的運作狀态的程序配置設定時間片。在目前時間片用完之後,系統從程序中優等級最高的程序中選擇程序運作。

      SCHED_FIFO是針對運作的實時性要求比較高、運作時間短的程序排程政策。這種政策中,系統按進入隊列的先後進行程序的排程,在沒有更高優先級程序到來或者目前程序沒有因為等待資源而阻塞的情況下,會一直運作。

      SCHED_RR是針對運作的實時性要求比較高、運作經較長的程序排程政策。這種政策與SCHED_OTHER的政策類似,隻不過SCHED_RR程序的優先級要高得多。 系統配置設定給SCHED_RR的程序時間片,然後輪循運作這些程序,将時間片用完的程序放入隊列的末尾。

       Linux程序排程月票用的是“有條件可剝奪”的排程方式。普通程序中采用的是SCHED_OTHER的時間片輪循方式,實時程序可以剝奪普通程序。如果普通程序在使用者空間運作,則普通程序立即停止運作,将資源讓給實時程序vkjsuo通程序運作在核心空間,需要等系統調用傳回使用者空間後方可剝奪資源。

2.主程序調用 拉高序列槽的CTS信号,節選如下代碼

  while(1)

        {

                ioctl(portHandle, TIOCMGET, &Value);

                Value |= TIOCM_RTS;

                usleep(5000);

                ioctl(portHandle, TIOCMSET, &Value);

        }

線程處理函數中,拉低CTS信号,節選如下代碼:

void *MCRThread(void *Param)

{

        int SerialHandle = (int)Param;

        unsigned long int  ModemStatus;

        while(1)

        {

                ioctl(SerialHandle, TIOCMIWAIT, TIOCM_CTS);

                ModemStatus &= ~TIOCM_RTS;

                ioctl(SerialHandle, TIOCMSET, &ModemStatus);

        }

        pthread_exit(NULL);

        return 0;

}

3.ioctl(SerialHandle, TIOCMIWAIT, TIOCM_CTS);其中,TIOCMIWAIT:等待 MSR 改變. 使用者在非尋常的情況下請求這個 ioctl, 它想在核心中睡眠直到這個 tty 裝置的 MSR 寄存器發生某些事情. arg 參數包含使用者在等待的事件類型. 這通常用來等待直到一個狀态線變化, 訓示有更多的資料發送給裝置.參考連結如下:http://oss.org.cn/kernel-book/ldd3/ch18s04.html

4.建立一個線程預設的狀态是joinable, 如果一個線程結束運作但沒有被join,則它的狀态類似于程序中的Zombie Process,即還有一部分資源沒有被回收(退出狀态碼),是以建立線程者應該調用pthread_join來等待線程運作結束,并可得到線程的退出代碼,回收其資源(類似于wait,waitpid)

但是調用 pthread_join(pthread_id)後,如果該 線程沒有運作結束,調用者會被阻塞,在有些情況下我們并不希望如此,比如在Web伺服器中當 主線程為每個新來的連結建立一個子線程進行處理的時候,主線程并不希望因為調用pthread_join而阻塞(因為還要繼續處理之後到來的連結),這時可以在子線程中加入代碼 pthread_detach( pthread_self()) 或者父線程調用 pthread_detach(thread_id)(非阻塞,可立即傳回) 這将該子線程的狀态設定為detached,則該線程運作結束後會自動釋放所有資源

5.測試方法:裝置上的序列槽的RTS(pin7)與CTS(pin8)連接配接接起來,啟動測試程式,使用示波器測試RTS,CTS信号,示波器出現10ms的脈沖信号,脈沖寬度就是interupt Latency。

6.可以寫程式和腳本開啟多個程序,來測試壓力情況下的線程排程時間。

繼續閱讀