日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

操作系统进程学习(Linux 内核学习笔记)

發(fā)布時(shí)間:2023/12/10 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 操作系统进程学习(Linux 内核学习笔记) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

操作系統(tǒng)進(jìn)程學(xué)習(xí)(Linux 內(nèi)核學(xué)習(xí)筆記)

進(jìn)程優(yōu)先級(jí)

并非所有進(jìn)程都具有相同的重要性。除了大多數(shù)我們所熟悉的進(jìn)程優(yōu)先級(jí)之外,進(jìn)程還有不同的關(guān)鍵度類別,以滿足不同需求。首先進(jìn)程比較粗糙的劃分,進(jìn)程可以分為實(shí)時(shí)進(jìn)程非實(shí)時(shí)進(jìn)程(普通進(jìn)程)

實(shí)時(shí)進(jìn)程優(yōu)先級(jí)(0-99)都比普通 進(jìn)程的優(yōu)先級(jí)(100-139)高。當(dāng)系統(tǒng)中有實(shí)時(shí)進(jìn)程運(yùn)行時(shí),普通進(jìn)程幾乎無(wú)法分到時(shí)間片(只能分到5%的CPU時(shí)間)。

進(jìn)程系統(tǒng)調(diào)用

? 討論fork和exec系列系統(tǒng)調(diào)用的實(shí)現(xiàn)。通常這些調(diào)用不是由應(yīng)用程序直接發(fā)出的,而是通過(guò)一個(gè)中間層調(diào)用,即負(fù)責(zé)與內(nèi)核通信的C標(biāo)準(zhǔn)庫(kù)。從用戶狀態(tài)切換到核心態(tài)的方法,依不同的體系結(jié)構(gòu)而各有不同

