## Specfication same as assignment1 ## Step | 步驟 | 說明 | |:------:|:------:| |1|加入一個system call entry <br> ![image](https://hackmd.io/_uploads/HkdAANvW1g.png)![image-1](https://hackmd.io/_uploads/BySgySvZyx.png)| |2| `cd /usr/src/linux-6.10.9/include/linux` <br> 新增header`sudo gedit printfo.h` <br> ![image-2](https://hackmd.io/_uploads/HJtJkBPZyx.png =500x300)) | |3| 加入system call define`cd /usr/src/linux-6.10.9/kernel` <br> `gedit sys.c`加入header <br><img src="https://hackmd.io/_uploads/Sk1GJBPbkx.png =" width="50%" /><img src="https://hackmd.io/_uploads/H1hzyHwZkg.png =" width="50%" /> |4.1| `cd /usr/src/linux-6.10.9/include/linux` <br>`sudo gedit syscalls.h`加入剛剛自定義好的header **"linux/prinfo.h"**![image-9](https://hackmd.io/_uploads/rkuQkHwWkx.png =500x300)| |4.2| 往下加入system call linkage <br> ![image-5](https://hackmd.io/_uploads/rkMNkBP-yl.png)| |5.1| 開始編譯kernel `sudo make -j8` <br> ![image-10](https://hackmd.io/_uploads/r134krv-kg.png)| |5.2| 安裝剛編譯好的kernel `sudo make install` <br> ![image-11](https://hackmd.io/_uploads/HJ18yBw-1e.png =500x300) | |5.3| 重開機 <br> ![image-12](https://hackmd.io/_uploads/BkT81HwZkg.png)| |6.1| 建立測試檔案 `cd /home` <br> `sudo gedit test2.c` <br> ![image-13](https://hackmd.io/_uploads/HypD1rvZ1l.png)| |6.2|在user mode端呼叫system call **464**! <br> <img src="https://hackmd.io/_uploads/ryDOJSw-Jx.png " width="70%" />| |7|運行的結果,兩個不同shell <br><img src="https://hackmd.io/_uploads/BkNKySDbye.png " width="50%" /><img src="https://hackmd.io/_uploads/Sy45krw-Jl.png" width="50%" />| <div style="page-break-after: always;"></div> # Challenging part 一開始沒看到有tips,所以直接慢慢地從kernel source code裡面挖掘需要的資訊從`sched.h`, `thread_info.h`,從`task_struct`裡面找到PCB的資訊,在想有什麼方式可以直接取得目前process的資訊,這時候我看到有一個叫做`current`的結構,依照裡面macro的定義,在網路上找了一下這個結構的定義,發現`thread_info`有相依性,但型別是`thread_info`,但是又可以接收task_struct的型別,我就嘗試在`SYSTEM_DEFINE`呼叫看看`current`的型別,一試就成功,再來是處理nice value的轉換,kernel code裡面也有包含轉換`static priority`成`nice值`的macro,也成功解決,之後遇到要把kernel當中的資料複製回user mode,需要有copy_to_user的函示來幫忙檢查權限,我是直接複製指標回去,然後編譯看看,有成功的編譯完成,而後面user mode測試也很順利的解決,沒遇到太多問題。 <div style="page-break-after: always;"></div> # Reference [task_struct講解](https://www.cnblogs.com/yungyu16/p/13023982.html) [task struct mapping 技術](https://hackmd.io/@PIFOPlfSS3W_CehLxS3hBQ/S14tx4MqP) [copy to user檢查](https://hackmd.io/@sakuraiiii/r1gFubKkF) [關於linux list_head, list這邊說明得很清楚 : Linux list wrapper](https://hackmd.io/@RinHizakura/HkEuhNwGO) [nice val](https://deepinout.com/linux-kernel-api/linux-kernel-api-process-scheduling/linux-kernel-api-task_nice.html) <div style="page-break-after: always;"></div> # Appendix ### prinfo.h ```c #include <linux/types.h> #ifndef PRINTFO_H #define PRINTFO.H struct printfo{ long state; long nice; pid_t pid; pid_t parent_pid; pid_t youngest_child_pid; unsigned long start_time; long user_time; long sys_time; long uid; char comm[16]; }; #endif ``` ### SYSTEM_DEFINE1 ```c SYSCALL_DEFINE1(print_process_info, struct printfo *, usr_task_info) { struct prinfo task_info; struct prinfo *task_ptr = &task_info; task_ptr->state = current->__state; task_ptr->nice = task_nice(current); task_ptr->pid = current->pid; task_ptr->parent_pid = current->parent->pid; if(!list_empty(&current->children)) task_ptr->youngest_child_pid = list_last_entry(&current->children, struct task_struct, children)->pid; else task_ptr->youngest_child_pid = -1; task_ptr->start_time = current->start_time; task_ptr->user_time = current->utime; task_ptr->sys_time = current->stime; task_ptr->uid = current->cred->uid.val; strncpy(task_ptr->comm, current->comm, 16); if(copy_to_user(usr_task_info, task_ptr, sizeof(struct printfo))) return -EFAULT; return 0 ; } ``` ### test2.c ```c #include <stdio.h> #include <sys/syscall.h> #include <unistd.h> struct printfo{ long state; long nice; pid_t pid; pid_t parent_pid; pid_t youngest_child_pid; unsigned long start_time; long user_time; long sys_time; long uid; char comm[16]; }; int main() { long res = syscall(464, &user_task); printf("Syscall return : &ld\n", res); if(res == 0) { printf("current task state : %ld\n", user_task.state); printf("current task nice val : %ld\n", user_task.nice); printf("current task pid : %d\n", user_task.state); printf("current task parent pid : %d\n", user_task.state); printf("current task youngest child pid : %d\n", user_task.state); printf("current task start time : %ld\n", user_task.state); printf("current task user time : %ld\n", user_task.state); printf("current task system time : %ld\n", user_task.state); printf("current task uid : %ld\n", user_task.state); printf("current task comm : %s\n", user_task.state); return 0; } printf("Something wrong\n"); exit(1); } ```