TRƯỜNG ĐẠI HỌC BÁCH KHOA - ĐẠI HỌC QUỐC GIA TP Hồ CHÍ MINH KHOA KHOA HỌC VÀ KỸ THUẬT MÁY TÍNH MƠN HỌC: HỆ ĐIÊU HÀNH Bài tập lớn System Call GVHD: La Hoàng Lộc SVTH: Nguyễn Xuân Trực - 1513804 Lóp: L01 Hồ Chí Minh, 05/2020 Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Trường Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính Minh Khoa Khoa học Kỹ thuật Máy tính Mục lục Bài Bàitập tậplớn lớn1 1- -HệHệđiều điềuhành hành, ,2019 2019- -2020 2020 Trang Trang2/9 2/9 Biên dịch Linux Kernel 1.1 Chuẩn bị Thiết lập máy ảo (Virtual machine): Trong tập lốn này, cài đặt Ubuntu 18.04 máy ảo VirtuaBox Và cấp phát cho máy ảo đủ RAM cần thiết, dung lượng ổ cứng tối thiểu 40GB Cài đặt core packages: Sau cài xong máy ảo, cài Ubuntu's toolchain (gcc, make): $ sudo apt-get update $ sudo apt-get install build-essential Sau cài kernel-package: $ sudo apt-get install kernel-package Câu hỏi: Tại phải cài kernel-package? 10 Trả lời: Bởi kernel-package có nhiều phiên hạt nhân (kernel) để lựa chọn cho phù hợp vói cấu hình phần cứng máy ảo (hay máy thật) bạn 11 Tạo thư mục biên dịch kernel : Tiếp theo, ta tạo mói thư mục kernelbuild Home Sau tải kernel source giải nén, tập lón này, ta sử dụng phiên kernel 5.0.5: 12 $ mkdir ~/kernelbuild 13 $ cd ~/kernelbuild 14 $ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.5.tar.xz 15 $ tar -xvJf linux-5.0.5.tar.xz 16 Câu hỏi: Tại phải sử dụng kernel source khác từ server http://www.kernel.org Chúng ta biên dịch kernel source gốc (kernel OS hành) trực tiếp không? 17 Trả lời: Được, biên dịch hạt nhân gốc (the original kernel) tệp OS sử dụng, kernel mặc định vận chuyển vói Debian xử lý hầu hết cấu hình Ngồi ra, Debian thường cung cấp số kernel thay thế, cần kiểm tra trưóc kernel tưìng thích tốt vói cấu hình phần cứng, nhiên lợi ích cụ thể biên dịch từ kernel mói từ server để: • Xử lý nhu cầu phần cứng đặc biệt, xung đột phần cứng vói kernel cung cấp trưóc • Sử dụng tùy chọn sử dụng kernel mà không hỗ trợ kernel cung cấp trưóc (chẳng hạn hỗ trợ nhó cao) • Tối ưu hóa kernel cách loại bỏ trình điều khiển vơ ích để tăng tốc độ khởi động • Tạo monolithic thay kernel modularized • Chạy cập nhật kernel dành cho nhà phát triển 1.2 Cấu hình 18 Cấu hình kernel nằm file config, cách cài đặt lại tùy chỉnh file cấu hình giúp kernel máy tính hoạt động cách hiệu 19 Chúng ta copy file cấu hình kernel OS sang thư mục linux-5.0.5: 20 $ cp /boot/config-$(uname -r) /kernelbuild/.config 21 Sau đó, đổi tên lại phiên kernel Để tùy chỉnh file cấu hình thơng qua terminal interface, ta phải cài đặt thêm package cần thiết: 22 $ sudo apt-get install fakeroot ncurses-dev xz-utils bc flex libelf-dev bison libncurses5-dev openssl libssl-dev 23 Và chạy lệnh make menuconfig make nconfig để mở Kernel Configuration: 24 $ make nconfig 25 Để thay đổi phiên kernel, chọn General setup option -> (-ARCH) Local version - append to kernel release, sau nhập vào 1513804 26 Lưu file lại thoát 1.3 Xây dựng kernel cấu hình 27 Đầu tiên ta phải biên dịch kernel tạo máy ảo vmlinuz Việc khoảng thời gian dài Trong terminal, di chuyển đến thư mục linux-5.0.5 command: 28 $ make 29 Hoặc 30 $ make -j 31 Sau xây dựng loadable kernel modules: 32 $ make modules 33 Hoặc 34 $ make -j modules 35 Câu hỏi: Ý nghĩa command make make modules gì? Những tạo để làm gì? 36 Trả lời: • make: biên dịch liên kết kernel image Kết tạo file có tên vmlinuz • make modules: biên dịch module Kết tạo file nhị phân 1.4 Cài đặt kernel 37 Đầu tiên cài đặt modules: 38 $ sudo make modules_install 39 Hoặc 40 $ sudo make -j modules_install 41 Sau cài đặt kernel mói: 42 $ sudo make install 43 Hoặc 44 $ sudo make -j install 45 Sẽ thời gian để hồn thành việc cài đặt kernel mói Sau cài đặt xong, khởi động lại máy: 46 $ sudo reboot 47 Sau khởi động lại, kiểm tra việc cài đặt command sau: 48 $ uname -r 49 Kết quả: kết có chứa MSSV, việc biên dịch cài đặt thành cơng 50 osboxes@osboxes: ~ 51 File Edit view Search Terminal Help osboxesgosboxesuname -r 5.0.5.1513804 osboxes@osboxes:~s I Làm gọn kernel (trim the kernel) 52 Sau cài đặt kernel thành công, có kernel mói vói cấu hình mặc định Nó bao gồm gói hỗ trợ tất thứ, dẫn đến dư thừa không cần thiết Vói cấu hình này, nhiều thời gian để biên dịch Trong khuôn khổ tập lón này, cần cấu hình kernel khác cho máy Cụ thể, nên mở lại make nconfig để chọn cấu hình phù hợp cho máy Nó cung cấp cho loạt menu, từ chọn tùy chọn ta muốn đưa vào Sau cấu hình, biên lại lại kernel System Call 3.1 Hiện thực system call 53 Trong thư mục kernelbuild, tạo mói thư mục có tên get_proc_info, sau tạo file sys_get_proc_info.c bên thư mục get_proc_info: 54 $ cd ~/kernelbuild 55 $ mkdir get_proc_info 56 $ cd get_proc_info 57 $ touch sys_get_proc_info.c 58 Sau viết code vào file sys_get_proc_info.c: 1 Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 3 59 60 61 62 63 64 5 6 #include #include #include #include #include struct proc_info { pid_t pid; char name[16]; 9 65 } 66 struct procinfos { 10 10 11 67 68 69 70 11 12 12 13 13 71 long studentlD; struct proc_info proc; struct proc_info parent_proc; struct proc_info oldest_child_proc; }; 14 14 72 asmlinkage long sys_get_proc_info(pid_t pid, struct procinfos *info){ struct task_struct *task = pid_task ( find_vpid ( pid ) , PIDTYPE_PID); printk("Finding \n"); 73 for_each_process(task) { printk("[%d] - [%s]\n", task->pid, task->comm); 74 if(task->pid == pid) { if(task->mm != NULL){ 75 //struct proc_info proc; struct procinfos buff; buff.studenID = 1513804; buff.proc.pid = task->pid; buff.proc.name = task->comm; buff.parent_proc.pid = task->real-parent->pid; buff.oldest_child_proc.pid = task->children->pid; int res = copy_to_user(info, &buff, sizeof(buff)); if(res == 0) printk("success!"); 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 76 else printk("fail"); 23 return 0; 24 77 } 24 78 25 79 80 25 26 26 27 81 } } return -1; } 27 28 28 29 29 30 30 31 31 32 32 33 33 82 Sau đó, tạo Makefile: 83 $ pwd 84 ~/kernelbuild/get_proc_info 85 $ touch Makefile 86 $ echo "obj-y := get_proc_info.o" » Makefile 87 Sau vào kernel Makefile, tìm dịng: 34 34 35 35 36 36 37 37 Bài tập lớn - Hệ điều hành , 2019 - 2020 Trang 6/9 Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 88 core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ 42 43 44 45 46 47 48 49 50 94 $ cd arch/x86/entry/syscalls/ 51 10 95 $ echo "548 64 get_proc_info sys_get_proc_info" » syscall_64.tbl 52 11 53 12 89 bổ sung thành: 90 core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ get_proc_info/ 91 Tiếp theo, bổ sung system call vào system call table: 92 $ pwd 93 ~/kernelbuild/ 96 Câu hỏi: Ý nghĩa thông tin thêm vào system call table (548 64 get_proc_info sys_get_proc_info)? 97 Trả lời: Các system call system call table có định dạng: • 548: (số thứ tự) • 64: : chứa giá trị: "common", "64" hệ thống 64-bit, "x32" hệ thống 32-bit • get proc info: : tên system call • sys get proc info: 98 Tiếp theo, bổ sung system call mói vào file system call header: 99 $ ~/kernelbuild/include/linux/ 100 Mở file syscalls.h bổ sung dòng sau vào trưóc #endif: 101 struct proc_info; 54 55 56 57 58 59 60 61 62 107 $ make -j 63 10 108 $ make modules -j 64 11 109 $ sudo make modules_install 65 12 66 13 67 14 68 15 69 16 70 17 71 18 72 19 102 struct procinfos; 103 asmlinkage long sys_get_proc_info(pid_t pid, struct procinfos *info); 104 Câu hỏi: Ý nghĩa dòng trên? 105 Trả lời: Các dòng bổ sung vào file header (syscalls.h) nhằm mục đích khai báo struct proc_info, procinfos hàm sys_get_proc_info(pid_t pid, struct procinfos *info) 106 Cuối cùng, biên dịch lại kernel khởi động lại hệ thống để áp dụng kernel mói: 110 $ sudo make install 111 $ sudo reboot 3.2 Testing Bài tập lớn - Hệ điều hành , 2019 - 2020 Trang 7/9 Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 73 74 75 76 77 78 79 80 112 Sau khởi động vào kernel mói, tạo chưong trình C nhỏ để kiểm tra system call tích hợp chưa vào kernel hay chưa: 113 114 115 116 #include #include #include #define SIZE 200 117 int main(){ 118 long sys_return_value; 119 unsigned long info[SIZE]; 120 sys_return_value = syscall(548, -1, &info); 121 printf("My student ID: %lu\n", info[0]); 122 return 0; } 123 124 Câu hỏi: Tại chưìng trình cho biết liệu hệ thống chúng tơi có hoạt động hay khơng? 125 Trả lời: Chưìng trình in MSSV thêm vào file sys_get_proc_info.c Nếu không in MSSV, system call thất bại 3.3 Wrapper 126 Mặc dù system call get_proc_info hoạt động đúng, cần phải cải tiến để thuận tiện hìn cho lập trình viên khác Chúng ta cần triển khai C wrapper để dễ dàng sử dụng hìn Để tránh biên dịch kernel lại lần nữa, tạo thư mục khác để lưu trữ mã nguồn cho chưìng trình wapper Trưóc tiên tạo header file chưìng trình wrapper cấu trúc procinfos, proc_info Chúng ta đặt tên cho header file get_proc_info.h chứa nội dung sau: 127 128 129 130 #ifndef _GET_PROC_INFO_H_ #define _GET_PROC_INFO_H_ #include #include 131 struct proc_info { 132 pid_t pid; 133 char name[16]; }; 134 81 82 83 84 85 86 87 88 89 90 10 91 11 92 12 93 13 94 14 95 15 135 140 struct prociníos { 136 long studentlD; 137 struct proc_info proc; 138 struct proc_info parent_proc; 139 struct proc_info oldest_child_proc; }; 141 142 long sys_get_proc_info(pid_t pid, struct prociníos *info); #endif // GET PROC INFO H 143 Câu hỏi: Tại phải định nghĩa lại cấu trúc procinfos proc_info định nghĩa bên kernel? 144 Trả lời: 145 Sau tạo file get_proc_info.c để giữ mã nguồn cho wrapper Nội dung file sau: Bài tập lớn - Hệ điều hành , 2019 - 2020 Trang 8/9 Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 146 147 148 149 #include #include #include #include 150 "get_proc_info.h" long get_proc_info(pid_t return syscall(548, pid, info); 151 pid, struct prociníos *info) } 3.4 Validation 152 Tiếp theo, copy file header get_proc_info.h vào /usr/include: 153 $ sudo cp /usr/include 154 Câu hỏi: Tại root lại đặc quyền? (Ví dụ phải thêm sudo trưdc cp để copy file header sang /usr/include)? 155 Trả lời: thư mục /usr thuộc quền sử hữu root nên cần copy phải đc cho phép root 156 Sau ta biên dịch source code đối tượng chia phép người dùng truy cập system call ta thông qua ứng dụng họ: 157 $ gcc -shared -fpic get_proc_info.c -o libget_proc_info.so 158 Sau biên dịch thành công, copy file libget_proc_info.so sang /usr/lib: 159 $ sudo cp libget_proc_info.so /usr/lib 160 Câu hỏi: Tại ta phải thêm -shared -fpic gcc command? 161 Trả lời: 162 Bưóc cuối để kiểm tra tồn cơng việc, sử dụng chưìng trình sau biên dịch vói tùy chọn get_proc_info option: 163 164 165 166 167 int main() { 168 pid_t mypid = getpid(); 169 printf("PID: %d\n", mypid); 170 struct prociníos info; 171 if(get_proc_info(mypid, &info) == 0) { 172 printf("My student ID: %lu/n", info.studentID); 173 printf("Process with pid or current process: %llu\n", info.proc.pid); 174 printf("Parent %llu\n", info.parent_proc.pid); 175 printf("Oldest childprocess: process: %llu\n", info.oldest_child_proc.pid); #include #include #include #include #include 16 Bài tập lớn - Hệ điều hành , 2019 - 2020 Trang 9/9 { Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 17 Bài tập lớn - Hệ điều hành , 2019 - 2020 Trang 10/9 ... #endif: 10 1 struct proc_info; 54 55 56 57 58 59 60 61 62 10 7 $ make -j 63 10 10 8 $ make modules -j 64 11 10 9 $ sudo make modules_install 65 12 66 13 67 14 68 15 69 16 70 17 71 18 72 19 10 2 struct... #include 16 Bài tập lớn - Hệ điều hành , 2 019 - 2020 Trang 9/9 { Trường Đại học Bách Khoa - Đại học Quốc Gia TP Hồ Chí Minh Khoa Khoa học Kỹ thuật Máy tính 17 Bài tập lớn - Hệ điều hành , 2 019 -... 90 10 91 11 92 12 93 13 94 14 95 15 13 5 14 0 struct prociníos { 13 6 long studentlD; 13 7 struct proc_info proc; 13 8 struct proc_info parent_proc; 13 9 struct proc_info oldest_child_proc; }; 14 1 14 2