用戶發(fā)起一個(gè)新進(jìn)程之后,CPU為進(jìn)程分配資源,并將硬盤數(shù)據(jù)讀到內(nèi)存中去,但是用戶進(jìn)程是一個(gè)應(yīng)用級(jí)程序,無(wú)法直接與CPU進(jìn)行交互,所以通過(guò)系統(tǒng)調(diào)用(system_call),加載完成內(nèi)核就會(huì)退出CPU,用戶進(jìn)程執(zhí)行完畢后,內(nèi)核進(jìn)入CPU將用戶進(jìn)程移除,下一個(gè)同上

  • 進(jìn)程復(fù)制

    (1) fork是重量級(jí)調(diào)用,因?yàn)樗⒘烁高M(jìn)程的一個(gè)完整副本,然后作為子進(jìn)程執(zhí)行。 為減少與該調(diào)用相關(guān)的工作量,Linux使用了寫時(shí)復(fù)制(copy-on-write)1技術(shù)。

    (2) vfork類似于fork,但并不創(chuàng)建父進(jìn)程數(shù)據(jù)的副本。相反,父子進(jìn)程之間共享數(shù)據(jù)。 這節(jié)省了大量CPU時(shí)間(如果一個(gè)進(jìn)程操縱共享數(shù)據(jù),則另一個(gè)會(huì)自動(dòng)注意到)。

    (3) clone產(chǎn)生線程,可以對(duì)父子進(jìn)程之間的共享、復(fù)制進(jìn)行精確控制。

  • 調(diào)度器分析

  • 調(diào)度器及其功能

    內(nèi)核中用來(lái)安排進(jìn)程執(zhí)行的模塊稱為調(diào)度器(scheduler),它可以切換進(jìn)程狀態(tài) (process state)。例如執(zhí)行、可中斷睡眠、不可中斷睡眠、退出、暫停等。 調(diào)度器是CPU中央處理器的管理員,主要負(fù)責(zé)完成做兩件事情:一、選擇某些就緒進(jìn) 程來(lái)執(zhí)行,二是打斷某些執(zhí)行的進(jìn)程讓它們變?yōu)榫途w狀態(tài)。調(diào)度器分配CPU時(shí)間的基本依據(jù)就 是進(jìn)程的優(yōu)先級(jí)。上下文 切換(context switch):將進(jìn)程在CPU中切換執(zhí)行的過(guò)程,內(nèi)核承擔(dān) 此任務(wù),負(fù)責(zé)重建和存儲(chǔ)被切換掉之前的CPU狀態(tài)

  • 主要有兩個(gè)函數(shù)可以獲得線程設(shè)置的最高和最低優(yōu)先級(jí):

    int sched_get_priority_max(int); // 獲取實(shí)時(shí)優(yōu)先級(jí)最大值 int sched_get_priority_min(int); // 獲取實(shí)時(shí)優(yōu)先級(jí)最小值

    設(shè)置與獲取優(yōu)先級(jí)各個(gè)主要函數(shù):

    int pthread_attr_setschedparam(pthread_attr_t*,const struct sched_param);//創(chuàng)建線程優(yōu)先級(jí) int pthread_attr_getschedparam(pthread_attr_t*,const struct sched_param);//獲取線程優(yōu)先級(jí)

    實(shí)戰(zhàn):

    #include <assert.h> #include <iostream> #include <pthread.h> #include <sched.h> #include <stdio.h>static int get_thread_policy(pthread_attr_t *attr) //獲取線程調(diào)度策略 {int plicy;int rs = pthread_attr_getschedpolicy(attr, &plicy);assert(rs == 0);switch (plicy){case SCHED_FIFO:printf("policy = FIFO");break;case SCHED_RR:printf("policy = RR");break;case SCHED_OTHER:printf("policy=OTHER");break;default:printf("policy = unknown");break;}return plicy; }static void show_thread_priority(pthread_attr_t *attr, int policy) {int priority = sched_get_priority_max(policy);assert(priority != -1);printf("max_priority=%d\n", priority);priority = sched_get_priority_min(policy);assert(priority != -1);printf("min_priority=%d\n", priority); }static int get_thread_priority(pthread_attr_t *attr) //獲取線程優(yōu)先級(jí) {sched_param param;int rs = pthread_attr_getschedparam(attr, &param);assert(rs == 0);printf("priority = %d", param.sched_priority);return param.sched_priority; } static void set_thread_policy(pthread_attr_t *attr, int policy) {int rs = pthread_attr_setschedpolicy(attr, policy);assert(rs == 0);get_thread_policy(attr); }int main(int argc, char const *argv[]) {pthread_attr_t attr;struct sched_param sched;int rs = pthread_attr_init(&attr);assert(rs == 0);int plicy = get_thread_policy(&attr);printf("輸出進(jìn)程優(yōu)先級(jí)\n");show_thread_priority(&attr, plicy);printf("輸出FIFO優(yōu)先級(jí)");show_thread_priority(&attr, SCHED_FIFO);printf("輸出RR優(yōu)先級(jí)\n");show_thread_priority(&attr, SCHED_RR);printf("輸出當(dāng)前線程優(yōu)先級(jí)");int priority = get_thread_priority(&attr);printf("設(shè)置線程策略\n");printf("設(shè)置FIFO策略");set_thread_policy(&attr, SCHED_FIFO);printf("設(shè)置RR策略");set_thread_policy(&attr, SCHED_RR);printf("還原線程屬性\n");set_thread_policy(&attr, plicy);rs = pthread_attr_destroy(&attr);assert(rs == 0);return 0; }

    實(shí)戰(zhàn)2

    #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>void threadfunc1() {sleep(1);int policy;struct sched_param praram;pthread_getschedparam(pthread_self(), &policy, &praram);if (policy == SCHED_OTHER)printf("SCHED_OTHER.\n");if (policy == SCHED_RR);printf("SCHED_RR 1.\n");if (policy == SCHED_FIFO)printf("SCHED_FIFO.\n");for (int i = 1; i <= 10; i++){for (int j = 1; j < 4000000; j++){}printf("Threadfunc1.\n");}printf("pthreadfunc1 EXIT.\n"); }void threadfunc2() {sleep(1);int policy;struct sched_param praram;pthread_getschedparam(pthread_self(), &policy, &praram);if (policy == SCHED_OTHER)printf("SCHED_OTHER.\n");if (policy == SCHED_RR);printf("SCHED_RR 1.\n");if (policy == SCHED_FIFO)printf("SCHED_FIFO.\n");for (int i = 1; i <= 10; i++){for (int j = 1; j < 4000000; j++){}printf("Threadfunc2.\n");}printf("pthreadfunc2 EXIT.\n"); }void threadfunc3() {sleep(1);int policy;struct sched_param praram;pthread_getschedparam(pthread_self(), &policy, &praram);if (policy == SCHED_OTHER)printf("SCHED_OTHER.\n");if (policy == SCHED_RR);printf("SCHED_RR 1.\n");if (policy == SCHED_FIFO)printf("SCHED_FIFO.\n");for (int i = 1; i <= 10; i++){for (int j = 1; j < 4000000; j++){}printf("Threadfunc3.\n");}printf("pthreadfunc3 EXIT.\n"); }int main() {int i;i = getuid();if (i == 0)printf("the current user is root.\n");elseprintf("the current user is not root.\n");pthread_t ppid1, ppid2, ppid3;struct sched_param param;pthread_attr_t attr1, attr2, attr3;pthread_attr_init(&attr2);pthread_attr_init(&attr1);pthread_attr_init(&attr3);param.sched_priority = 51;pthread_attr_setschedpolicy(&attr3, SCHED_RR);pthread_attr_setschedparam(&attr3, &param);pthread_attr_setinheritsched(&attr3, PTHREAD_EXPLICIT_SCHED);param.sched_priority = 22;pthread_attr_setschedpolicy(&attr2, SCHED_RR);pthread_attr_setschedparam(&attr2, &param);pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);pthread_create(&ppid3, &attr1, (void *)threadfunc3, NULL);pthread_create(&ppid2, &attr2, (void *)threadfunc2, NULL);pthread_create(&ppid1, &attr3, (void *)threadfunc1, NULL);pthread_join(ppid3, NULL);pthread_join(ppid2, NULL);pthread_join(ppid1, NULL);pthread_attr_destroy(&attr3);pthread_attr_destroy(&attr2);pthread_attr_destroy(&attr1);return 0; }

    RCU機(jī)制

    ? RCU英文全稱為Read-Copy-Update,顧名思義就是 “讀 - 拷貝-更新”,是內(nèi)核中重要 的同步機(jī)制。Linux內(nèi)核已有原子操作、讀寫信號(hào)量等等鎖機(jī)制,為何會(huì)單獨(dú)設(shè)計(jì)一個(gè)比較復(fù)雜的新機(jī)制?

    RCU原理

    ? RCU記錄所有指向共享數(shù)據(jù)的指針的使用者,當(dāng)要修改該共享數(shù)據(jù)時(shí),首先創(chuàng)建一個(gè) 副本,在副本中修改。所有讀訪問(wèn)線程都離開讀臨界區(qū)之后 ,指針指向新的修改后副本的指針,并且刪除舊數(shù)據(jù)

  • 寫者修改對(duì)象的過(guò)程:首先生成一個(gè)副本,讓后更新副本,最后使用新的對(duì)象替換舊的對(duì)象,在寫者執(zhí)行復(fù)制更新的時(shí)候讀者可以讀數(shù)據(jù)
  • 寫者刪除對(duì)象:必須等到所有訪問(wèn)的讀者訪問(wèn)結(jié)束,才能執(zhí)行銷毀操作,RCU技術(shù)的關(guān)鍵:如何判斷所有的讀者已經(jīng)結(jié)束訪問(wèn),等待所有讀者訪問(wèn)時(shí)間結(jié)束的時(shí)間稱為寬限期
  • RCU讀者并不需要與寫進(jìn)行同步,讀者和寫者能夠并發(fā)執(zhí)行,RCU目標(biāo)最大程序來(lái)減少讀者的開銷,因?yàn)橐步?jīng)常使用于讀者性能要求高的場(chǎng)合
  • RCU優(yōu)點(diǎn):讀者開銷少,不需要鎖,原子指令,內(nèi)存屏障等,無(wú)死鎖問(wèn)題,無(wú)內(nèi)存泄露風(fēng)險(xiǎn)

    RCU缺點(diǎn):寫者同步開銷比較大,寫著之間需要互斥處理,同步機(jī)制復(fù)雜

    內(nèi)核內(nèi)存布局

    ? ARM64架構(gòu)處理器采用48位物理尋址機(jī)制,最大可尋找256TB的物理地址空間。對(duì)于 目前應(yīng)用完全足夠,不需要擴(kuò)展到64位的物理尋址。虛擬地址也同樣最大支持48位尋址,所以 在處理器架構(gòu)設(shè)計(jì)上,把虛擬地址空間劃分為兩個(gè)空間,每個(gè)空間最大支持256TB,linux內(nèi)核 在大多數(shù)體系結(jié)構(gòu)上都把兩個(gè)地址劃分為:用戶空間和內(nèi)核空間。

    用戶空間:0x0000_0000_0000_0000至0x0000_ffff_ffff_ffff。

    內(nèi)核空間:0xffff_0000_0000_0000至0xffff_ffff_ffff_ffff

    總結(jié)

    以上是生活随笔為你收集整理的操作系统进程学习(Linux 内核学习笔记)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。