linux进程的高级管理,sched_yield()函数 高级进程管理
1、讓出處理器
Linux提供一個(gè)系統(tǒng)調(diào)用運(yùn)行進(jìn)程主動(dòng)讓出執(zhí)行權(quán):sched_yield。進(jìn)程運(yùn)行的好好的,為什么需要這個(gè)函數(shù)呢?有一種情況是用戶(hù)空間線(xiàn)程的鎖定。如果一個(gè)線(xiàn)程試圖取得另一個(gè)線(xiàn)程所持有的鎖,則新的線(xiàn)程應(yīng)該讓出處理器知道該鎖變?yōu)榭捎谩S脩?hù)空間鎖沒(méi)有內(nèi)核的支持,這是一個(gè)最間單、最有效率的做法。但是現(xiàn)在Linux線(xiàn)程實(shí)現(xiàn)引入一個(gè)使用futexes的優(yōu)化解決方案。
另一個(gè)情況是在有處理器密集型程序可用周期性調(diào)用sched_yield,試圖將該進(jìn)程對(duì)系統(tǒng)的沖擊減到最小。不管怎么說(shuō),如何調(diào)度程序應(yīng)該是系統(tǒng)的事情,而不是進(jìn)程自己去管。eg:
int main(){ int ret, i;
ret = sched_yield(); if(ret == -1){
printf("調(diào)用sched_yield失敗!\n");
} return 0;
}
那該調(diào)用內(nèi)核是如何實(shí)現(xiàn)的?2.6以前的版本sched_yield所造成的影響非常小,如果存在另一個(gè)可以運(yùn)行的進(jìn)程,內(nèi)核就切換到該進(jìn)程,把進(jìn)行調(diào)用的進(jìn)程放在可運(yùn)行進(jìn)程列表的結(jié)尾處。短期內(nèi)內(nèi)核會(huì)對(duì)該進(jìn)程進(jìn)行重新調(diào)度。這樣的話(huà)可能出現(xiàn)“乒乓球”現(xiàn)象,也就是兩個(gè)程序來(lái)回運(yùn)行,直到他們都運(yùn)行結(jié)束。2.6版本中做了一些改變:
如果進(jìn)程是RR,把它放到可運(yùn)行進(jìn)程結(jié)尾,返回。
否則,把它從可運(yùn)行進(jìn)程列表移除,放到到期進(jìn)程列表,這樣在其他可運(yùn)行進(jìn)程時(shí)間片用完之前不會(huì)再運(yùn)行該進(jìn)程。
從可執(zhí)行進(jìn)程列表中找到另一個(gè)要執(zhí)行的進(jìn)程。
2、進(jìn)程的優(yōu)先級(jí)
看過(guò)CFS中會(huì)看到進(jìn)程的nice value會(huì)決定進(jìn)程會(huì)運(yùn)行多長(zhǎng)時(shí)間,或者說(shuō)是占用的百分比。可以通過(guò)系統(tǒng)調(diào)用nice來(lái)設(shè)置、獲取進(jìn)程的nice value。該值的范圍是-20~19,越低的值越高的優(yōu)先級(jí)(這個(gè)在計(jì)算虛擬時(shí)間的時(shí)候放在分母上),實(shí)時(shí)進(jìn)程應(yīng)該是負(fù)數(shù),eg:
int main(){ int ret, i;
ret = nice(0);
printf("當(dāng)前進(jìn)程的nice value:%d\n", ret);
ret = nice(10);
printf("當(dāng)前進(jìn)程的nice value:%d\n", ret); return 0;
}
因?yàn)閞et本來(lái)就可以是-1,那么在判斷是否系統(tǒng)調(diào)用失敗的時(shí)候就要綜合ret和errno。還有兩個(gè)系統(tǒng)調(diào)用可以更靈活地設(shè)置,getpriority可以獲得進(jìn)程組、用戶(hù)的任何進(jìn)程中優(yōu)先級(jí)最高的。setpriority將所指定的所有進(jìn)程優(yōu)先級(jí)設(shè)置為prio,eg:
int main(){ int ret, i;
ret = getpriority(PRIO_PROCESS, 0);
printf("nice value:%d\n", ret);
ret = setpriority(PRIO_PROCESS, 0, 10);
ret = getpriority(PRIO_PROCESS, 0);
printf("nice value:%d\n", ret); return 0;
}
進(jìn)程有在處理器上執(zhí)行的優(yōu)先級(jí),也有傳輸數(shù)據(jù)的優(yōu)先級(jí):I/O優(yōu)先級(jí)。linux有額外的兩個(gè)系統(tǒng)調(diào)用可用顯示設(shè)置和取得I/O nice value,但是尚未導(dǎo)出:
int ioprio_get(int which, int who); int ioprio_set(int which, int who, int ioprio);
3、處理器親和性
Linux支持具有多個(gè)處理器的單一系統(tǒng)。在SMP上,系統(tǒng)要決定每個(gè)處理器上要運(yùn)行那些程序,這里有兩項(xiàng)挑戰(zhàn):
調(diào)度程序必須想辦法充分利用所有的處理器。
切換程序運(yùn)行的處理器是需要代價(jià)的。
進(jìn)程會(huì)繼承父進(jìn)程的處理器親和性,Linux提供兩個(gè)系統(tǒng)調(diào)用用于獲取和設(shè)定“硬親和性”。eg:
int main(){ int ret, i;
cpu_set_t set;
CPU_ZERO(&set);
ret = sched_getaffinity(0, sizeof(cpu_set_t), &set); if(ret == -1)
printf("調(diào)用失敗!\n"); for(i = 0; i < 10; i++){ int cpu = CPU_ISSET(i, &set);
printf("cpu=%i is %s\n", i, cpu?"set":"unset");
}
CPU_ZERO(&set);
CPU_SET(0, &set);
CPU_CLR(1, &set);
ret = sched_setaffinity(0, sizeof(cpu_set_t), &set); if(ret == -1)
printf("調(diào)用失敗!\n"); for(i = 0; i < 10; i++){ int cpu = CPU_ISSET(i, &set);
printf("cpu=%i is %s\n", i, cpu?"set":"unset");
} return 0;
}
4、Linux的調(diào)度策略與優(yōu)先級(jí)
關(guān)于Linux系統(tǒng)中對(duì)進(jìn)程的幾種調(diào)度方法和他們的區(qū)別就不在這里說(shuō)了,這里關(guān)注的是如何獲取、設(shè)置這些值。可以使用sched_getscheduler來(lái)獲取進(jìn)程的調(diào)度策略,eg:
int main(){ int ret, i; struct sched_param sp;
sp.sched_priority = 1;
ret = sched_setscheduler(0, SCHED_RR, &sp); if(ret == -1)
printf("sched_setscheduler failed.\n"); if(errno == EPERM)
printf("Process don't the ability.\n");
ret = sched_getscheduler(0); switch(ret){ case SCHED_OTHER:
printf("Policy is normal.\n"); break; case SCHED_RR:
printf("Policy is round-robin.\n"); break; case SCHED_FIFO:
printf("Policy is first-in, first-out.\n"); break; case -1:
printf("sched_getscheduler failed.\n"); break; default:
printf("Unknow policy\n");
} return 0;
}
sched_getparam和sched_setparam接口可用于取得、設(shè)定一個(gè)已經(jīng)設(shè)定好的策略,這里不只是返回一個(gè)策略的ID,eg:
int main(){ int ret, i; struct sched_param sp;
sp.sched_priority = 1;
ret = sched_setparam(0, &sp); if(ret == -1)
printf("sched_setparam error.\n");
ret = sched_getparam(0, &sp); if(ret == -1)
printf("sched_getparam error.\n");
printf("our priority is %d.\n", sp.sched_priority); return 0;
}
Linux提供兩個(gè)用于取得有效優(yōu)先值的范圍的系統(tǒng)調(diào)用,分別返回最大值、最小值,eg:
int main(){ int ret, i; struct sched_param sp;
ret = sched_get_priority_min(SCHED_RR); if(ret == -1)
printf("sched_get_priority_min error.\n");
printf("The min nice value is %d.\n", ret);
ret = sched_get_priority_max(SCHED_RR); if(ret == -1)
printf("sched_get_priority_max error.\n");
printf("The mmax nice value is %d.\n", ret); return 0;
}
關(guān)于時(shí)間片,這個(gè)概念可能在Linux中和傳統(tǒng)的在操作系統(tǒng)的課程中學(xué)到的還是有很大的區(qū)別的,如果感興趣的化可以看看CFS里面的。通過(guò)sched_rr_get_interval可以取到分配給pid的時(shí)間片的長(zhǎng)度,eg:
int main(){ int ret, i; struct timespec tp;
ret = sched_rr_get_interval(0, &tp); if(ret == -1)
printf("sched_rr_get_interval error.\n");
printf("The time is %ds:%ldns.\n", (int)tp.tv_sec, tp.tv_nsec); return 0;
}
5、實(shí)時(shí)進(jìn)程的預(yù)防措施
由于實(shí)時(shí)進(jìn)程的本質(zhì),開(kāi)發(fā)者在開(kāi)發(fā)和調(diào)試此類(lèi)程序時(shí)應(yīng)該謹(jǐn)慎行事,如果一個(gè)實(shí)時(shí)進(jìn)程突然發(fā)脾氣,系統(tǒng)的反應(yīng)會(huì)突然變慢。任何一個(gè)CPU密集型循環(huán)在一個(gè)實(shí)時(shí)程序中會(huì)繼續(xù)無(wú)止境地運(yùn)行下去,只要沒(méi)有優(yōu)先級(jí)更高實(shí)時(shí)進(jìn)程變成可運(yùn)行的。因此設(shè)計(jì)實(shí)時(shí)程序的時(shí)候要謹(jǐn)慎,這類(lèi)程序至高無(wú)上,可用輕易托跨整個(gè)系統(tǒng),下面是一些要決與注意事項(xiàng):
因?yàn)閷?shí)時(shí)進(jìn)程會(huì)好用系統(tǒng)上一切資源,小心不要讓系統(tǒng)其他進(jìn)程等不到處理時(shí)間。
循環(huán)可能會(huì)一直運(yùn)行到結(jié)束。
小心忙碌等待,也就是實(shí)時(shí)進(jìn)程等待一個(gè)優(yōu)先級(jí)低的進(jìn)程所占有的資源。
開(kāi)發(fā)一個(gè)實(shí)時(shí)進(jìn)程的時(shí)候,讓一個(gè)終端保持開(kāi)啟狀態(tài),以更高的優(yōu)先級(jí)來(lái)運(yùn)行該實(shí)時(shí)進(jìn)程,發(fā)生緊急情況終端機(jī)依然會(huì)有反應(yīng),允許你終止失控的實(shí)時(shí)進(jìn)程。
使用chrt設(shè)置、取得實(shí)時(shí)屬性。
6、資源限制
Linux對(duì)進(jìn)程加上了若干資源限制,這些限制是一個(gè)進(jìn)程所能耗用的內(nèi)核資源的上限。限制的類(lèi)型如下:
RLIMIT_AS:地址空間上限。
RLIMIT_CORE:core文件大小上限。
RLIMIT_CPU:可耗用CPU時(shí)間上限。
RLIMIT_DATA:數(shù)據(jù)段與堆的上限。
RLIMIT_FSIZE:所能創(chuàng)建文件的大小上限。
RLIMIT_LOCKS:文件鎖數(shù)目上限。
RLIMIT_MEMLOCK:不具備CAP_SYS_IPC能力的進(jìn)程最多將多少個(gè)字節(jié)鎖進(jìn)內(nèi)存。
RLIMIT_MSGQUEUE:可以在消息隊(duì)列中分配多少字節(jié)。
RLIMIT_NICE:最多可以將自己的友善值調(diào)多低。
RLIMIT_NOFILE:文件描述符數(shù)目的上限。
RLIMIT_NPROC:用戶(hù)在系統(tǒng)上能運(yùn)行進(jìn)程數(shù)目上限。
RLIMIT_RSS:內(nèi)存中頁(yè)面的數(shù)目的上線(xiàn)。
RLIMIT_RTPRIO:不具備CAP_SYS_NICE能力進(jìn)程所能請(qǐng)求的實(shí)時(shí)優(yōu)先級(jí)的上限。
RLIMIT_SIGPENDING:在隊(duì)列中信號(hào)量的上限,Linux特有的限制。
RLIMIT_STACK:堆棧大小的上限。
這些就不多說(shuō)了,到了實(shí)際用到的時(shí)候再仔細(xì)看,eg:
int main(){ int ret, i; struct rlimit rlim;
rlim.rlim_cur = 32*1024*1024;
rlim.rlim_max = RLIM_INFINITY;
ret = setrlimit(RLIMIT_CORE, &rlim);
ret = getrlimit(RLIMIT_CORE, &rlim); if(ret == -1)
printf("getrlimit error.\n");
printf("RLIMIT_CORE limits: soft=%ld hard=%ld\n", rlim.rlim_cur, rlim.rlim_max); return 0;
}
總結(jié)
以上是生活随笔為你收集整理的linux进程的高级管理,sched_yield()函数 高级进程管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 历史影像再来一波(能到70年代、80年代
- 下一篇: linux挂载文件夹