『壹』 linux系統進程調度
主要參考 :Linux manual page - sched
自從linux內核2.6.23以來,默認的進高嘩扮程調度器就被設置為完全公平調度器(CFS,complete fair scheler),取代了之前的O(1)調度器。
每個線程都有一個靜態調度優先順序,即 sched_priority 欄位。
一個線程的調度策略決定了線程會被插入到同級靜態優先順序的線程隊列的位置,以及它在隊列中會怎樣移動。
所有的調度都是可插入的,如果一個更高靜態優先順序的線程准備好了,現在運行中的線程就會被插入。而調度策略則僅僅影響了同樣靜態優先順序的線程。
進程(線程)可以通過系蘆橋統調用設置自身或者其他進程(線程)的調度策略。
其中 pid 為0時,設置自身的調度策略和參數。結構體 sched_attr 包含以下戚灶欄位: size 、 sched_policy (即調度策略,具體會在下一節介紹)、 sched_flags 、 sched_nice 、 sched_runtime 、 sched_deadline 、 sched_period (最後三個為 SCHED_DEADLINE 相關的參數)。當設置成功,系統調用返回0;否則返回-1,並會設置 errno 。
普通進程: SCHED_OTHER / SCHED_BATCH / SCHED_IDLE
實時進程: SCHED_FIFO / SCHED_RR
特殊實時進程: SCHED_DEADLINE
靜態優先順序:Static_priority:對於普通進程,靜態優先順序為0;對於實時進程,靜態優先順序為1-99,99為最高優先順序。
動態優先順序:Dynamic_priority:僅對普通進程有用,取決於nice和一個動態調整的量(比如進程ready卻沒被調度,則增加)。
『貳』 linux c如何調整線程優先順序
你好。
在分時系隱數統里應該沒什必要吧
setpriority/getpriority,這兩個函數描述的是改變進程優先順序。
但是在linux中線程就是一個輕量級的山辯進程,
所以這兩個函數是可以作用於單獨的線程的
如果我的回答沒能幫助您,請繼續逗攜缺追問。
『叄』 linux查看線程優先順序命令
用top或者ps -l查看進程會發現有PR(PRI) NI兩個欄位:
NI 是優先值,是用戶層面的概念, PR是進程的實際優先順序, 是給內核(kernel)看(用)的。
一般情況下,PR=NI+20, 如果一個進程的優先順序PR是20, 那麼它的NI(nice)值就是20-20=0。
進程調度優先順序是從-20到19,一共40個級別,數字越大,表示進程的優先順序越低。默認時候,進程的優先順序是0。查看進程優先順序有兩個辦法:ps和top。top命令顯示的NI列的值。或者可以使用ps -efl來查看,也是在ni列表示了進程的優先順序。《Linux就該這么學》 一起學習,進程的優先順序可以在程序運行的時候設置,也可以在程序運行過程中動態的修改。
『肆』 在Linux下怎麼修改當前線程的優先順序
pthread_create()中的attr參數的__schedpolicy成員,表示新線程的調度策略,主要包括SCHED_OTHER(正常、非實時)、SCHED_RR(實時、輪轉法)和SCHED_FIFO(實時、先入先出)三種,預設為SCHED_OTHER,後兩種調度策略僅對超級用戶有效。運行時可以用過pthread_setschedparam()來改變。
__schedparam成員是一個struct sched_param結構,目前僅有一個sched_priority整型變數表示線程的運行優先順序。這個參數僅當調度策略為實時(即SCHED_RR或SCHED_FIFO)時才有效,並可以在運行時通過pthread_setschedparam()函數來改變,預設為0
『伍』 linux進程、線程及調度演算法(三)
調度策略值得是大家都在ready時,並且CPU已經被調度時,決定誰來運行,誰來被調度。
兩者之間有一定矛盾。
響應的優化,意味著高優先順序會搶占優先順序,會花時間在上下文切換,會影響吞吐。
上下文切換的時間是很短的,幾微妙就能搞定。上下文切換本身對吞吐並多大影響, 重要的是,切換後引起的cpu 的 cache miss.
每次切換APP, 數據都要重新load一次。
Linux 會盡可能的在響應與吞吐之間尋找平衡。比如在編譯linux的時候,會讓你選擇 kernal features -> Preemption model.
搶占模型會影響linux的調度演算法。
所以 ARM 的架構都是big+LITTLE, 一個很猛CPU+ 多個 性能較差的 CPU, 那麼可以把I/O型任務的調度 放在 LITTLE CPU上。需要計算的放在big上。
早期2.6 內核將優先順序劃分了 0-139 bit的優先順序。數值越低,優先順序越高。0-99優先順序 都是 RT(即時響應)的 ,100-139都是非RT的,即normal。
調度的時候 看哪個bitmap 中的 優先順序上有任務ready。可能多個任務哦。
在普通優先順序線程調度中,高優先順序並不代表對低優先順序的絕對優勢。會在不同優先順序進行輪轉。
100 就是比101高,101也會比102高,但100 不會堵著101。
眾屌絲進程在輪轉時,優先順序高的:
初始設置nice值為0,linux 會探測 你是喜歡睡眠,還是幹活。越喜歡睡,linux 越獎勵你,優先順序上升(nice值減少)。越喜歡幹活,優先順序下降(nice值增加)。所以一個進程在linux中,干著干著 優先順序越低,睡著睡著 優先順序越高。
後期linux補丁中
紅黑樹,數據結構, 左邊節點小於右邊節點
同時兼顧了 CPU/IO 和 nice。
數值代表著 進程運行到目前為止的virtual runtime 時間。
(pyhsical runtime) / weight * 1024(系數)。
優先調度 節點值(vruntime)最小的線程。權重weight 其實有nice 來控制。
一個線程一旦被調度到,則物理運行時間增加,vruntime增加,往左邊走。
weight的增加,也導致vruntime減小,往右邊走。
總之 CFS讓線程 從左滾到右,從右滾到左。即照顧了I/O(喜歡睡,分子小) 也 照顧了 nice值低(分母高).所以 由喜歡睡,nice值又低的線程,最容易被調度到。
自動調整,無需向nice一樣做出獎勵懲罰動作,個人理解權重其實相當於nice
但是 此時 來一個 0-99的線程,進行RT調度,都可以瞬間秒殺你!因為人家不是普通的,是RT的!
一個多線程的進程中,每個線程的調度的策略 如 fifo rr normal, 都可以不同。每一個的優先順序都可以不一樣。
實驗舉例, 創建2個線程,同時開2個:
運行2次,創建兩個進程
sudo renice -n -5(nice -5級別) -g(global), 會明顯看到 一個進程的CPU佔用率是另一個的 3倍。
為什麼cpu都已經達到200%,為什麼系統不覺得卡呢?因為,我們的線程在未設置優先順序時,是normal調度模式,且是 CPU消耗型 調度級別其實不高。
利用chrt工具,可以將進程 調整為 50 從normal的調度策略 升為RT (fifo)級別的調度策略,會出現:
chrt , nice renice 的調度策略 都是以線程為單位的,以上 設置的將進程下的所有線程進行設置nice值
線程是調度單位,進程不是,進程是資源封裝單位!
兩個同樣死循環的normal優先順序線程,其中一個nice值降低,該線程的CPU 利用率就會比另一個CPU的利用率高。
『陸』 C++在linux下怎麼多線程
#ifndefTHREAD_H_
#defineTHREAD_H_
#include<unistd.h>
#include<pthread.h>
classRunnable
{
public:
//運行實體
virtualvoidrun()=0;
};
//線程類
classThread:publicRunnable
{
private:
//線程初始化號
staticintthread_init_number;
//當前線程初始化序號
intcurrent_thread_init_number;
//線程體
Runnable*target;
//當前線程的線程ID
pthread_ttid;
//線程的狀態
intthread_status;
//線程屬性
pthread_attr_tattr;
//線程優先順序
sched_paramparam;
//獲取執行方法的指針
staticvoid*run0(void*pVoid);
//內部執行方法
void*run1();
//獲取線程序號
staticintget_next_thread_num();
public:
//線程的狀態-新建
staticconstintTHREAD_STATUS_NEW=0;
//線程的狀態-正在運行
staticconstintTHREAD_STATUS_RUNNING=1;
//線程的狀態-運行結束
staticconstintTHREAD_STATUS_EXIT=-1;
//構造函數
Thread();
//構造函數
Thread(Runnable*target);
//析構
~Thread();
//線程的運行體
voidrun();
//開始執行線程
boolstart();
//獲取線程狀態
intget_state();
//等待線程直至退出
voidjoin();
//等待線程退出或者超時
voidjoin(unsignedlongmillis_time);
//比較兩個線程時候相同,通過current_thread_init_number判斷
booloperator==(constThread*other_pthread);
//獲取this線程ID
pthread_tget_thread_id();
//獲取當前線程ID
staticpthread_tget_current_thread_id();
//當前線程是否和某個線程相等,通過tid判斷
staticboolis_equals(Thread*iTarget);
//設置線程的類型:綁定/非綁定
voidset_thread_scope(boolisSystem);
//獲取線程的類型:綁定/非綁定
boolget_thread_scope();
//設置線程的優先順序,1-99,其中99為實時,意外的為普通
voidset_thread_priority(intpriority);
//獲取線程的優先順序
intget_thread_priority();
};
intThread::thread_init_number=1;
inlineintThread::get_next_thread_num()
{
returnthread_init_number++;
}
void*Thread::run0(void*pVoid)
{
Thread*p=(Thread*)pVoid;
p->run1();
returnp;
}
void*Thread::run1()
{
thread_status=THREAD_STATUS_RUNNING;
tid=pthread_self();
run();
thread_status=THREAD_STATUS_EXIT;
tid=0;
pthread_exit(NULL);
}
voidThread::run()
{
if(target!=NULL)
{
(*target).run();
}
}
Thread::Thread()
{
tid=0;
thread_status=THREAD_STATUS_NEW;
current_thread_init_number=get_next_thread_num();
pthread_attr_init(&attr);
}
Thread::Thread(Runnable*iTarget)
{
target=iTarget;
tid=0;
thread_status=THREAD_STATUS_NEW;
current_thread_init_number=get_next_thread_num();
pthread_attr_init(&attr);
}
Thread::~Thread()
{
pthread_attr_destroy(&attr);
}
boolThread::start()
{
returnpthread_create(&tid,&attr,run0,this);
}
inlinepthread_tThread::get_current_thread_id()
{
returnpthread_self();
}
inlinepthread_tThread::get_thread_id()
{
returntid;
}
inlineintThread::get_state()
{
returnthread_status;
}
voidThread::join()
{
if(tid>0)
{
pthread_join(tid,NULL);
}
}
voidThread::join(unsignedlongmillis_time)
{
if(tid==0)
{
return;
}
if(millis_time==0)
{
join();
}
else
{
unsignedlongk=0;
while(thread_status!=THREAD_STATUS_EXIT&&k<=millis_time)
{
usleep(100);
k++;
}
}
}
boolThread::operator==(constThread*other_pthread)
{
if(other_pthread==NULL)
{
returnfalse;
}if(current_thread_init_number==(*other_pthread).current_thread_init_number)
{
returntrue;
}
returnfalse;
}
boolThread::is_equals(Thread*iTarget)
{
if(iTarget==NULL)
{
returnfalse;
}
returnpthread_self()==iTarget->tid;
}
voidThread::set_thread_scope(boolisSystem)
{
if(isSystem)
{
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);
}
else
{
pthread_attr_setscope(&attr,PTHREAD_SCOPE_PROCESS);
}
}
voidThread::set_thread_priority(intpriority)
{
pthread_attr_getschedparam(&attr,¶m);
param.__sched_priority=priority;
pthread_attr_setschedparam(&attr,¶m);
}
intThread::get_thread_priority(){
pthread_attr_getschedparam(&attr,¶m);
returnparam.__sched_priority;
}
#endif/*THREAD_H_*/
『柒』 是指實時線程,Linux分配1-99為實時線程,是1為最高優先順序還是99為最高
1是實時進程優先順序最高的,99是實時進程優先順序最低的,數字越小,優先順序越高
你在做operating system的實驗?
『捌』 嵌入式與Linux(五):Linux線程
姓名:王央京 學號:18050100052 學院:電子工程學院
轉自:https://blog.csdn.net/qq_22847457/article/details/89371217
【嵌牛導讀】本文介紹了Linux線程的相關信息
【嵌牛鼻子】Linux線程
【嵌牛提問】在了解Linux系統後,能否具體介紹線程的概念?
【嵌牛正文】
類Unix系統中,早期是沒有「線程」概念的,80年代才引答握態入,藉助進程機制實現出了線程的概念。因此在這類系統中,進程和線程關系密切。一個進程可以有多個線程,這個進程本身也叫做線程只不過是主線程。通常主線程分配任務給子線程做。程序設計時候就可以某一時刻不止做一件事情,每一個線程處理各自獨立的任務。
多個線程可以訪問相同的存儲地址空間和文件描述符。同一進程內的線程共享以下數據:全局內存、進程指令、打開的文件、信號處理函數和信號處置、當前工作目錄、用戶ID和用戶組ID、大多數數據。每個線程有各自的線程ID、寄存器集合(包括程序計數器和棧指針)、棧、errono、信號掩碼、優先順序。
線程的優點有提高程序並發性、開銷小和數據通信、共享數據方便等。線程的缺點有庫函數不穩定、調試編寫困難、gdb不支持、對信號支持不好等。除此之外,多線程內如果其中一個線程出現了 除0、野指針 等問題會造成該線程崩潰,進而導致整個進程終止。同時,線程是進程的執行分支,線程出異常,就類似進程出異常,進而觸發信號機制,終止進程,進程終止,該進程內的所有線程也就隨即退出。
從上述分析來看,線程的優點相對突出,缺點均不是硬傷。Linux下由於實現方法導致進程、線程差別不是很大。
線程有一套完整的與其有關的函數庫調用,它們中的絕大多數函數名都以pthread_開頭。為了使用這些函數庫調用,我們必須定義宏_REENTRANT,在程序中包含頭文件pthread.h,並且在編譯程序皮嘩時需要用選項-lpthread來鏈接線程庫。其中常用的函數庫如下:
1. pthread_self函數獲取線程ID,其作用對應進程中getpid()函數。
2. pthread_create函數創建一個新線程,其作用對應進程中fork()函數。
3. pthread_exit函數將單個線程退出,其作用對應進程中exit()函數
4. pthread_join函數阻塞等待線程退出,獲取線程退出狀態其作用,對清源應進程中waitpid()函數。
5. pthread_cancel函數殺死(取消)線程其作用,對應進程中kill()函數。
6. pthread_detach函數實現線程分離。
『玖』 linux 信號燈中線程切換問題
(1)Posix標准中有有名信號燈和無名信號燈之分,對於有名信號燈,可以用sem_open來創建,其prototype是:
sem_t *sem_open(const char *name, int oflag);//打開已有的信號燈
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned value);//一般是創建信號燈。
期中name是信號燈的名字, oflag是0, O_CREAT 或者 O_CREAT | O_EXCL, 如果指定O_CREAT, 那麼mode和value對應創建該信號的模式和初始值。 如果指定了O_EXCL, 而且該信號燈已經在系統中存在,那調用會出錯返回SEM_FAILED常量。 對於Linux內核來說,有名信號燈是很晚才加入內核中的,創建或是打開有名信號時候,應該指定」/semname「名字,對應的信號燈創建在/dev/shm目錄下,名字是/dev/shm/sem.semname. BTW, 用gcc/g++編譯實用信號燈功能的程序時候,應該引用librt庫,(e.g., g++ -lrt sem.cpp). 關閉已打開的信號燈,用sem_close(sem_t *sem). 關閉信號燈並不意味著系統會刪除它,要刪除一個信號燈,需要調用sem_unlink(sem_t *sem)。 有名信號燈一般是為了進程之間同步實用的。 無名信號燈,一般是為一個進程內的不同線程之間同步使用的。 創建無名信號燈的方法如下:
sem_t sem;
sem_init(&sem, int shared, unsigned int value);//初始化信號燈。
......
sem_destroy(&sem);//清除信號燈。
(2)信號燈的使用和狀態。
信號燈一般用來描述不同線程所共享的公共資源的數量,每一個信號燈都有一個叫做信號量的非負整數與之相連;信號量一般代表公共資源的數目,比如空閑列表中的緩沖區數目,視頻中讀入幀的數目,等等。對於一個線程可以用sem_wait, sem_post函數來改變一個信號燈的信號量。
sem_wait(sem_t &sem);
sem_wait的語義如下:
{
while(信號量==0)
等待; //此處線程被掛起,等待其他線程調用sem_post喚醒之。
信號量減1;
}
注意:測試信號量是否為零,和減一的操作是原子的,也就是說期間不會發生線程切換。
與sem_wait對應的調用是sem_post,語義如下:
{
信號量加1;
喚醒等待該信號量的線程;//調用sem_wait並等待的線程。
}
該操作也是原子的。
信號燈的狀態可以用sem_getvalue來查看。一般來說sem_wait和sem_post的調用不必在同一個線程內成對出現(象mutex那樣,lock/unlock要配對出現)。 一般的情形是這樣的,一個線程等待資源可用,調用sem_wait, 另外一個線程生成資源,然後調用sem_post,喚醒等待該資源的線程。因為信號燈所描述的是線程間公共資源,使用的時候一般和mutex一起使用,mutex保證訪問公共資源的線程排他性,信號燈表示資源的可用性。
『拾』 關於嵌入式系統線程調度與優先順序的問題,wince或linux
你剛講了線程1的優秀級高,那麼中斷來了之後,肯定要先處理這個線程。
系統不會強制結束當前的線程,如果這樣做可能導致死機活崩潰,因為該線程可能是系統的。
正常的做法是將該線程的數據備份,處理優先順序高的,之後再回來繼續工作