<!-- {%hackmd theme-dark %} --> # Linux Project 2 111522125 童柏堯 111522140 陳政瑋 111525026 鄧皓 ## Kernel & OS version * 作業系統: ubuntu 22.04 * Kernel 版本: 5.15.137 ## 新增system call ### system call :::info 此system call的用意在於變更目前的process的priority,而此system call目的是想去觀察process的priority在101~139(completely fair scheduling class)的變化中,是否會對process的execution time 照成影響,也就是normal tasks之間priority對於process exection time的關係。 ::: ```Linux #include <linux/kernel.h> #include <linux/syscalls.h> #include <linux/sched.h> SYSCALL_DEFINE1(set_process_priority, int, x) { // Check if x is within the valid range (101 to 139) printk("my_fixed_priority: %d\n", current->my_fixed_priority); printk("my_fixed_priority x: %d\n", x); if (x < 101 || x > 139){ return 0; } else { current->my_fixed_priority = x; return 1; // System call completed successfully } } ``` ### execution c file :::info 整個code的目的是計算process各別在priority 101~139時,所花費的執行時間。set_process_priority(priority)函式使用到了我們所新增的syscall,在更改完priority後,就會開始計算process的execution time。 ::: ```C= #include <stdlib.h> #include <time.h> #include <sys/time.h> #define TOTAL_ITERATION_NUM 100000000 #define NUM_OF_PRIORITIES_TESTED 40 void * set_process_priority(int priority){ long int sys = syscall(451, priority); } int main() { int index=0; int priority,i; struct timeval start[NUM_OF_PRIORITIES_TESTED], end[NUM_OF_PRIORITIES_TESTED]; gettimeofday(&start[index], NULL); //begin for(i=1;i<=TOTAL_ITERATION_NUM;i++) rand(); gettimeofday(&end[index], NULL); //end /*================================================================================*/ for(index=1, priority=101;priority<=139;++priority,++index) { if(!set_process_priority(priority)) printf("Cannot set priority %d.\n", priority); gettimeofday(&start[index], NULL); //begin for(i=1;i<=TOTAL_ITERATION_NUM;i++) rand(); gettimeofday(&end[index], NULL); //end } /*================================================================================*/ printf("The process spent %ld uses to execute when priority is not adjusted.\n", ((end[0].tv_sec * 1000000 + end[0].tv_usec) - (start[0].tv_sec * 1000000 + start[0].tv_usec))); for(i=1;i<=NUM_OF_PRIORITIES_TESTED-1;i++) printf("The process spent %ld uses to execute when priority is %d.\n", ((end[i].tv_sec * 1000000 + end[i].tv_usec) - (start[i].tv_sec * 1000000 + start[i].tv_usec)), i+100); } ``` ### outupt ![image](https://hackmd.io/_uploads/SkJDwj5_6.png) ### Observation :::info 1. process的執行時間跟Priority依照我們的觀察是沒有相關性的 2. 第一行的priority is not adjusted依照程式邏輯是因為還沒賦值給current->my_fixed_prioity(我們也利用printk來驗證我們的想法) :::spoiler ![螢幕擷取畫面 2024-01-05 160517](https://hackmd.io/_uploads/rkl7arSu6.png) ![螢幕擷取畫面 2024-01-05 160531](https://hackmd.io/_uploads/HJ776HH_T.png) ::: ## kernel需要更改的地方 :::info 在kernel/sched/core.c 賦值,利用system call傳入的value 給新增的task_struct欄位: ==my_fixed_priority== ,再將my_fixed_priority賦值給static_prio。 **line 50為新增指令** *** :::success **code相關資料** 1. prepare_task_switch(rq, prev, next) & finish_task_switch(prev):為下一次任務切換做好準備工作,以確保系統可以順利地進行context switch,並確保各個任務能夠正確地執行。 2. process address space切換(中間if_else部分):context switch時,處理當前process和即將要執行的process之間的page切換和memory management。 3. rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP):清除rq的時鐘更新標誌。 4. prepare_lock_switch(rq, next, rf):確保在context switch期間不會出現race condition。 5. switch_to(prev, next, prev):切換是在 switch_to 函數中完成的。 保存原process所有的register,恢復新process所有register,執行新process。 ::: ```Linux= static __always_inline struct rq * context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next, struct rq_flags *rf) { prepare_task_switch(rq, prev, next); /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into * one hypercall. */ arch_start_context_switch(prev); /* * kernel -> kernel lazy + transfer active * user -> kernel lazy + mmgrab() active * * kernel -> user switch + mmdrop() active * user -> user switch */ if (!next->mm) { // to kernel enter_lazy_tlb(prev->active_mm, next); next->active_mm = prev->active_mm; if (prev->mm) // from user mmgrab(prev->active_mm); else prev->active_mm = NULL; } else { // to user membarrier_switch_mm(rq, prev->active_mm, next->mm); /* * sys_membarrier() requires an smp_mb() between setting * rq->curr / membarrier_switch_mm() and returning to userspace. * * The below provides this either through switch_mm(), or in * case 'prev->active_mm == next->mm' through * finish_task_switch()'s mmdrop(). */ switch_mm_irqs_off(prev->active_mm, next->mm, next); if (!prev->mm) { // from kernel /* will mmdrop() in finish_task_switch(). */ rq->prev_mm = prev->active_mm; prev->active_mm = NULL; } } prev->static_prio=prev->my_fixed_priority; rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP); prepare_lock_switch(rq, next, rf); /* Here we just switch the register state and the stack. */ switch_to(prev, next, prev); barrier(); return finish_task_switch(prev); } ``` ### 在 struct task_struct新增的feild :::warning 我們想在process descriptior中新增欄位(變數),因此在```include/linux/sched.h```找到了struct task_struct,由於linux在這部分程式碼的撰寫上是直接使用offset去編譯,因此為了不影響整體程式的運行,我們找到此task_struct最後的欄位位置,新增my_fixed_priority變數,避免程式發生錯誤。 ::: ![螢幕擷取畫面 2024-01-05 160657](https://hackmd.io/_uploads/B13LTrB_a.png) ### core-y新增我們新的system call名稱 set_process_priority ![螢幕擷取畫面 2024-01-05 160745](https://hackmd.io/_uploads/S1xuaBH_6.png) ### syscall_64.tbl新增system call編號為451 ![螢幕擷取畫面 2024-01-05 160835](https://hackmd.io/_uploads/ByFdaHH_6.png) ### syscalls.h新增syscall的prototype ![螢幕擷取畫面 2024-01-05 160909](https://hackmd.io/_uploads/BkGKaHrda.png)