├── .gitignore ├── README.md ├── imgs ├── 1-1.png ├── 1-2.png ├── 2-1.png ├── 2-2.png └── 2-3.png ├── project1 ├── Makefile ├── README.md ├── jiffies.c ├── seconds.c └── simple.c ├── project2 ├── .gdb_history ├── Makefile ├── README.md ├── output ├── part2 │ ├── Makefile │ └── pid.c └── simulator.c ├── project3 ├── Driver.java ├── Makefile ├── SortTask.class ├── SumTask.class ├── SumTask.java ├── ThreadPoolExample.java ├── fig4-23.c ├── mergeSortTask.class ├── mergeSortTask.java ├── openmp.c ├── quickSortTask.class ├── quickSortTask.java ├── sort.c ├── test.sh ├── thrd-posix.c └── thrd-win32.c ├── project4 ├── CPU.c ├── Makefile ├── README ├── book.txt ├── cpu.h ├── driver.c ├── list.c ├── list.h ├── peda-session-fcfs.txt ├── peda-session-priority_rr.txt ├── pri-schedule.txt ├── rr-schedule.txt ├── schedule.txt ├── schedule_fcfs.c ├── schedule_priority.c ├── schedule_priority_rr.c ├── schedule_rr.c ├── schedule_sjf.c ├── schedulers.h └── task.h ├── project5 ├── .gdb_history ├── Makefile ├── README ├── client.c ├── procon.c ├── threadpool.c ├── threadpool.h └── threadpool_back.txt ├── project6 ├── Makefile ├── banker ├── banker.c ├── input.txt └── project6.pdf ├── project7 ├── Makefile ├── allocator.c └── allocator.h ├── project8 ├── .gdb_history ├── BACKING_STORE.bin ├── Makefile ├── addresses.txt ├── correct.txt ├── manager ├── manager.c ├── manager.h ├── output.txt └── peda-session-manager.txt └── reports ├── project1.pdf ├── project1.tex ├── project2.pdf ├── project2.tex ├── project3.pdf ├── project3.tex ├── project4.pdf ├── project4.tex ├── project5.pdf ├── project5.tex ├── project6.pdf ├── project6.tex ├── project7.pdf ├── project7.tex ├── project8.pdf └── project8.tex /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | peda* 3 | *.aux 4 | *.log 5 | *.gz 6 | *.ko 7 | *.cmd 8 | *.zip 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Operating System Concepts(10th edition) Projects 2 | > 2019.Spring SJTU CS 307 projects 3 | > Only part of the projects in the book are implemented here 4 | 5 | ## Overview 6 | * Project1: Introduction to linux kernel module 7 | * Project2: Unix shell programming & linux kernel module for task information 8 | * Project3: Multithreaded Sorting Application & Fork-Join Sorting Application 9 | * Project4: Scheduling Algorithms 10 | * Project5: Design a thread pool & producer-consumer problem 11 | * Project6: Banker's algorithm 12 | * Project7: Contiguous Memory Allocation 13 | * Project8: Designing a Virtual Memory Manager 14 | * src: the official downloaded source code(based which you can implement your own algorithm) 15 | -------------------------------------------------------------------------------- /imgs/1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/imgs/1-1.png -------------------------------------------------------------------------------- /imgs/1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/imgs/1-2.png -------------------------------------------------------------------------------- /imgs/2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/imgs/2-1.png -------------------------------------------------------------------------------- /imgs/2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/imgs/2-2.png -------------------------------------------------------------------------------- /imgs/2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/imgs/2-3.png -------------------------------------------------------------------------------- /project1/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += seconds.o simple.o jiffies.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | 9 | test: 10 | sudo dmesg -C 11 | sudo insmod simple.ko 12 | sudo rmmod simple.ko 13 | dmesg 14 | -------------------------------------------------------------------------------- /project1/README.md: -------------------------------------------------------------------------------- 1 | ## Project1: Brief Introduction For Kernel Module 2 | > This part is about some basic knowedge about Linux Kernel Module 3 | ### Features 4 | * *do not execute sequentially*(do not have a main function), use `init` and `exit` instead. 5 | * *do not have automatic cleanup*(resources must be released manually) 6 | * *do not have `printf()` function*, since that is for the user space 7 | * *can be interruppted and* accessed by multiple users at the same time, so consistent behavior must be ensured. 8 | * *more CPU cycles will be assigned to the kernel module * 9 | * *do not have floating-point support* since it is kernel code that uses traps to transitions from integer to fp 10 | 11 | ### Makefile 12 | make -C argument: specify the directory which it will enters(here the source code directory) 13 | make M=$(PWD) (M is the variable to be passed on to the Makefile in -C directory so that it will jump back to current directory) 14 | ### Specify parameters 15 | `module_param(name, type, permission)`(the `type` specifies the type(e.g. charp) and permission can be specified as (S_INUGO)) 16 | ### where to find the output 17 | * `/sys/module/$(moduleName)` 18 | * `/var/log/kern.log` (use `tail -f /var/log/kern.log`) 19 | * `/proc` (simply use `cat /proc/modules | grep simple` to grep the output) 20 | 21 | ## Implementation Tutorial 22 | ### Part A: Hello world! 23 | > source code is available in project1/simple.c 24 | #### Step 1: Basic framework of a LKM 25 |   The simplest version of a LKM only has an entry and exiting point. 26 | ``` C 27 | /* entry point */ 28 | /* in kernel space we don't have functions 29 | printf() which is from user space. We use 30 | printk() instead */ 31 | static int __init simple_init(void){ 32 | printk("Loading module...\n"); 33 | return 0; 34 | } 35 | 36 | static void __exit simple_exit(void){ 37 | printk("Removing module...\n"); 38 | } 39 | 40 | /* specify the entry point and exiting point */ 41 | module_init(simple_init); 42 | module_exit(simple_exit); 43 | ``` 44 | #### Step2: Write a makefile 45 |   We have to write a makefile to get our simple.ko module 46 | ``` shell 47 | # use subtle rule (make will find simple.c automatically) 48 | obj-m += simple.o 49 | # -C specify where the make will go(/lib/modules/...) and M=$(PWD) 50 | # means that make will come back to currect directory once it finishes 51 | # compiling in /lib/modules/... 52 | all: 53 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 54 | 55 | clean: 56 | $(RM) simple.o simple.ko 57 | ``` 58 | 59 | #### Step3: Using kernel space variables and functions 60 | ``` C 61 | #include 62 | #include 63 | ... 64 | static int __init simple_init(void){ 65 | printk("The GOLDEN_RATIO_PRIME value is:%llu\n", GOLDEN_RATIO_PRIME); 66 | printk("Currently the jiffies value is:%lu\n", jiffies); 67 | printk("HZ value is: %d\n", HZ); 68 | return 0; 69 | } 70 | 71 | static void __exit simple_exit(void){ 72 | /* get the maximum common divisor of 3300 and 24 */ 73 | printk("The maximum common divisor of 3300 and 24 is:%lu\n", gcd(3300, 24)); 74 | printk("Currently the jiffies value is %lu\n", jiffies); 75 | } 76 | ... 77 | ``` 78 | 79 | #### Step4: Insert the Module 80 | * Run `make` and compile your module. A common error in this step is that `Can not find directory.... Run make oldconfig to fix it`. This is usually because of incomplete kernel header code. A possible solution(work for me) is to re-install your kernel module(or simply update to another version, this can be done by simply using .deb files in ubuntu). 81 | * `sudo insmod simple.ko` 82 | * You can see your module using `lsmod | grep simple` or `cat /proc/modules | grep simple` 83 | * `sudo rmmod simple`(remove the kernel module) 84 | * Output is as follows(I add some extra logic here and you can refer to the source code) 85 | 86 | ![1-1](../imgs/1-1.png) 87 | 88 | ### Part B: The /proc file system 89 | >   The /proc file system is a “pseudo” file system that exists only in kernel memory and is used primarily for querying various kernel and per-process statistics. Here I only show how to use HZ and jiffies to get the time interval, source code is available at project1/seconds.c 90 | 91 | ``` C 92 | #include 93 | #include 94 | #include 95 | #include 96 | #include 97 | #include 98 | #include 99 | 100 | #define BUFFER_SIZE 128 101 | #define PROC_NAME "seconds" 102 | 103 | static long unsigned int start, end; 104 | 105 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos); 106 | 107 | static struct file_operations proc_ops = { 108 | .owner = THIS_MODULE, 109 | .read = proc_read, 110 | }; 111 | 112 | static int proc_init(void) 113 | { 114 | /* this will create /proc/seconds file */ 115 | proc_create(PROC_NAME, 0666, NULL, &proc_ops); 116 | printk(KERN_INFO "/proc/%s created\n", PROC_NAME); 117 | start = jiffies; 118 | 119 | return 0; 120 | } 121 | 122 | static void proc_exit(void) 123 | { 124 | /* remove the /proc/seconds file */ 125 | remove_proc_entry(PROC_NAME, NULL); 126 | 127 | printk(KERN_INFO "/proc/%s removed\n", PROC_NAME); 128 | } 129 | 130 | /* the function will be called whenever the user use 131 | command cat /proc/seconds or other methods to read /proc/seconds. 132 | Its counterpart is `proc_write`, which will be shown in project2 */ 133 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 134 | { 135 | int rv = 0; 136 | static int completed = 0; 137 | char buffer[BUFFER_SIZE]; 138 | 139 | /* since when user call cat /proc/seconds, 140 | proc_read() function will be called repeated until 141 | it returns 0, we have this logic to return 0 once the data is collected */ 142 | if(completed){ 143 | completed = 0; 144 | return 0; 145 | } 146 | 147 | completed = 1; 148 | 149 | end = jiffies; 150 | rv = sprintf(buffer, "%lus has eplased since creation.\n", (end-start)/HZ); 151 | 152 | /* copy the user space */ 153 | copy_to_user(usr_buf, buffer, rv); 154 | return rv; 155 | } 156 | 157 | module_init(proc_init); 158 | module_exit(proc_exit); 159 | 160 | MODULE_LICENSE("GPL"); 161 | MODULE_DESCRIPTION("Jiffies module"); 162 | MODULE_AUTHOR("Junjie Wang"); 163 | ``` 164 |   Output is as follows: 165 | 166 | ![1-2](../imgs/1-2.png) 167 | -------------------------------------------------------------------------------- /project1/jiffies.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: jiffies.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月20日 星期一 22时47分39秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define BUFFER_SIZE 128 19 | #define PROC_NAME "jiffies" 20 | 21 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos); 22 | 23 | static struct file_operations proc_ops = { 24 | .owner = THIS_MODULE, 25 | .read = proc_read, 26 | }; 27 | 28 | static int proc_init(void) 29 | { 30 | proc_create(PROC_NAME, 0666, NULL, &proc_ops); 31 | printk(KERN_INFO "/proc/%s created\n", PROC_NAME); 32 | 33 | return 0; 34 | } 35 | 36 | static void proc_exit(void) 37 | { 38 | remove_proc_entry(PROC_NAME, NULL); 39 | 40 | printk(KERN_INFO "/proc/%s removed\n", PROC_NAME); 41 | } 42 | 43 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 44 | { 45 | int rv = 0; 46 | static int completed = 0; 47 | char buffer[BUFFER_SIZE]; 48 | 49 | if(completed){ 50 | completed = 0; 51 | return 0; 52 | } 53 | 54 | completed = 1; 55 | 56 | rv = sprintf(buffer, "Currently jiffies value is:%lu\n", jiffies); 57 | 58 | copy_to_user(usr_buf, buffer, rv); 59 | return rv; 60 | } 61 | 62 | module_init(proc_init); 63 | module_exit(proc_exit); 64 | 65 | MODULE_LICENSE("GPL"); 66 | MODULE_DESCRIPTION("Jiffies module"); 67 | MODULE_AUTHOR("Junjie Wang"); 68 | -------------------------------------------------------------------------------- /project1/seconds.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: jiffies.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月20日 星期一 22时47分39秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define BUFFER_SIZE 128 19 | #define PROC_NAME "seconds" 20 | 21 | static long unsigned int start; 22 | 23 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos); 24 | 25 | static struct file_operations proc_ops = { 26 | .owner = THIS_MODULE, 27 | .read = proc_read, 28 | }; 29 | 30 | static int proc_init(void) 31 | { 32 | proc_create(PROC_NAME, 0666, NULL, &proc_ops); 33 | printk(KERN_INFO "/proc/%s created\n", PROC_NAME); 34 | start = jiffies; 35 | 36 | return 0; 37 | } 38 | 39 | static void proc_exit(void) 40 | { 41 | remove_proc_entry(PROC_NAME, NULL); 42 | 43 | printk(KERN_INFO "/proc/%s removed\n", PROC_NAME); 44 | } 45 | 46 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 47 | { 48 | int rv = 0; 49 | static int completed = 0; 50 | char buffer[BUFFER_SIZE]; 51 | 52 | if(completed){ 53 | completed = 0; 54 | return 0; 55 | } 56 | 57 | completed = 1; 58 | 59 | rv = sprintf(buffer, "%lus has eplased since creation.\n", (jiffies-start)/HZ); 60 | 61 | copy_to_user(usr_buf, buffer, rv); 62 | return rv; 63 | } 64 | 65 | module_init(proc_init); 66 | module_exit(proc_exit); 67 | 68 | MODULE_LICENSE("GPL"); 69 | MODULE_DESCRIPTION("Jiffies module"); 70 | MODULE_AUTHOR("Junjie Wang"); 71 | -------------------------------------------------------------------------------- /project1/simple.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: simple.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: Tue 14 May 2019 07:07:47 PM PDT 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | MODULE_LICENSE("GPL"); 19 | MODULE_DESCRIPTION("simple module"); 20 | MODULE_AUTHOR("Junjie Wang"); 21 | MODULE_VERSION("1.0"); 22 | 23 | static char *name = "JunjieWang"; 24 | /* charp = char PTR S_IRUGO means Read Only */ 25 | module_param(name, charp, S_IRUGO); 26 | MODULE_PARM_DESC(name, "The name is to be displayed in /var/log/kern.log"); 27 | 28 | static int start, end; 29 | 30 | static int __init simple_init(void){ 31 | printk(KERN_INFO "Loading module...\n"); 32 | printk("Hello, %s\n", name); 33 | printk("The GOLDEN_RATIO_PRIME value is:%llu\n", GOLDEN_RATIO_PRIME); 34 | printk("The HZ value: %d\n", HZ); 35 | start = jiffies; 36 | printk("Current jiffies value: %lu\n", jiffies); 37 | /* we must have a return value here */ 38 | return 0; 39 | } 40 | 41 | static void __exit simple_exit(void){ 42 | printk("The gcd result: %lu", gcd(3300, 24)); 43 | end = jiffies; 44 | printk("Current jiffies value: %lu\n", jiffies); 45 | printk("%ds time has elapsed since the insertion.\n", (end-start)/HZ); 46 | printk(KERN_INFO "Removing module...\n"); 47 | printk("Goodbye, %s\n", name); 48 | } 49 | 50 | module_init(simple_init); 51 | module_exit(simple_exit); 52 | 53 | -------------------------------------------------------------------------------- /project2/.gdb_history: -------------------------------------------------------------------------------- 1 | r 2 | ls 3 | l 4 | l 5 | l 6 | l 7 | l 8 | b 38 9 | r 10 | s 11 | s 12 | s 13 | s 14 | q 15 | l 16 | l 17 | l 18 | l 19 | b 38 20 | s 21 | r 22 | s 23 | l 24 | output 25 | print(output) 26 | s 27 | l 28 | s 29 | s 30 | q 31 | -------------------------------------------------------------------------------- /project2/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | SRC_FILE=$(wildcard *.c) 3 | OBJ_FILE=$(patsubst %.c, %.o ,$(SRC_FILE)) 4 | target=simulator 5 | 6 | all : $(target) 7 | 8 | $(target) : $(OBJ_FILE) 9 | $(CC) -o $@ $^ 10 | 11 | $(OBJ_FILE) : $(SRC_FILE) 12 | $(CC) -o $@ -c $^ 13 | 14 | clean: 15 | $(RM) $(target) $(OBJ_FILE) 16 | 17 | -------------------------------------------------------------------------------- /project2/README.md: -------------------------------------------------------------------------------- 1 | ## Project2: Unix-shell programming & LKM for task information 2 | ### Background knowledge 3 |   In this project we will use some C functions in Linux. First I introduce some of them as belows: 4 | ``` C 5 | #include 6 | #include 7 | /* copy the file descriptor. This function will find a minimum 8 | avaiable file descriptor and sets its pointer according to the oldfd(i.e. 9 | the two fd will point to the same file) */ 10 | int dup(int oldfd); 11 | /* just a little different from dup(), dup2() can specify the newfd 12 | we want to use. It the newfd is already opened, this function will first close it and reopen */ 13 | int dup2(int oldfd, int newfd); 14 | 15 | /* exec function family. `file` command will be search in $(PATH) 16 | environment variable and argv need to be the arguments list 17 | example: execvp("ls", {"ls", "-al", NULL})*/ 18 | execvp(const char *file, const char *argv[]); 19 | ... 20 | /* when creating child processes, if the parent process 21 | does not wait until its child exits, the child process will possibly become a zombie. In this case we can use the following 22 | function to ask init process to release the resources of the child process. For more details refer to 23 | https://www.geeksforgeeks.org/zombie-processes-prevention/ */ 24 | signal(SIGCHID, SIG_IGNORE); 25 | ``` 26 | 27 | ### Part A: Unix shell programming 28 | > source code is available in project2/simulator.c 29 | 30 | #### Step1: Main logic and analysis 31 |   Use a while loop(parent process) to read the input and then create a seperate child process the handle this input 32 | ``` C 33 | char *input = malloc(sizeof(char) * MAX_LINE); 34 | 35 | while(should_run){ 36 | printf("osh>"); 37 | fflush(stdout); 38 | 39 | fgets(input, MAX_LINE, stdin); 40 | /* logic to handle the input */ 41 | } 42 | ``` 43 | #### Step2: Create a child process to execute the command 44 | ``` C 45 | /* parse the input string into argument list valid_args */ 46 | pid_t pid; 47 | pid = fork(); 48 | if(pid < 0){ 49 | perror("fork error!\n"); 50 | exit(1); 51 | }else if(pid == 0){ 52 | /* logic for the child process */ 53 | res = execvp(valid_args[0], valid_args); 54 | if(res<0){ 55 | perror("execute error!\n"); 56 | exit(1); 57 | } 58 | } 59 | ``` 60 | ![2-1](../imgs/2-1.png) 61 | #### Step3: handle the '&' 62 |   In terminal we sometimes use the '&' to let the process run in the background. To implement this logic we simply need to modify a little bit about the parent process part 63 | ``` C 64 | if(pid > 0){ 65 | if(wait_flag) wait(NULL); 66 | else signal(SIGCHID, SIG_IGNORE); // prevent zombie 67 | } 68 | ``` 69 | #### Step4: handle redirection 70 |   In terminal we often use the '>' or '<' to redirect the input or output(e.g. ls -al > output, sort < output). When implement this logic, we need to use dup2() function introduced above, closing stdout/stdin and open our own file-descriptor to put/get our results 71 | ``` C 72 | /* parse the input and check whether there is a '<', '>', 73 | get the output file path and then set the flags accordingly 74 | here we take the output redirection as an example */ 75 | int fd = open(output_path, "w"); 76 | if(dup2(fd, 1) < 0) { perror("dup2 error!\n"); exit(1);} 77 | close(fd); 78 | ``` 79 | ![2-2](../imgs/2-2.png) 80 | #### Step5: handle pipeline 81 |   In terminal we often use pipeline "|" to execute our command(e.g. ls -al | sort). To implement this logic, we use the pipe() function, where the write port and read port will be the first command and second command executor accordingly. Also dup() function will be used. 82 | ``` C 83 | /* first parse the input string to get the pipeline flag */ 84 | /* extra logic is also needed to get the arguments of the first 85 | command and second command. Refer to the source code for more details */ 86 | 87 | if(pipeline_flag){ 88 | int ppid; 89 | int fd[2]; 90 | pipe(fd); 91 | ppid = fork(); 92 | if(ppid == 0){ 93 | /* child process of the child process */ 94 | close(0); 95 | /* close the write port */ 96 | close(fd[1]); 97 | dup(fd[0]); 98 | execvp(pipe_args[0], pipe_args); 99 | }else if(ppid > 0){ 100 | /* child process */ 101 | close(1); 102 | /* close the read port */ 103 | close(fd[0]); 104 | dup(fd[1]); 105 | execvp(valid_args[0], valid_args); 106 | } 107 | } 108 | ``` 109 | ![2-3](../imgs/2-3.png) 110 | 111 | #### Reflection and Problems 112 |   There is still some problems in my implementation due to time and ability limitation :-) 113 | * The implementation assumes that there are spaces on the both sides of '|' '<' '>'. Actually this can be solved by simply modify a little about the input parsing part. 114 | * When using '&' or '|', 'osh>' print will be out of order. I have no idea how to solve this problem, though. Any pull request is welcome! 115 | 116 | ### Part B: LKM for task information 117 | > This part will be mostly based on our implementation of project 1 118 | > source code is avaiable at project2/part2/pid.c 119 | 120 |    The main logic here lies in the proc_read() and proc_write() functions. proc_write() function will be called once the user want to write to the /proc/pid file(e.g echo "1234" > /proc/pid)
121 |   Once the user write some pid to the /proc/pid. We get the input and use pid_task(find_vpid(l_pid), PIDTYPE_PID) function to get corresponding task(refer to linux/sched.h for more details). And then once the user call proc_read(), we display the tsk->comm, tsk->state, tsk->pid. Note that logic for false pid need to be offered. 122 | ``` C 123 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 124 | { 125 | int rv = 0; 126 | char buffer[BUFFER_SIZE]; 127 | static int completed = 0; 128 | struct task_struct *tsk = NULL; 129 | 130 | if (completed) { 131 | completed = 0; 132 | return 0; 133 | } 134 | 135 | tsk = pid_task(find_vpid(l_pid), PIDTYPE_PID); 136 | 137 | completed = 1; 138 | 139 | /* return 0 if no this pid */ 140 | if( tsk == NULL) return 0; 141 | else rv = sprintf(buffer, "command = %s pid = %d state = %ld\n", tsk->comm, tsk->pid, tsk->state); 142 | 143 | // copies the contents of kernel buffer to userspace usr_buf 144 | if (copy_to_user(usr_buf, buffer, rv)) { 145 | rv = -1; 146 | } 147 | 148 | return rv; 149 | } 150 | 151 | /** 152 | * This function is called each time we write to the /proc file system. 153 | */ 154 | static ssize_t proc_write(struct file *file, const char __user *usr_buf, size_t count, loff_t *pos) 155 | { 156 | char *k_mem; 157 | 158 | // allocate kernel memory 159 | k_mem = kmalloc(count, GFP_KERNEL); 160 | 161 | /* copies user space usr_buf to kernel buffer */ 162 | if (copy_from_user(k_mem, usr_buf, count)) { 163 | printk( KERN_INFO "Error copying from user\n"); 164 | return -1; 165 | } 166 | 167 | /** 168 | * kstrol() will not work because the strings are not guaranteed 169 | * to be null-terminated. 170 | * 171 | * sscanf() must be used instead. 172 | */ 173 | sscanf(k_mem, "%ld", &l_pid); 174 | 175 | kfree(k_mem); 176 | 177 | return count; 178 | } 179 | 180 | ``` 181 | -------------------------------------------------------------------------------- /project2/output: -------------------------------------------------------------------------------- 1 | 总用量 60 2 | drwxrwxr-x 3 dreamboy dreamboy 4096 5月 23 13:48 . 3 | drwxrwxr-x 14 dreamboy dreamboy 4096 5月 23 13:43 .. 4 | -rw------- 1 dreamboy dreamboy 84 5月 15 20:17 .gdb_history 5 | -rw-rw-r-- 1 dreamboy dreamboy 236 5月 15 20:44 Makefile 6 | -rw-r--r-- 1 dreamboy dreamboy 0 5月 23 14:26 output 7 | drwxrwxr-x 3 dreamboy dreamboy 4096 5月 23 10:08 part2 8 | -rw-rw-r-- 1 dreamboy dreamboy 6583 5月 22 22:08 README.md 9 | -rwxrwxr-x 1 dreamboy dreamboy 13856 5月 23 13:48 simulator 10 | -rw-rw-r-- 1 dreamboy dreamboy 8150 5月 23 12:33 simulator.c 11 | -rw-rw-r-- 1 dreamboy dreamboy 8064 5月 23 13:48 simulator.o 12 | -------------------------------------------------------------------------------- /project2/part2/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += pid.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | 9 | test: 10 | sudo dmesg -C 11 | sudo insmod simple.ko 12 | sudo rmmod simple.ko 13 | dmesg 14 | -------------------------------------------------------------------------------- /project2/part2/pid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Kernel module that communicates with /proc file system. 3 | * 4 | * This provides the base logic for Project 2 - displaying task information 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define BUFFER_SIZE 128 18 | #define PROC_NAME "pid" 19 | 20 | /* the current pid */ 21 | static long l_pid; 22 | 23 | /** 24 | * Function prototypes 25 | */ 26 | static ssize_t proc_read(struct file *file, char *buf, size_t count, loff_t *pos); 27 | static ssize_t proc_write(struct file *file, const char __user *usr_buf, size_t count, loff_t *pos); 28 | 29 | static struct file_operations proc_ops = { 30 | .owner = THIS_MODULE, 31 | .read = proc_read, 32 | .write = proc_write, 33 | }; 34 | 35 | /* This function is called when the module is loaded. */ 36 | static int proc_init(void) 37 | { 38 | // creates the /proc/procfs entry 39 | proc_create(PROC_NAME, 0666, NULL, &proc_ops); 40 | 41 | printk(KERN_INFO "/proc/%s created\n", PROC_NAME); 42 | 43 | return 0; 44 | } 45 | 46 | /* This function is called when the module is removed. */ 47 | static void proc_exit(void) 48 | { 49 | // removes the /proc/procfs entry 50 | remove_proc_entry(PROC_NAME, NULL); 51 | 52 | printk( KERN_INFO "/proc/%s removed\n", PROC_NAME); 53 | } 54 | 55 | /** 56 | * This function is called each time the /proc/pid is read. 57 | * 58 | * This function is called repeatedly until it returns 0, so 59 | * there must be logic that ensures it ultimately returns 0 60 | * once it has collected the data that is to go into the 61 | * corresponding /proc file. 62 | */ 63 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 64 | { 65 | int rv = 0; 66 | char buffer[BUFFER_SIZE]; 67 | static int completed = 0; 68 | struct task_struct *tsk = NULL; 69 | 70 | if (completed) { 71 | completed = 0; 72 | return 0; 73 | } 74 | 75 | tsk = pid_task(find_vpid(l_pid), PIDTYPE_PID); 76 | 77 | completed = 1; 78 | 79 | /* return 0 if no this pid */ 80 | if( tsk == NULL) return 0; 81 | else rv = sprintf(buffer, "command = %s pid = %d state = %ld\n", tsk->comm, tsk->pid, tsk->state); 82 | 83 | // copies the contents of kernel buffer to userspace usr_buf 84 | if (copy_to_user(usr_buf, buffer, rv)) { 85 | rv = -1; 86 | } 87 | 88 | return rv; 89 | } 90 | 91 | /** 92 | * This function is called each time we write to the /proc file system. 93 | */ 94 | static ssize_t proc_write(struct file *file, const char __user *usr_buf, size_t count, loff_t *pos) 95 | { 96 | char *k_mem; 97 | 98 | // allocate kernel memory 99 | k_mem = kmalloc(count, GFP_KERNEL); 100 | 101 | /* copies user space usr_buf to kernel buffer */ 102 | if (copy_from_user(k_mem, usr_buf, count)) { 103 | printk( KERN_INFO "Error copying from user\n"); 104 | return -1; 105 | } 106 | 107 | /** 108 | * kstrol() will not work because the strings are not guaranteed 109 | * to be null-terminated. 110 | * 111 | * sscanf() must be used instead. 112 | */ 113 | sscanf(k_mem, "%ld", &l_pid); 114 | 115 | kfree(k_mem); 116 | 117 | return count; 118 | } 119 | 120 | /* Macros for registering module entry and exit points. */ 121 | module_init( proc_init ); 122 | module_exit( proc_exit ); 123 | 124 | MODULE_LICENSE("GPL"); 125 | MODULE_DESCRIPTION("Module"); 126 | MODULE_AUTHOR("SGG"); 127 | 128 | -------------------------------------------------------------------------------- /project2/simulator.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: simulator.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月15日 星期三 14时28分55秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MAX_LINE 80 20 | void *preprocess(char *input); 21 | 22 | int main(){ 23 | char *args[MAX_LINE/2 + 1]; 24 | /* store the history */ 25 | 26 | char *input, *find, *redirect_path; 27 | char *last_input; 28 | int i, last, num_args, res, fd; 29 | /* initialization */ 30 | /* flag for the while loop */ 31 | int should_run = 1; 32 | int wait_flag = 1; 33 | int in_redirect_flag = 0; 34 | int out_redirect_flag = 0; 35 | int pipe_flag = 0; 36 | int pipe_idx = 0; 37 | pid_t pid; 38 | 39 | for(i=0;i"); 49 | fflush(stdout); 50 | 51 | /* we must reset the input to avoid the effect of the last input*/ 52 | for(i=0;i") == 0){ 92 | printf("capture the output redirection...\n"); 93 | out_redirect_flag = 1; 94 | /* get the redirect file */ 95 | for(;input[i] == ' ' && i") == 0) break; 130 | if(strcmp(args[i], "|") == 0 ) continue; 131 | /* store the main args */ 132 | if(i < pipe_idx) valid_args[i] = args[i]; 133 | /* store the pipe args (note that we skip the | char)*/ 134 | else if(i > pipe_idx) pipe_args[i-pipe_idx-1] = args[i]; 135 | } 136 | 137 | /* add NULL to the end */ 138 | valid_args[pipe_idx] = NULL; 139 | pipe_args[num_args - pipe_idx - 1] = NULL; 140 | 141 | /* handle the redirection */ 142 | if(out_redirect_flag){ 143 | fd = open(redirect_path, O_WRONLY | O_TRUNC | O_CREAT, 0644); 144 | if(fd < 0) {perror("open error!"); exit(1);} 145 | /* dup2(oldfd, newfd) (close the stdout) */ 146 | if(dup2(fd, 1) < 0) {perror("dup2 error!"); exit(1);} 147 | close(fd); 148 | }else if(in_redirect_flag){ 149 | fd = open(redirect_path, O_RDONLY, 0644); 150 | if(fd < 0) {perror("open error!"); exit(1);} 151 | /* dup2(oldfd, newfd) (close the stdin) */ 152 | if(dup2(fd, 0) < 0) {perror("dup2 error!");exit(1);} 153 | close(fd); 154 | } 155 | 156 | if(!pipe_flag) res = execvp(valid_args[0], valid_args); 157 | else{ 158 | /* for a cmd1 | cmd2 simple pipeline problem */ 159 | /* we create a child for the child and use IPC between them to finish the pipeline */ 160 | int p[2], ppid; 161 | 162 | pipe(p); 163 | ppid = fork(); 164 | if(ppid < 0) {perror("ppid create error!");exit(1);} 165 | else if(ppid == 0){ 166 | /* for the child of the child process, set it as the executor of the second commmand */ 167 | close(0); 168 | close(p[1]); 169 | if(dup(p[0]) < 0) {perror("dup error!");exit(1);} 170 | res = execvp(pipe_args[0], pipe_args); 171 | if(res < 0) { perror("cmd2 execution error!"); exit(1); } 172 | }else{ 173 | /* for the parent process, it will execute the first command */ 174 | /* close stdout */ 175 | close(1); 176 | /* close one port */ 177 | close(p[0]); 178 | if(dup(p[1]) < 0) {perror("dup error!");exit(1);} 179 | res = execvp(valid_args[0], valid_args); 180 | if(res < 0) { perror("cmd1 execution error!"); exit(1); } 181 | } 182 | } 183 | if(res < 0){ 184 | perror("Execution error!"); 185 | } 186 | }else{ 187 | /* parent process */ 188 | /* if wait: wait the child process 189 | * else use signal to avoid zombie */ 190 | if(wait_flag) wait(NULL); 191 | else signal(SIGCHLD, SIG_IGN); 192 | } 193 | } 194 | return 0; 195 | } 196 | 197 | /* preprocess function for the input */ 198 | void *preprocess(char *input){ 199 | /* first find the '\n', first nonspace and last nonspace */ 200 | int i, enter, first_non_space, last_non_space; 201 | char *output; 202 | first_non_space = 0; 203 | last_non_space = 0; 204 | 205 | output = malloc(sizeof(char) * MAX_LINE); 206 | 207 | for(i=0;i=0 && input[i] == ' ';i--) ; 221 | last_non_space = i; 222 | 223 | /* then trim the space on both sides */ 224 | strcpy(output, input+first_non_space); 225 | output[last_non_space-first_non_space+1] = '\0'; 226 | 227 | input = output; 228 | } 229 | -------------------------------------------------------------------------------- /project3/Driver.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Summation program using exectuors/callable/futures 3 | * 4 | * Figure 4.14 5 | * 6 | * @author Gagne, Galvin, Silberschatz 7 | * Operating System Concepts - Tenth Edition 8 | * Copyright John Wiley & Sons - 2018 9 | */ 10 | 11 | import java.util.concurrent.*; 12 | 13 | class Summation implements Callable 14 | { 15 | private int upper; 16 | 17 | public Summation(int upper) { 18 | this.upper = upper; 19 | } 20 | 21 | public Integer call() { 22 | int sum = 0; 23 | for (int i = 1; i <= upper; i++) 24 | sum += i; 25 | 26 | return new Integer(sum); 27 | } 28 | } 29 | 30 | 31 | public class Driver 32 | { 33 | public static void main(String[] args) { 34 | if (args.length == 1) { 35 | int upper = Integer.parseInt(args[0]); 36 | 37 | ExecutorService pool = Executors.newSingleThreadExecutor(); 38 | Future result = pool.submit(new Summation(upper)); 39 | 40 | try { 41 | System.out.println("sum = " + result.get()); 42 | } 43 | catch (InterruptedException | ExecutionException ie) { } 44 | 45 | pool.shutdown(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /project3/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | LDFLAGS += -lpthread 3 | SRC=sort.c 4 | OBJ=sort.o 5 | TARGET=sort 6 | 7 | all : $(TARGET) 8 | 9 | $(TARGET) : $(OBJ) 10 | $(CC) -o $@ $^ $(LDFLAGS) 11 | 12 | $(OBJ) : $(SRC) 13 | $(CC) -o $@ -c $^ 14 | 15 | clean: 16 | $(RM) $(TARGET) $(OBJ) 17 | -------------------------------------------------------------------------------- /project3/SortTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project3/SortTask.class -------------------------------------------------------------------------------- /project3/SumTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project3/SumTask.class -------------------------------------------------------------------------------- /project3/SumTask.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Fork/join parallelism in Java 3 | * 4 | * Figure 4.18 5 | * 6 | * @author Gagne, Galvin, Silberschatz 7 | * Operating System Concepts - Tenth Edition 8 | * Copyright John Wiley & Sons - 2018 9 | */ 10 | 11 | import java.util.concurrent.*; 12 | 13 | public class SumTask extends RecursiveTask 14 | { 15 | static final int SIZE = 10000; 16 | static final int THRESHOLD = 1000; 17 | 18 | private int begin; 19 | private int end; 20 | private int[] array; 21 | 22 | public SumTask(int begin, int end, int[] array) { 23 | this.begin = begin; 24 | this.end = end; 25 | this.array = array; 26 | } 27 | 28 | protected Integer compute() { 29 | if (end - begin < THRESHOLD) { 30 | // conquer stage 31 | int sum = 0; 32 | for (int i = begin; i <= end; i++) 33 | sum += array[i]; 34 | 35 | return sum; 36 | } 37 | else { 38 | // divide stage 39 | int mid = begin + (end - begin) / 2; 40 | 41 | SumTask leftTask = new SumTask(begin, mid, array); 42 | SumTask rightTask = new SumTask(mid + 1, end, array); 43 | 44 | leftTask.fork(); 45 | rightTask.fork(); 46 | 47 | return rightTask.join() + leftTask.join(); 48 | } 49 | } 50 | 51 | public static void main(String[] args) { 52 | ForkJoinPool pool = new ForkJoinPool(); 53 | int[] array = new int[SIZE]; 54 | 55 | // create SIZE random integers between 0 and 9 56 | java.util.Random rand = new java.util.Random(); 57 | 58 | for (int i = 0; i < SIZE; i++) { 59 | array[i] = rand.nextInt(10); 60 | } 61 | 62 | // use fork-join parallelism to sum the array 63 | SumTask task = new SumTask(0, SIZE-1, array); 64 | 65 | int sum = pool.invoke(task); 66 | 67 | System.out.println("The sum is " + sum); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /project3/ThreadPoolExample.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a Java thread pool. 3 | * 4 | * Figure 4.15 5 | * 6 | * @author Gagne, Galvin, Silberschatz 7 | * Operating System Concepts - Tenth Edition 8 | * Copyright John Wiley & Sons - 2018 9 | */ 10 | 11 | import java.util.concurrent.*; 12 | 13 | class Task implements Runnable 14 | { 15 | public void run() { 16 | System.out.println(Thread.currentThread().getName()); 17 | } 18 | } 19 | 20 | public class ThreadPoolExample 21 | { 22 | public static void main(String[] args) { 23 | int numTasks = Integer.parseInt(args[0].trim()); 24 | 25 | ExecutorService pool = Executors.newCachedThreadPool(); 26 | 27 | for (int i = 0; i < numTasks; i++) 28 | pool.execute(new Task()); 29 | 30 | // The following invovles using a lambda function 31 | // pool.execute( () -> {System.out.println(Thread.currentThread().getName());}); 32 | 33 | pool.shutdown(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /project3/fig4-23.c: -------------------------------------------------------------------------------- 1 | /** 2 | * A pthread program illustrating how to 3 | * create a simple thread and some of the pthread API 4 | * This program implements the summation function where 5 | * the summation operation is run as a separate thread. 6 | * 7 | * Most Unix/Linux/OS X users 8 | * gcc fig4-23.c -lpthread 9 | * 10 | * Figure 4.23 11 | * 12 | * @author Gagne, Galvin, Silberschatz 13 | * Operating System Concepts - Tenth Edition 14 | * Copyright John Wiley & Sons - 2018 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int value = 0; 23 | void *runner(void *param); /* the thread */ 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | pid_t pid; 28 | pthread_t tid; pthread_attr_t attr; 29 | pid = fork(); 30 | 31 | if (pid == 0) { /* child process */ 32 | pthread_attr_init(&attr); 33 | pthread_create(&tid,&attr,runner,NULL); 34 | pthread_join(tid,NULL); 35 | printf("CHILD: value = %d",value); /* LINE C */ 36 | } 37 | else if (pid > 0) { /* parent process */ 38 | wait(NULL); 39 | printf("PARENT: value = %d",value); /* LINE P */ 40 | } 41 | } 42 | 43 | void *runner(void *param) { 44 | value = 5; 45 | pthread_exit(0); 46 | } 47 | -------------------------------------------------------------------------------- /project3/mergeSortTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project3/mergeSortTask.class -------------------------------------------------------------------------------- /project3/mergeSortTask.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.*; 2 | 3 | public class mergeSortTask extends RecursiveAction 4 | { 5 | static final int SIZE = 1000; 6 | static final int THRESHOLD = 10; 7 | 8 | private int begin; 9 | private int end; 10 | private int[] array; 11 | 12 | public mergeSortTask(int begin, int end, int[] array){ 13 | this.begin = begin; 14 | this.end = end; 15 | this.array = array; 16 | } 17 | 18 | protected void merge(int begin, int end, int [] array){ 19 | int mid = (begin+end)/2; 20 | int i=begin, j=mid+1, k=0; 21 | int [] tmp = new int[end-begin+1]; 22 | while(i<=mid && j<=end){ 23 | if(array[i] 1 to see parallel execution of the parallel region. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | /* sequential code */ 21 | 22 | #pragma omp parallel 23 | { 24 | printf("I am a parallel region\n"); 25 | } 26 | 27 | /* sequential code */ 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /project3/quickSortTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project3/quickSortTask.class -------------------------------------------------------------------------------- /project3/quickSortTask.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.*; 2 | 3 | public class quickSortTask extends RecursiveAction 4 | { 5 | static final int SIZE = 1000; 6 | static final int THRESHOLD = 10; 7 | 8 | private int begin; 9 | private int end; 10 | private int[] array; 11 | 12 | public quickSortTask(int begin, int end, int[] array){ 13 | this.begin = begin; 14 | this.end = end; 15 | this.array = array; 16 | } 17 | 18 | @Override 19 | protected void compute(){ 20 | if (end - begin < THRESHOLD){ 21 | /* conquer stage */ 22 | /* use comparison sort to sort the array */ 23 | int min, idx; 24 | for(int i=begin;i= val) high--; 43 | if(low < high) { array[low] = array[high]; low++;} 44 | while(low < high && array[low] <= val) low++; 45 | if(low < high) { array[high] = array[low];high--; } 46 | }while(low!=high); 47 | 48 | array[low] = val; 49 | 50 | /* from the place we put val */ 51 | int mid = low + 1; 52 | quickSortTask left = new quickSortTask(begin, mid - 1, array); 53 | quickSortTask right = new quickSortTask(mid + 1, end, array); 54 | 55 | left.fork(); 56 | right.fork(); 57 | 58 | left.join(); 59 | right.join(); 60 | 61 | } 62 | } 63 | 64 | public static void main(String [] args){ 65 | ForkJoinPool pool = new ForkJoinPool(); 66 | int [] array = new int[SIZE]; 67 | 68 | /* initialize the array */ 69 | java.util.Random rand = new java.util.Random(); 70 | 71 | /* print the input */ 72 | System.out.println("Before sorting, input array is:"); 73 | for(int i=0;i File Name: sort.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 15时04分36秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* sort the list by using multi-thread */ 16 | 17 | /* the size of the list */ 18 | #define LEN 80 19 | #define ARG_LEN 10 20 | 21 | /* for multiple arguments to be passed 22 | * we have to define a struct */ 23 | typedef struct _param{ 24 | int start; 25 | int end; 26 | } funcParam; 27 | 28 | /* sort thread */ 29 | void *sortThread(void *param); 30 | /* merge thread */ 31 | void *mergeThread(void *param); 32 | /* input array */ 33 | int *in_arr; 34 | /* output array */ 35 | int *out_arr; 36 | 37 | int main(int argc, char *argv[]){ 38 | int i, mid = LEN >> 1; 39 | pthread_t tid[3]; 40 | pthread_attr_t attr[3]; 41 | /* arguments */ 42 | funcParam params[2]; 43 | /* allocate the space and initilize the in_array */ 44 | in_arr = malloc(sizeof(int) * LEN); 45 | out_arr = malloc(sizeof(int) * LEN); 46 | printf("Before sorting, the input array is:\n"); 47 | for(int i=0;i 18 | #include 19 | #include 20 | 21 | int sum; /* this data is shared by the thread(s) */ 22 | 23 | void *runner(void *param); /* the thread */ 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | pthread_t tid; /* the thread identifier */ 28 | pthread_attr_t attr; /* set of attributes for the thread */ 29 | 30 | if (argc != 2) { 31 | fprintf(stderr,"usage: a.out \n"); 32 | /*exit(1);*/ 33 | return -1; 34 | } 35 | 36 | if (atoi(argv[1]) < 0) { 37 | fprintf(stderr,"Argument %d must be non-negative\n",atoi(argv[1])); 38 | /*exit(1);*/ 39 | return -1; 40 | } 41 | 42 | /* get the default attributes */ 43 | pthread_attr_init(&attr); 44 | 45 | /* create the thread */ 46 | pthread_create(&tid,&attr,runner,argv[1]); 47 | 48 | /* now wait for the thread to exit */ 49 | pthread_join(tid,NULL); 50 | 51 | printf("sum = %d\n",sum); 52 | } 53 | 54 | /** 55 | * The thread will begin control in this function 56 | */ 57 | void *runner(void *param) 58 | { 59 | int i, upper = atoi(param); 60 | sum = 0; 61 | 62 | if (upper > 0) { 63 | for (i = 1; i <= upper; i++) 64 | sum += i; 65 | } 66 | 67 | pthread_exit(0); 68 | } 69 | -------------------------------------------------------------------------------- /project3/thrd-win32.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This program creates a separate thread using the CreateThread() system call. 3 | * 4 | * Figure 4.13 5 | * 6 | * @author Gagne, Galvin, Silberschatz 7 | * Operating System Concepts - Tenth Edition 8 | * Copyright John Wiley & Sons - 2018 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | 15 | DWORD Sum; /* data is shared by the thread(s) */ 16 | 17 | /* the thread runs in this separate function */ 18 | DWORD WINAPI Summation(PVOID Param) 19 | { 20 | DWORD Upper = *(DWORD *)Param; 21 | 22 | for (DWORD i = 0; i <= Upper; i++) 23 | Sum += i; 24 | 25 | 26 | 27 | return 0; 28 | } 29 | 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | DWORD ThreadId; 34 | HANDLE ThreadHandle; 35 | int Param; 36 | 37 | // do some basic error checking 38 | if (argc != 2) { 39 | fprintf(stderr,"An integer parameter is required\n"); 40 | return -1; 41 | } 42 | 43 | Param = atoi(argv[1]); 44 | 45 | if (Param < 0) { 46 | fprintf(stderr, "an integer >= 0 is required \n"); 47 | return -1; 48 | } 49 | 50 | // create the thread 51 | ThreadHandle = CreateThread(NULL, 0, Summation, &Param, 0, &ThreadId); 52 | 53 | if (ThreadHandle != NULL) { 54 | WaitForSingleObject(ThreadHandle, INFINITE); 55 | CloseHandle(ThreadHandle); 56 | printf("sum = %d\n",Sum); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /project4/CPU.c: -------------------------------------------------------------------------------- 1 | /** 2 | * "Virtual" CPU that also maintains track of system time. 3 | */ 4 | 5 | #include 6 | 7 | #include "task.h" 8 | 9 | // run this task for the specified time slice 10 | void run(Task *task, int slice) { 11 | printf("Running task = [%s] [%d] [%d] for %d units.\n",task->name, task->priority, task->burst, slice); 12 | } 13 | -------------------------------------------------------------------------------- /project4/Makefile: -------------------------------------------------------------------------------- 1 | # makefile for scheduling program 2 | # 3 | # make rr - for round-robin scheduling 4 | # make fcfs - for FCFS scheduling 5 | # make sjf - for SJF scheduling 6 | # make priority - for priority scheduling 7 | # make priority_rr - for priority with round robin scheduling 8 | 9 | CC=gcc 10 | CFLAGS=-Wall -g 11 | 12 | clean: 13 | rm -rf *.o 14 | rm -rf fcfs 15 | rm -rf sjf 16 | rm -rf rr 17 | rm -rf priority 18 | rm -rf priority_rr 19 | 20 | rr: driver.o list.o CPU.o schedule_rr.o 21 | $(CC) $(CFLAGS) -o rr driver.o schedule_rr.o list.o CPU.o 22 | 23 | sjf: driver.o list.o CPU.o schedule_sjf.o 24 | $(CC) $(CFLAGS) -o sjf driver.o schedule_sjf.o list.o CPU.o 25 | 26 | fcfs: driver.o list.o CPU.o schedule_fcfs.o 27 | $(CC) $(CFLAGS) -g -o fcfs driver.o schedule_fcfs.o list.o CPU.o 28 | 29 | priority: driver.o list.o CPU.o schedule_priority.o 30 | $(CC) $(CFLAGS) -o priority driver.o schedule_priority.o list.o CPU.o 31 | 32 | schedule_fcfs.o: schedule_fcfs.c 33 | $(CC) $(CFLAGS) -c schedule_fcfs.c 34 | 35 | priority_rr: driver.o list.o CPU.o schedule_priority_rr.o 36 | $(CC) $(CFLAGS) -o priority_rr driver.o schedule_priority_rr.o list.o CPU.o 37 | 38 | driver.o: driver.c 39 | $(CC) $(CFLAGS) -c driver.c 40 | 41 | schedule_sjf.o: schedule_sjf.c 42 | $(CC) $(CFLAGS) -c schedule_sjf.c 43 | 44 | schedule_priority.o: schedule_priority.c 45 | $(CC) $(CFLAGS) -c schedule_priority.c 46 | 47 | schedule_rr.o: schedule_rr.c 48 | $(CC) $(CFLAGS) -c schedule_rr.c 49 | 50 | list.o: list.c list.h 51 | $(CC) $(CFLAGS) -c list.c 52 | 53 | CPU.o: CPU.c cpu.h 54 | $(CC) $(CFLAGS) -c CPU.c 55 | 56 | test: 57 | make fcfs 58 | make rr 59 | make sjf 60 | make priority 61 | make priority_rr 62 | -------------------------------------------------------------------------------- /project4/README: -------------------------------------------------------------------------------- 1 | Completing this project will require writing the following C files: 2 | 3 | schedule_fcfs.c 4 | schedule_sjf.c 5 | schedule_rr.c 6 | schedule_priority.c 7 | schedule_priority_rr.c 8 | 9 | The supporting files invoke the appropriate scheduling algorithm. 10 | 11 | For example, to build the FCFS scheduler, enter 12 | 13 | make fcfs 14 | 15 | which builds the fcfs executable file. 16 | -------------------------------------------------------------------------------- /project4/book.txt: -------------------------------------------------------------------------------- 1 | P1, 4, 5 2 | P2, 1, 3 3 | P3, 2, 1 4 | P4, 2, 7 5 | P5, 3, 4 6 | -------------------------------------------------------------------------------- /project4/cpu.h: -------------------------------------------------------------------------------- 1 | // length of a time quantum 2 | #define QUANTUM 10 3 | 4 | // run the specified task for the following time slice 5 | void run(Task *task, int slice); 6 | -------------------------------------------------------------------------------- /project4/driver.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Driver.c 3 | * 4 | * Schedule is in the format 5 | * 6 | * [name] [priority] [CPU burst] 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "task.h" 14 | #include "list.h" 15 | #include "schedulers.h" 16 | 17 | #define SIZE 100 18 | 19 | struct node **head; 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | FILE *in; 24 | char *temp; 25 | char task[SIZE]; 26 | 27 | char *name; 28 | int priority; 29 | int burst; 30 | 31 | head = malloc(sizeof(struct node *)); 32 | in = fopen(argv[1],"r"); 33 | 34 | while (fgets(task,SIZE,in) != NULL) { 35 | temp = strdup(task); 36 | name = strsep(&temp,","); 37 | priority = atoi(strsep(&temp,",")); 38 | burst = atoi(strsep(&temp,",")); 39 | 40 | // add the task to the scheduler's list of tasks 41 | add(name,priority,burst); 42 | 43 | free(temp); 44 | } 45 | 46 | fclose(in); 47 | 48 | // invoke the scheduler 49 | schedule(); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /project4/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Various list operations 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "list.h" 10 | #include "task.h" 11 | 12 | 13 | // add a new task to the list of tasks 14 | void insert(struct node **head, Task *newTask) { 15 | // add the new task to the list 16 | struct node *newNode = malloc(sizeof(struct node)); 17 | 18 | newNode->task = newTask; 19 | newNode->next = *head; 20 | *head = newNode; 21 | } 22 | 23 | // delete the selected task from the list 24 | void delete(struct node **head, Task *task) { 25 | struct node *temp; 26 | struct node *prev; 27 | 28 | temp = *head; 29 | // special case - beginning of list 30 | if (strcmp(task->name,temp->task->name) == 0) { 31 | *head = (*head)->next; 32 | } 33 | else { 34 | // interior or last element in the list 35 | prev = *head; 36 | temp = temp->next; 37 | while (strcmp(task->name,temp->task->name) != 0) { 38 | prev = temp; 39 | temp = temp->next; 40 | } 41 | 42 | prev->next = temp->next; 43 | } 44 | } 45 | 46 | // traverse the list 47 | void traverse(struct node *head) { 48 | struct node *temp; 49 | temp = head; 50 | 51 | while (temp != NULL) { 52 | printf("[%s] [%d] [%d]\n",temp->task->name, temp->task->priority, temp->task->burst); 53 | temp = temp->next; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /project4/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * list data structure containing the tasks in the system 3 | */ 4 | 5 | #include "task.h" 6 | 7 | struct node { 8 | Task *task; 9 | struct node *next; 10 | }; 11 | 12 | // insert and delete operations. 13 | void insert(struct node **head, Task *task); 14 | void delete(struct node **head, Task *task); 15 | void traverse(struct node *head); 16 | -------------------------------------------------------------------------------- /project4/peda-session-fcfs.txt: -------------------------------------------------------------------------------- 1 | break /home/dreamboy/OSProjects/src/osc10e/ch5/project/posix/driver.c:31 2 | 3 | -------------------------------------------------------------------------------- /project4/peda-session-priority_rr.txt: -------------------------------------------------------------------------------- 1 | break /home/dreamboy/OSProjects/src/osc10e/ch5/project/posix/driver.c:49 2 | 3 | -------------------------------------------------------------------------------- /project4/pri-schedule.txt: -------------------------------------------------------------------------------- 1 | T1, 1, 50 2 | T2, 1, 50 3 | T3, 1, 50 4 | T4, 1, 50 5 | T5, 1, 50 6 | T6, 1, 50 7 | -------------------------------------------------------------------------------- /project4/rr-schedule.txt: -------------------------------------------------------------------------------- 1 | T1, 40, 50 2 | T2, 40, 50 3 | T3, 40, 50 4 | T4, 40, 50 5 | T5, 40, 50 6 | T6, 40, 50 7 | -------------------------------------------------------------------------------- /project4/schedule.txt: -------------------------------------------------------------------------------- 1 | T1, 4, 20 2 | T2, 3, 25 3 | T3, 3, 25 4 | T4, 5, 15 5 | T5, 5, 20 6 | T6, 1, 10 7 | T7, 3, 30 8 | T8, 10, 25 9 | -------------------------------------------------------------------------------- /project4/schedule_fcfs.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: schedule_fcfs.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 21时52分30秒 8 | ************************************************************************/ 9 | 10 | /* implement the first in first out algorithm */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "task.h" 16 | #include "list.h" 17 | #include "cpu.h" 18 | #include "schedulers.h" 19 | 20 | extern struct node **head; 21 | 22 | void add(char *name, int priority, int burst){ 23 | Task *task; 24 | task = malloc(sizeof(Task)); 25 | task->name = malloc(sizeof(char)*20); 26 | strcpy(task->name, name); 27 | task->priority = priority; 28 | task->burst = burst; 29 | insert(head, task); 30 | } 31 | 32 | void schedule(){ 33 | struct node **p; 34 | p = malloc(sizeof(struct node *)); 35 | while((*head)->next != NULL){ 36 | *p = *head; 37 | while((*p)->next != NULL) *p = (*p) -> next; 38 | run((*p)->task, (*p)->task->burst); 39 | delete(head, (*p)->task); 40 | } 41 | run((*head)->task, (*head)->task->burst); 42 | 43 | free(p); 44 | } 45 | -------------------------------------------------------------------------------- /project4/schedule_priority.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: schedule_fcfs.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 21时52分30秒 8 | ************************************************************************/ 9 | 10 | /* implement the first in first out algorithm */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "task.h" 16 | #include "list.h" 17 | #include "cpu.h" 18 | #include "schedulers.h" 19 | 20 | extern struct node **head; 21 | 22 | void add(char *name, int priority, int burst){ 23 | Task *task; 24 | task = malloc(sizeof(Task)); 25 | task->name = malloc(sizeof(char)*20); 26 | strcpy(task->name, name); 27 | task->priority = priority; 28 | task->burst = burst; 29 | insert(head, task); 30 | } 31 | 32 | void schedule(){ 33 | int priority = 0; 34 | Task *task = malloc(sizeof(task)); 35 | struct node **p = malloc(sizeof(struct node *)); 36 | while((*head)->next != NULL){ 37 | *p = *head; 38 | task = (*p) -> task; 39 | priority = task -> priority; 40 | while((*p)->next != NULL){ 41 | (*p) = (*p) -> next; 42 | if((*p) -> task -> priority > priority) 43 | task = (*p) -> task; 44 | priority = task -> priority; 45 | } 46 | run(task, task->burst); 47 | delete(head, task); 48 | } 49 | run((*head)->task, (*head)->task->burst); 50 | delete(head, (*head)->task); 51 | free(task); free(p); 52 | free(head); 53 | } 54 | -------------------------------------------------------------------------------- /project4/schedule_priority_rr.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: schedule_fcfs.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 21时52分30秒 8 | ************************************************************************/ 9 | 10 | /* implement the first in first out algorithm */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "task.h" 16 | #include "list.h" 17 | #include "cpu.h" 18 | #include "schedulers.h" 19 | 20 | #define RR_TIME 10 21 | extern struct node **head; 22 | 23 | void add(char *name, int priority, int burst){ 24 | Task *task; 25 | task = malloc(sizeof(Task)); 26 | task->name = malloc(sizeof(char)*20); 27 | strcpy(task->name, name); 28 | task->priority = priority; 29 | task->burst = burst; 30 | insert(head, task); 31 | } 32 | 33 | void schedule(){ 34 | /* implement the priority round robin schedule algorithm 35 | * first reverse the list */ 36 | struct node **headNew = malloc(sizeof(struct node *)); 37 | /* must maually set it to NULL */ 38 | *headNew = NULL; 39 | 40 | /* a very strange thing 41 | * when using the headNew which was malloc in main, *headNew = NULL 42 | * but when using the headNew here, *headNew != NULL */ 43 | Task *task = malloc(sizeof(Task)); 44 | struct node *newNode; 45 | struct node **p = malloc(sizeof(struct node *)); 46 | while((*head)->next!=NULL){ 47 | task = (*head) -> task; 48 | newNode = malloc(sizeof(struct node)); 49 | newNode -> task = task; 50 | newNode -> next = *headNew; 51 | *headNew = newNode; 52 | *head = (*head)-> next; 53 | } 54 | task = (*head) -> task; 55 | newNode = malloc(sizeof(struct node)); 56 | newNode -> task = task; 57 | newNode -> next = *headNew; 58 | *headNew = newNode; 59 | 60 | /* implement the priority RR based on the headNew 61 | * first use an array to store the priority counts */ 62 | *p = *headNew; 63 | int counts[MAX_PRIORITY+1], i; 64 | for(i=0;i<=MAX_PRIORITY;i++) counts[i] = 0; 65 | while((*p)->next != NULL){ 66 | task = (*p) -> task; 67 | counts[task->priority]++; 68 | *p = (*p) -> next; 69 | } 70 | 71 | i = MAX_PRIORITY; 72 | while(1){ 73 | for(;counts[i] == 0 && i>0; i--) ; 74 | if(i == 0) break; 75 | 76 | if(counts[i] == 1){ 77 | /* with only one task, we just execute it */ 78 | *p = *headNew; 79 | while((*p)->next != NULL){ 80 | if((*p) -> task -> priority == i){ 81 | run((*p)->task, (*p)->task->burst); 82 | delete(headNew, (*p)->task); 83 | break; 84 | } 85 | *p = (*p) -> next; 86 | } 87 | counts[i] = 0; 88 | }else{ 89 | /* with more than one task, we use the round robin */ 90 | *p = *headNew; 91 | while(counts[i]>0){ 92 | if((*p)->task->priority == i){ 93 | task = (*p) -> task; 94 | if(task->burst <= RR_TIME){ 95 | /* with time less than the limit */ 96 | run(task, task->burst); 97 | /* move on */ 98 | delete(headNew, task); 99 | counts[i]--; 100 | }else{ 101 | /* with time more than the Q */ 102 | run(task, RR_TIME); 103 | task->burst -= RR_TIME; 104 | } 105 | } 106 | if((*p)->next == NULL) *p = *headNew; 107 | else *p = (*p) -> next; 108 | } 109 | } 110 | } 111 | free(newNode); 112 | free(headNew); 113 | free(p); 114 | free(task); 115 | } 116 | -------------------------------------------------------------------------------- /project4/schedule_rr.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: schedule_fcfs.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 21时52分30秒 8 | ************************************************************************/ 9 | 10 | /* implement the first in first out algorithm */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "task.h" 16 | #include "list.h" 17 | #include "cpu.h" 18 | #include "schedulers.h" 19 | 20 | #define RR_TIME 10 21 | extern struct node **head; 22 | 23 | void add(char *name, int priority, int burst){ 24 | Task *task; 25 | task = malloc(sizeof(Task)); 26 | task->name = malloc(sizeof(char)*20); 27 | strcpy(task->name, name); 28 | task->priority = priority; 29 | task->burst = burst; 30 | insert(head, task); 31 | } 32 | 33 | void schedule(){ 34 | /* implement the round robin schedule algorithm 35 | * first reverse the list */ 36 | struct node **headNew = malloc(sizeof(struct node *)); 37 | /* must maually set it to NULL */ 38 | *headNew = NULL; 39 | 40 | /* a very strange thing 41 | * when using the headNew which was malloc in main, *headNew = NULL 42 | * but when using the headNew here, *headNew != NULL */ 43 | Task *task = malloc(sizeof(Task)); 44 | struct node *newNode; 45 | struct node **p = malloc(sizeof(struct node *)); 46 | while((*head)->next!=NULL){ 47 | task = (*head) -> task; 48 | newNode = malloc(sizeof(struct node)); 49 | newNode -> task = task; 50 | newNode -> next = *headNew; 51 | *headNew = newNode; 52 | *head = (*head)-> next; 53 | } 54 | task = (*head) -> task; 55 | newNode = malloc(sizeof(struct node)); 56 | newNode -> task = task; 57 | newNode -> next = *headNew; 58 | *headNew = newNode; 59 | 60 | traverse(*headNew); 61 | *p = *headNew; 62 | /* now based on the headNew we implement the RR algorithm */ 63 | while(*headNew != NULL){ 64 | task = (*p)->task; 65 | if(task->burst <= RR_TIME){ 66 | /* for this job we can finish */ 67 | run(task, task->burst); 68 | if((*p)->next == NULL) *p = *headNew; 69 | else *p = (*p) -> next; 70 | delete(headNew, task); 71 | }else{ 72 | /* can not finish this task*/ 73 | run(task, RR_TIME); 74 | (*p)->task->burst -= RR_TIME; 75 | if((*p)->next == NULL) *p = *headNew; 76 | else *p = (*p) -> next; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /project4/schedule_sjf.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: schedule_fcfs.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月16日 星期四 21时52分30秒 8 | ************************************************************************/ 9 | 10 | /* implement the first in first out algorithm */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "task.h" 16 | #include "list.h" 17 | #include "cpu.h" 18 | #include "schedulers.h" 19 | 20 | extern struct node **head; 21 | 22 | void add(char *name, int priority, int burst){ 23 | Task *task; 24 | task = malloc(sizeof(Task)); 25 | task->name = malloc(sizeof(char)*20); 26 | strcpy(task->name, name); 27 | task->priority = priority; 28 | task->burst = burst; 29 | insert(head, task); 30 | } 31 | 32 | void schedule(){ 33 | /* implement the SJF schedule algorithm */ 34 | int burst = 0; 35 | Task *task = malloc(sizeof(task)); 36 | struct node **p = malloc(sizeof(struct node *)); 37 | while((*head)->next != NULL){ 38 | *p = *head; 39 | task = (*p) -> task; 40 | burst = task -> burst; 41 | while((*p)->next != NULL){ 42 | (*p) = (*p) -> next; 43 | if((*p) -> task -> burst < burst){ 44 | task = (*p) -> task; 45 | burst = task -> burst; 46 | } 47 | } 48 | run(task, task->burst); 49 | delete(head, task); 50 | } 51 | run((*head)->task, (*head)->task->burst); 52 | delete(head, (*head)->task); 53 | free(p); free(task); 54 | free(head); 55 | } 56 | -------------------------------------------------------------------------------- /project4/schedulers.h: -------------------------------------------------------------------------------- 1 | #define MIN_PRIORITY 1 2 | #define MAX_PRIORITY 10 3 | 4 | // add a task to the list 5 | void add(char *name, int priority, int burst); 6 | 7 | // invoke the scheduler 8 | void schedule(); 9 | -------------------------------------------------------------------------------- /project4/task.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Representation of a task in the system. 3 | */ 4 | 5 | #ifndef TASK_H 6 | #define TASK_H 7 | 8 | // representation of a task 9 | typedef struct task { 10 | char *name; 11 | int tid; 12 | int priority; 13 | int burst; 14 | } Task; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /project5/.gdb_history: -------------------------------------------------------------------------------- 1 | l 2 | l 3 | l 4 | q 5 | -------------------------------------------------------------------------------- /project5/Makefile: -------------------------------------------------------------------------------- 1 | # makefile for thread pool 2 | # 3 | 4 | CC=gcc 5 | CFLAGS=-Wall -g 6 | PTHREADS=-lpthread 7 | 8 | all: client.o threadpool.o 9 | $(CC) $(CFLAGS) -o example client.o threadpool.o $(PTHREADS) 10 | $(CC) $(CFLAGS) -o procon procon.c $(PTHREADS) 11 | 12 | client.o: client.c 13 | $(CC) $(CFLAGS) -c client.c $(PTHREADS) 14 | 15 | threadpool.o: threadpool.c threadpool.h 16 | $(CC) $(CFLAGS) -c threadpool.c $(PTHREADS) 17 | 18 | clean: 19 | rm -rf *.o 20 | rm -rf example 21 | rm -rf procon 22 | 23 | test: 24 | ./example 25 | 26 | procon: 27 | $(CC) $(CFLAGS) -o procon procon.c $(PTHREADS) 28 | -------------------------------------------------------------------------------- /project5/README: -------------------------------------------------------------------------------- 1 | These files support the POSIX implementation of the thread pool project. 2 | 3 | Source files: 4 | 5 | - client.c (client program that uses thread pool) 6 | 7 | - threadpool.c (implementation of thread pool) 8 | 9 | - threadpool.h (header file containing function prototypes) 10 | 11 | Makefile 12 | 13 | To run the make file, enter "make" 14 | 15 | To run the example program, enter "./example" 16 | -------------------------------------------------------------------------------- /project5/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Example client program that uses thread pool. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "threadpool.h" 9 | 10 | struct data 11 | { 12 | int a; 13 | int b; 14 | }; 15 | 16 | void add(void *param) 17 | { 18 | struct data *temp; 19 | temp = (struct data*)param; 20 | 21 | printf("I add two values %d and %d result = %d\n",temp->a, temp->b, temp->a + temp->b); 22 | } 23 | 24 | int main(void) 25 | { 26 | // create some work to do 27 | struct data work[4]; 28 | 29 | // initialize the thread pool 30 | pool_init(); 31 | 32 | /* ensure that all the threads are successfully created */ 33 | sleep(0.5); 34 | // submit the work to the queue 35 | 36 | /* note that for mulitiple test cases 37 | * do not use the same variable work */ 38 | for(int i=0;i File Name: producer_consumer.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月18日 星期六 16时20分04秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define BUFFER_SIZE 10 18 | /* do not create too much producers or consumers */ 19 | #define LIMIT 5 20 | /* type for the items in buffer */ 21 | typedef int bufferItem; 22 | /* pointer/index for the position of the consumer */ 23 | int con_index = 0; 24 | int pro_index = 0; 25 | /* buffer */ 26 | bufferItem buffer[BUFFER_SIZE]; 27 | /* semaphore and mutex */ 28 | sem_t empty, full; 29 | pthread_mutex_t mutex; 30 | 31 | void usage(); 32 | 33 | void insertItem(bufferItem item){ 34 | /* empty == 0 => the buffer is full */ 35 | sem_wait(&empty); 36 | /* use mutex, since multiple producers may 37 | * want to access at the same time */ 38 | pthread_mutex_lock(&mutex); 39 | buffer[pro_index] = item; 40 | pro_index = (pro_index + 1) % BUFFER_SIZE; 41 | pthread_mutex_unlock(&mutex); 42 | sem_post(&full); 43 | } 44 | 45 | bufferItem removeItem(){ 46 | /* full == 0 => the buffer is empty */ 47 | bufferItem item; 48 | sem_wait(&full); 49 | pthread_mutex_lock(&mutex); 50 | item = buffer[con_index]; 51 | con_index = (con_index + 1) % BUFFER_SIZE; 52 | pthread_mutex_unlock(&mutex); 53 | sem_post(&empty); 54 | return item; 55 | } 56 | 57 | void *consumer(void *param){ 58 | /* sleep for random time 59 | * remove an item from the buffer */ 60 | int sleep_time; 61 | int id = *(int *)param; 62 | bufferItem item; 63 | while(1){ 64 | /* avoid endless sleeping */ 65 | sleep_time = rand() % 10; 66 | sleep(sleep_time); 67 | item = removeItem(); 68 | printf("Consumer %d removes item %d.\n", id, item); 69 | } 70 | } 71 | 72 | void *producer(void *param){ 73 | /* sleep for random time 74 | * insert an item into the buffer */ 75 | int sleep_time; 76 | int id = *(int *)param; 77 | bufferItem item; 78 | while(1){ 79 | /* avoid endless sleeping */ 80 | sleep_time = rand() % 10; 81 | sleep(sleep_time); 82 | /* please do not be too large */ 83 | item = rand() % 1000; 84 | insertItem(item); 85 | printf("Producer %d inserts item %d.\n", id, item); 86 | } 87 | } 88 | 89 | int main(int argc, char *argv[]){ 90 | char c; 91 | int num_cons = 0, num_pros = 0; 92 | int sleep_time = 0; 93 | int i; 94 | /* necessary initialization 95 | * note the definition of the empty and full semaphore */ 96 | sem_init(&empty, 0, BUFFER_SIZE); 97 | sem_init(&full, 0, 0); 98 | pthread_mutex_init(&mutex, NULL); 99 | 100 | /* pid and attributes */ 101 | pthread_t con[LIMIT]; pthread_attr_t con_attr[LIMIT]; 102 | pthread_t pro[LIMIT]; pthread_attr_t pro_attr[LIMIT]; 103 | 104 | /* parse the inputs */ 105 | while((c=getopt(argc, argv, "p:c:t:")) != -1){ 106 | switch(c){ 107 | case 'p': 108 | num_pros = atoi(optarg); 109 | break; 110 | case 'c': 111 | num_cons = atoi(optarg); 112 | break; 113 | case 't': 114 | sleep_time = atoi(optarg); 115 | break; 116 | default: 117 | fprintf(stderr, "unrecognized options!\n"); 118 | usage(); 119 | exit(-1); 120 | } 121 | } 122 | 123 | if(num_pros == 0 || num_pros == 0){ 124 | fprintf(stderr, "Invalid arguments!\n"); 125 | usage(); 126 | exit(-1); 127 | } 128 | 129 | if(num_pros > LIMIT || num_cons > LIMIT){ 130 | fprintf(stderr, "Too much consumers or producers!\n"); 131 | usage(); 132 | exit(-1); 133 | } 134 | /* create the consumers */ 135 | for(i=0;i File Name: threadpool.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月18日 星期六 14时14分38秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "threadpool.h" 15 | 16 | Task task; 17 | 18 | struct node *head, *tmp, *newNode; 19 | sem_t sem; 20 | pthread_mutex_t mutex; 21 | pthread_t pid[MAX_THREADS]; 22 | int res, is_shutdown, num_tasks; 23 | 24 | void enqueue(Task task){ 25 | newNode = malloc(sizeof(struct node)); 26 | newNode -> task = task; 27 | newNode -> next = NULL; 28 | if(head == NULL) { 29 | head = newNode; 30 | }else{ 31 | tmp = head; 32 | while(tmp->next != NULL) tmp = tmp->next; 33 | tmp -> next = newNode; 34 | } 35 | } 36 | 37 | Task dequeue(){ 38 | task = head -> task; 39 | tmp = head; 40 | head = head -> next; 41 | free(tmp); 42 | return task; 43 | } 44 | 45 | int pool_submit(void (*somefunction)(void *p), void *p){ 46 | /* submit the task to the pool */ 47 | task.function = somefunction; 48 | task.data = p; 49 | /* lock the mutex, avoid multi access to the queue */ 50 | pthread_mutex_lock(&mutex); 51 | enqueue(task); 52 | num_tasks++; 53 | printf("sucessfully submit the task!\n"); 54 | sem_post(&sem); 55 | pthread_mutex_unlock(&mutex); 56 | 57 | return 0; 58 | } 59 | 60 | void *worker(void *param){ 61 | while(1){ 62 | while(num_tasks == 0 && !is_shutdown){ 63 | printf("waiting for the task...\n"); 64 | sem_wait(&sem); 65 | } 66 | if(is_shutdown){ 67 | printf("The pool has been shut down => threads all exiting...\n"); 68 | pthread_exit(0); 69 | } 70 | /* also lock the mutex */ 71 | pthread_mutex_lock(&mutex); 72 | task = dequeue(); 73 | pthread_mutex_unlock(&mutex); 74 | num_tasks--; 75 | execute(task.function, task.data); 76 | } 77 | } 78 | 79 | void execute(void (*somefunction)(void *p), void *p){ 80 | printf("executing...\n"); 81 | (*somefunction)(p); 82 | printf("finish execution...\n"); 83 | } 84 | 85 | void pool_init(void){ 86 | num_tasks = 0; 87 | is_shutdown = 0; 88 | head = NULL; 89 | pthread_mutex_init(&mutex, NULL); 90 | /* initialize it to 0 */ 91 | sem_init(&sem, 0, 0); 92 | for(int i=0;inext; 101 | free(tmp); 102 | } 103 | printf("shuting down...\n"); 104 | is_shutdown = 1; 105 | /* destroy all the threads */ 106 | for(int i=0;i 6 | #include 7 | #include 8 | #include 9 | #include "threadpool.h" 10 | 11 | #define QUEUE_SIZE 10 12 | #define NUMBER_OF_THREADS 3 13 | 14 | #define TRUE 1 15 | 16 | // this represents work that has to be 17 | // completed by a thread in the pool 18 | typedef struct 19 | { 20 | void (*function)(void *p); 21 | void *data; 22 | } task; 23 | 24 | /* data struct for the 25 | * link list */ 26 | typedef struct 27 | { 28 | task work; 29 | node *prev; 30 | node *next; 31 | } node; 32 | 33 | // the work queue 34 | task worktodo; 35 | 36 | // the worker bee 37 | pthread_t bee[NUMBER_OF_THREADS]; 38 | sem_t sem; 39 | 40 | /* use a bidirectional link list 41 | * to implement the queue */ 42 | node *newNode, *head, *tail, *tmp; 43 | 44 | // insert a task into the queue 45 | // returns 0 if successful or 1 otherwise, 46 | int enqueue(task t) 47 | { 48 | newNode = malloc(sizeof(node)); 49 | newNode -> work = t; 50 | if(head == tail){ 51 | /* special case */ 52 | newNode -> prev = head; 53 | newNode -> next = tail; 54 | head -> next = newNode; 55 | tail -> prev = newNode; 56 | }else{ 57 | tmp = head -> next; 58 | newNode -> next = tmp; 59 | tmp -> prev = newNode; 60 | newNode -> prev = head; 61 | head -> next = newNode; 62 | } 63 | return 0; 64 | } 65 | 66 | // remove a task from the queue 67 | task dequeue() 68 | { 69 | if(head == tail){ 70 | printf("Error! The queue is empty!\n"); 71 | exit(-1); 72 | }else{ 73 | tmp = tail -> prev; 74 | tmp -> prev -> next = tail; 75 | tail -> prev = tmp -> prev; 76 | } 77 | worktodo = tmp -> work; 78 | return worktodo; 79 | } 80 | 81 | // the worker thread in the thread pool 82 | void *worker(void *param) 83 | { 84 | sem_wait(&sem); 85 | worktodo = dequeue(); 86 | // execute the task 87 | execute(worktodo.function, worktodo.data); 88 | sem_post(&sem); 89 | pthread_exit(0); 90 | } 91 | 92 | /** 93 | * Executes the task provided to the thread pool 94 | */ 95 | void execute(void (*somefunction)(void *p), void *p) 96 | { 97 | (*somefunction)(p); 98 | } 99 | 100 | /** 101 | * Submits work to the pool. 102 | */ 103 | int pool_submit(void (*somefunction)(void *p), void *p) 104 | { 105 | worktodo.function = somefunction; 106 | worktodo.data = p; 107 | enqueue(worktodo); 108 | printf("submitted work successfully!\n"); 109 | 110 | return 0; 111 | } 112 | 113 | // initialize the thread pool 114 | void pool_init(void) 115 | { 116 | /* allocate the memory space for the head/tail */ 117 | head = malloc(sizeof(node)); 118 | /* set the tail = head */ 119 | tail = head; 120 | /* initialize the semaphore */ 121 | sem_init(&sem, 0, NUMBER_OF_THREADS); 122 | pthread_create(&bee,NULL,worker,NULL); 123 | } 124 | 125 | // shutdown the thread pool 126 | void pool_shutdown(void) 127 | { 128 | for(int i=0;i < NUMBER_OF_THREADS;i++) 129 | pthread_join(bee[i],NULL); 130 | /* destroy the semaphore */ 131 | sem_destroy(&sem); 132 | free(head); 133 | free(tail); 134 | } 135 | -------------------------------------------------------------------------------- /project6/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | 3 | all: 4 | $(CC) banker.c -o banker 5 | 6 | clean: 7 | $(RM) banker banker.o 8 | -------------------------------------------------------------------------------- /project6/banker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project6/banker -------------------------------------------------------------------------------- /project6/banker.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: banker.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月18日 星期六 18时39分57秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* the file which contains the 17 | * maximum need of each customer */ 18 | #define INPUT_FILEPATH "./input.txt" 19 | #define MAX_LINE_LENGTH 20 20 | 21 | /* we limit the maximum size 22 | * of the customers and resources. 23 | * Acutually in the implementation 24 | * by pointers, they are not needed */ 25 | 26 | #define MAX_CUSTOMERS 10 27 | #define MAX_RESOURCES 5 28 | 29 | /* martices will be used */ 30 | int **maximum; 31 | int **need; 32 | int *available; 33 | int **allocation; 34 | 35 | /* temporary pointer which will be 36 | * used when checing the safe state */ 37 | int **_maximum; 38 | int **_need; 39 | int *_available; 40 | int **_allocation; 41 | 42 | /* the number of customer and resources */ 43 | int num_customers = 0; 44 | int num_resources = 0; 45 | 46 | void initArrays(); 47 | char *preprocess(char *buffer); 48 | void getResources(int argc, char *argv[]); 49 | int judgeLegal(int customerIndex, int *strategy); 50 | void printArrays(); 51 | void handleReleases(char *buffer); 52 | int handleRequest(char *buffer); 53 | int releaseResources(int customerIndex, int *strategy); 54 | void allocateResources(int customerIndex, int *strategy); 55 | int checkSafeWrapper(); 56 | int checkSafe(int *finished); 57 | int findSomeCustomer(int *finished); 58 | int *parseLine(char *buffer); 59 | void destroyArrays(); 60 | 61 | /* implement the banker's algorithm */ 62 | int main(int argc, char *argv[]){ 63 | char *buffer, *find; 64 | /* we will use the buffer to store the input from stdin */ 65 | buffer = malloc(sizeof(char) * MAX_LINE_LENGTH); 66 | initArrays(); 67 | /* get the resources of each type */ 68 | getResources(argc, argv); 69 | if(!checkSafeWrapper()) printf("Warning: current state is unsafe.\n"); 70 | while(1){ 71 | printf("banker>"); 72 | fgets(buffer, MAX_LINE_LENGTH, stdin); 73 | buffer = preprocess(buffer); 74 | if(strcmp(buffer, "exit\n") == 0){ 75 | printf("Bye.\n"); 76 | break; 77 | }else if(buffer[0] == '*'){ 78 | /* output all the arrays */ 79 | printArrays(); 80 | }else if(strncmp(buffer, "RL", 2) == 0){ 81 | /* release the resources */ 82 | handleReleases(buffer); 83 | }else if(strncmp(buffer, "RQ", 2) == 0){ 84 | /* request the resources */ 85 | handleRequest(buffer); 86 | }else{ 87 | /* unrecognized input */ 88 | fprintf(stderr, "unrecognized input!\n"); 89 | } 90 | } 91 | destroyArrays(); 92 | return 0; 93 | } 94 | 95 | /* get the resources of each type */ 96 | void getResources(int argc, char *argv[]){ 97 | if(argc != num_resources + 1){ 98 | fprintf(stderr, "Error! Your input does not match the number of resources!\n"); 99 | exit(-1); 100 | } 101 | for(int i=0;i available[j]) break; 242 | } 243 | if(j == num_resources && !finished[i]) return i; 244 | } 245 | return -1; 246 | } 247 | 248 | /* parse the input(e.g. 7 3 3 4) */ 249 | int* parseLine(char *buffer){ 250 | int i, j=0; 251 | int *arr = malloc(sizeof(int) * (num_resources+1)); 252 | /* get the customer index */ 253 | arr[j++] = (int)(buffer[0]) - (int)('0'); 254 | 255 | for(i=2;i File Name: allocator.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月19日 星期日 09时39分01秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "allocator.h" 14 | 15 | int max_size; 16 | struct node *head, *tail, *newNode; 17 | Block *block, *tmp_block; 18 | /* the number of blocks */ 19 | int num_blocks = 0; 20 | 21 | int main(int argc, char *argv[]){ 22 | if(argc != 2){ 23 | fprintf(stderr, "Error! Insufficient arguments!\n"); 24 | exit(-1); 25 | } 26 | /* initialize */ 27 | head = malloc(sizeof(struct node *)); 28 | tail = malloc(sizeof(struct node *)); 29 | head->next = tail; tail->prev = head; 30 | max_size = atoi(argv[1]); 31 | block = malloc(sizeof(Block)); 32 | newNode = malloc(sizeof(struct node)); 33 | block->start = 0; 34 | block->end = max_size; 35 | block->type = 0; 36 | newNode->block = block; 37 | insertNode(head, tail, newNode); 38 | 39 | char *buffer = malloc(sizeof(char) * MAX_LENGTH); 40 | while(1){ 41 | printf("allocator>"); 42 | fgets(buffer, MAX_LENGTH, stdin); 43 | buffer = preprocess(buffer); 44 | if(buffer[0] == 'X'){ 45 | printf("Bye.\n"); 46 | break; 47 | }else if(buffer[0] == 'C'){ 48 | /* compact */ 49 | //handleCompactSimple(); 50 | handleCompactShuffle(); 51 | }else if(strncmp(buffer, "RQ", 2) == 0){ 52 | /* request the memory, use buffer+3 to get rid of the "RQ" at the beginning */ 53 | handleRequest(buffer+3); 54 | }else if(strncmp(buffer, "RL", 2) == 0){ 55 | /* release the memory to a specific process */ 56 | handleRelease(buffer+3); 57 | }else if(strncmp(buffer, "STAT", 2) == 0){ 58 | /* print out the memory allocation status */ 59 | printStatus(); 60 | }else{ 61 | fprintf(stderr, "Unrecognized input!\n"); 62 | usage(); 63 | } 64 | } 65 | return 0; 66 | } 67 | 68 | void insertNode(struct node *head_p, struct node *tail_p, struct node *newNode){ 69 | if(head_p -> next == tail_p){ 70 | head_p -> next = newNode; 71 | newNode -> prev = head_p; 72 | newNode -> next = tail_p; 73 | tail_p -> prev = newNode; 74 | }else{ 75 | /* insert the node at the end */ 76 | tail_p -> prev -> next = newNode; 77 | newNode -> prev = tail_p -> prev; 78 | tail_p -> prev = newNode; 79 | newNode -> next = tail_p; 80 | } 81 | } 82 | 83 | void splitNode(int size, char *name, struct node *oldNode){ 84 | block = oldNode -> block; 85 | if(block -> end - block -> start == size){ 86 | /* if we have size == end - start, that's perfect */ 87 | strcpy(block->name, name); 88 | block->type = 1; 89 | }else{ 90 | /* else we have to split the node */ 91 | tmp_block = malloc(sizeof(Block)); 92 | newNode = malloc(sizeof(struct node)); 93 | tmp_block -> start = block -> start; 94 | tmp_block -> end = block -> start + size; 95 | block -> start = block -> start + size; 96 | /* since the first one is the allocation 97 | * its type = 1 */ 98 | tmp_block -> type = 1; 99 | /* if use strcpy() function, 100 | * don't forget tmp_block -> name = malloc(...) */ 101 | tmp_block -> name = name; 102 | newNode -> block = tmp_block; 103 | oldNode -> prev -> next = newNode; 104 | newNode -> prev = oldNode -> prev; 105 | newNode -> next = oldNode; 106 | oldNode -> prev = newNode; 107 | } 108 | } 109 | 110 | void printStatus(){ 111 | struct node *p = head->next; 112 | while(p != tail){ 113 | block = p->block; 114 | printf("Addresses\t[%d: %d]\t", block->start , block->end); 115 | if(block->type) printf("Process\t%s\n", block->name); 116 | else printf("Unused\n"); 117 | p = p->next; 118 | } 119 | } 120 | 121 | void handleRequest(char *buffer){ 122 | int size; 123 | char fit_type; 124 | char *name = malloc(sizeof(char) * MAX_LENGTH); 125 | struct node *p = head->next; 126 | sscanf(buffer, "%s %d %c", name, &size, &fit_type); 127 | switch(fit_type){ 128 | case 'F': 129 | { 130 | /* using the first hit strategy */ 131 | while(p!=tail){ 132 | block = p->block; 133 | if(block->type == 0 && block->end - block->start >= size){ 134 | splitNode(size, name, p); 135 | break; 136 | } 137 | p = p->next; 138 | } 139 | if(p == tail) fprintf(stderr, "Error! No space to allocate. You may try compaction fisrt!\n"); 140 | break; 141 | } 142 | case 'B': 143 | { 144 | /* using the best fit strategy 145 | * maintain the min size which 146 | * satisfies our condition */ 147 | int min_hole = max_size + 1; 148 | struct node *best_node; 149 | while(p!=tail){ 150 | block = p->block; 151 | if(block->type == 0 && block->end - block->start >= size){ 152 | if(block->end - block->start <= min_hole){ 153 | min_hole = block->end - block->start; 154 | best_node = p; 155 | } 156 | } 157 | p = p->next; 158 | } 159 | if(min_hole == max_size + 1) fprintf(stderr, "Error! No space to allocate. You may try compaction first!\n"); 160 | else splitNode(size, name, best_node); 161 | break; 162 | } 163 | case 'W': 164 | { 165 | int max_hole = 0; 166 | struct node *largest_node; 167 | while(p!=tail){ 168 | block = p->block; 169 | if(block->type == 0 && block->end - block->start >= size){ 170 | if(block->end - block->start > max_hole){ 171 | max_hole = block->end - block->start; 172 | largest_node = p; 173 | } 174 | } 175 | p = p->next; 176 | } 177 | if(max_hole == 0) fprintf(stderr, "Error! No space to allocate. You may try compaction first!\n"); 178 | else splitNode(size, name, largest_node); 179 | } 180 | } 181 | } 182 | 183 | void handleRelease(char *buffer){ 184 | int idx = 0; 185 | char *name = malloc(sizeof(char) * MAX_LENGTH); 186 | for(;idxnext; 191 | while(p != tail){ 192 | block = p->block; 193 | if(block->type == 1 && strcmp(block->name, name) == 0){ 194 | /* simply set this type to 0 */ 195 | block->type = 0; 196 | /* then check whether we can merge holes */ 197 | printf("test\n"); 198 | mergeHole(p); 199 | } 200 | p = p->next; 201 | } 202 | } 203 | 204 | /* check whether we can merge the node with 205 | * its previous one and its following one */ 206 | void mergeHole(struct node *target){ 207 | newNode = malloc(sizeof(struct node)); 208 | block = malloc(sizeof(Block)); 209 | if(target->prev != head && target->prev->block->type == 0){ 210 | /* merge current one with previous one */ 211 | printf("test1\n"); 212 | block -> start = target -> prev -> block -> start; 213 | block -> end = target -> block -> end; 214 | printf("%d %d\n", block->start, block->end); 215 | block -> type = 0; 216 | newNode -> block = block; 217 | target -> prev -> prev -> next = newNode; 218 | newNode -> prev = target -> prev -> prev; 219 | newNode -> next = target -> next; 220 | target -> next -> prev = newNode; 221 | target = NULL; 222 | } 223 | if(target == NULL) { target = newNode; newNode = malloc(sizeof(struct node)); } 224 | 225 | if(target->next != tail && target->next->block->type == 0){ 226 | /* merge current one with following one */ 227 | printf("test1\n"); 228 | block -> start = target -> block -> start; 229 | block -> end = target -> next -> block -> end; 230 | block -> type = 0; 231 | newNode -> block = block; 232 | target -> next -> next -> prev = newNode; 233 | newNode -> next = target -> next -> next; 234 | target -> prev -> next = newNode; 235 | newNode -> prev = target -> prev; 236 | } 237 | } 238 | 239 | void handleCompactSimple(){ 240 | struct node *p = head->next; 241 | struct node *q = malloc(sizeof(struct node)); 242 | struct node *new_head = malloc(sizeof(struct node)); 243 | struct node *new_tail = malloc(sizeof(struct node)); 244 | new_head -> next = new_tail; new_tail -> prev = new_head; 245 | 246 | /* total size of the holes */ 247 | int sum_holes = 0, idx; 248 | /* first traverse -> get the sum_holes */ 249 | while(p != tail){ 250 | if(p->block->type == 0) sum_holes += p->block->end - p->block->start; 251 | p = p->next; 252 | } 253 | /* allocate a large block at the beginning of q */ 254 | block = malloc(sizeof(Block)); 255 | block->start = 0; 256 | block->end = sum_holes; 257 | block->type = 0; 258 | q -> block = block; 259 | insertNode(new_head, new_tail, q); 260 | /* second traverse, handle the allocation blocks*/ 261 | p = head->next; 262 | idx = sum_holes; 263 | while(p != tail){ 264 | if(p->block->type == 1){ 265 | q = malloc(sizeof(struct node)); 266 | block = malloc(sizeof(block)); 267 | block -> start = idx; 268 | block -> end = idx + (p->block->end - p->block->start); 269 | block -> type = 1; 270 | block -> name = malloc(sizeof(char) * MAX_LENGTH); 271 | strcpy(block->name, p->block->name); 272 | q -> block = block; 273 | insertNode(new_head, new_tail, q); 274 | idx += (p->block->end - p->block->start); 275 | } 276 | p = p->next; 277 | } 278 | destroyNodes(head, tail); 279 | head = new_head; 280 | tail = new_tail; 281 | } 282 | 283 | /* As we traverse the link list, whenever we meet 284 | * type 0 block, we shuffle that forward. Finally we 285 | * will have all the holes on one side of memory. */ 286 | void handleCompactShuffle(){ 287 | struct node *p = head->next, *prev; 288 | while(p != tail){ 289 | /* only when we meet unused */ 290 | if(p->block->type == 0 && p->prev != head){ 291 | /* since we merge the holes when 292 | * allocation, the previous one must 293 | * be allocated and we can just exchange */ 294 | prev = p->prev; 295 | /* actually this operation may be implemented as memory copy */ 296 | prev->block->start += (p->block->end - p->block->start); 297 | prev->block->end += (p->block->end - p->block->start); 298 | p->block->start -= (prev->block->end - prev->block->start); 299 | p->block->end -= (prev->block->end - prev->block->start); 300 | /* now exchange these two */ 301 | prev->prev->next = p; 302 | p->prev = prev->prev; 303 | p->next->prev = prev; 304 | prev->next = p->next; 305 | p -> next = prev; 306 | /* merge the the holes */ 307 | mergeHole(p); 308 | /* as we shift p ahead , add one more p -> next step */ 309 | p = p->next ; 310 | } 311 | p = p->next; 312 | } 313 | } 314 | 315 | /* destory a link list */ 316 | void destroyNodes(struct node *head_p, struct node *tail_p){ 317 | struct node *tmp; 318 | while(head_p != tail_p){ 319 | tmp = head_p; 320 | head_p = head_p -> next; 321 | free(tmp); 322 | } 323 | free(head_p); 324 | } 325 | 326 | /* preprocess the string, 327 | * stripping unnecessary space */ 328 | char *preprocess(char *buffer){ 329 | char *tmp = malloc(sizeof(char) * MAX_LENGTH); 330 | int i, j=0, last=0; 331 | for(i=0;i File Name: allocator.h 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月19日 星期日 09时51分04秒 8 | ************************************************************************/ 9 | 10 | #ifndef _ALLOCATOR_H 11 | #define _ALLOCATOR_H 12 | 13 | /* max length of the input */ 14 | #define MAX_LENGTH 50 15 | 16 | /* define the struct to represent the allocation and hole */ 17 | typedef struct{ 18 | /* type 1: allocation 19 | * type 0: hole(namely unused) */ 20 | int type; 21 | int start; 22 | int end; 23 | /* the process id */ 24 | char *name; 25 | } Block; 26 | 27 | /* use double link list */ 28 | struct node{ 29 | Block *block; 30 | struct node *prev; 31 | struct node *next; 32 | }; 33 | 34 | 35 | /* print help about the input arguments */ 36 | void usage(); 37 | /* destroy the nodes in some link list(specified by the head and tail pointers) */ 38 | void destroyNodes(struct node *head_p, struct node *tail_p); 39 | /* preprocess the buffer string to get rid of unnecessary space characters */ 40 | char *preprocess(char *buffer); 41 | /* handle the "RQ" input */ 42 | void handleRequest(char *buffer); 43 | /* handle the "RL" input */ 44 | void handleRelease(char *buffer); 45 | /* insert a node to some link list(specified by the head_p and tail_p pointers) */ 46 | void insertNode(struct node *head_p, struct node *tail_p, struct node *newNode); 47 | /* split a unused node(as we have to allocate the space) */ 48 | void splitNode(int size, char *name, struct node *oldNode); 49 | /* merge adjacent holes */ 50 | void mergeHole(struct node *target); 51 | /* simple/false way to handle compact the memory */ 52 | void handleCompactSimple(); 53 | /* shuffle unused ahead to one side of the memory space */ 54 | void handleCompactShuffle(); 55 | /* print out the memory allocation status */ 56 | void printStatus(); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /project8/.gdb_history: -------------------------------------------------------------------------------- 1 | r 2 | q 3 | -------------------------------------------------------------------------------- /project8/BACKING_STORE.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project8/BACKING_STORE.bin -------------------------------------------------------------------------------- /project8/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -g -o manager manager.c 3 | 4 | clean: 5 | rm -rf manager output.txt 6 | -------------------------------------------------------------------------------- /project8/addresses.txt: -------------------------------------------------------------------------------- 1 | 16916 2 | 62493 3 | 30198 4 | 53683 5 | 40185 6 | 28781 7 | 24462 8 | 48399 9 | 64815 10 | 18295 11 | 12218 12 | 22760 13 | 57982 14 | 27966 15 | 54894 16 | 38929 17 | 32865 18 | 64243 19 | 2315 20 | 64454 21 | 55041 22 | 18633 23 | 14557 24 | 61006 25 | 62615 26 | 7591 27 | 64747 28 | 6727 29 | 32315 30 | 60645 31 | 6308 32 | 45688 33 | 969 34 | 40891 35 | 49294 36 | 41118 37 | 21395 38 | 6091 39 | 32541 40 | 17665 41 | 3784 42 | 28718 43 | 59240 44 | 40178 45 | 60086 46 | 42252 47 | 44770 48 | 22514 49 | 3067 50 | 15757 51 | 31649 52 | 10842 53 | 43765 54 | 33405 55 | 44954 56 | 56657 57 | 5003 58 | 50227 59 | 19358 60 | 36529 61 | 10392 62 | 58882 63 | 5129 64 | 58554 65 | 58584 66 | 27444 67 | 58982 68 | 51476 69 | 6796 70 | 21311 71 | 30705 72 | 28964 73 | 41003 74 | 20259 75 | 57857 76 | 63258 77 | 36374 78 | 692 79 | 43121 80 | 48128 81 | 34561 82 | 49213 83 | 36922 84 | 59162 85 | 50552 86 | 17866 87 | 18145 88 | 3884 89 | 54388 90 | 42932 91 | 46919 92 | 58892 93 | 8620 94 | 38336 95 | 64357 96 | 23387 97 | 42632 98 | 15913 99 | 15679 100 | 22501 101 | 37540 102 | 5527 103 | 63921 104 | 62716 105 | 32874 106 | 64390 107 | 63101 108 | 61802 109 | 19648 110 | 29031 111 | 44981 112 | 28092 113 | 9448 114 | 44744 115 | 61496 116 | 31453 117 | 60746 118 | 12199 119 | 62255 120 | 21793 121 | 26544 122 | 14964 123 | 41462 124 | 56089 125 | 52038 126 | 47982 127 | 59484 128 | 50924 129 | 6942 130 | 34998 131 | 27069 132 | 51926 133 | 60645 134 | 43181 135 | 10559 136 | 4664 137 | 28578 138 | 59516 139 | 38912 140 | 63562 141 | 64846 142 | 62938 143 | 27194 144 | 28804 145 | 61703 146 | 10998 147 | 6596 148 | 37721 149 | 43430 150 | 22692 151 | 62971 152 | 47125 153 | 52521 154 | 34646 155 | 32889 156 | 13055 157 | 65416 158 | 62869 159 | 57314 160 | 12659 161 | 14052 162 | 32956 163 | 49273 164 | 50352 165 | 49737 166 | 15555 167 | 47475 168 | 15328 169 | 34621 170 | 51365 171 | 32820 172 | 48855 173 | 12224 174 | 2035 175 | 60539 176 | 14595 177 | 13853 178 | 24143 179 | 15216 180 | 8113 181 | 22640 182 | 32978 183 | 39151 184 | 19520 185 | 58141 186 | 63959 187 | 53040 188 | 55842 189 | 585 190 | 51229 191 | 64181 192 | 54879 193 | 28210 194 | 10268 195 | 15395 196 | 12884 197 | 2149 198 | 53483 199 | 59606 200 | 14981 201 | 36672 202 | 23197 203 | 36518 204 | 13361 205 | 19810 206 | 25955 207 | 62678 208 | 26021 209 | 29409 210 | 38111 211 | 58573 212 | 56840 213 | 41306 214 | 54426 215 | 3617 216 | 50652 217 | 41452 218 | 20241 219 | 31723 220 | 53747 221 | 28550 222 | 23402 223 | 21205 224 | 56181 225 | 57470 226 | 39933 227 | 34964 228 | 24781 229 | 41747 230 | 62564 231 | 58461 232 | 20858 233 | 49301 234 | 40572 235 | 23840 236 | 35278 237 | 62905 238 | 56650 239 | 11149 240 | 38920 241 | 23430 242 | 57592 243 | 3080 244 | 6677 245 | 50704 246 | 51883 247 | 62799 248 | 20188 249 | 1245 250 | 12220 251 | 17602 252 | 28609 253 | 42694 254 | 29826 255 | 13827 256 | 27336 257 | 53343 258 | 11533 259 | 41713 260 | 33890 261 | 4894 262 | 57599 263 | 3870 264 | 58622 265 | 29780 266 | 62553 267 | 2303 268 | 51915 269 | 6251 270 | 38107 271 | 59325 272 | 61295 273 | 26699 274 | 51188 275 | 59519 276 | 7345 277 | 20325 278 | 39633 279 | 1562 280 | 7580 281 | 8170 282 | 62256 283 | 35823 284 | 27790 285 | 13191 286 | 9772 287 | 7477 288 | 44455 289 | 59546 290 | 49347 291 | 36539 292 | 12453 293 | 49640 294 | 28290 295 | 44817 296 | 8565 297 | 16399 298 | 41934 299 | 45457 300 | 33856 301 | 19498 302 | 17661 303 | 63829 304 | 42034 305 | 28928 306 | 30711 307 | 8800 308 | 52335 309 | 38775 310 | 52704 311 | 24380 312 | 19602 313 | 57998 314 | 2919 315 | 8362 316 | 17884 317 | 45737 318 | 47894 319 | 59667 320 | 10385 321 | 52782 322 | 64416 323 | 40946 324 | 16778 325 | 27159 326 | 24324 327 | 32450 328 | 9108 329 | 65305 330 | 19575 331 | 11117 332 | 65170 333 | 58013 334 | 61676 335 | 63510 336 | 17458 337 | 54675 338 | 1713 339 | 55105 340 | 65321 341 | 45278 342 | 26256 343 | 64198 344 | 29441 345 | 1928 346 | 39425 347 | 32000 348 | 28549 349 | 46295 350 | 22772 351 | 58228 352 | 63525 353 | 32602 354 | 46195 355 | 55849 356 | 46454 357 | 7487 358 | 33879 359 | 42004 360 | 8599 361 | 18641 362 | 49015 363 | 26830 364 | 34754 365 | 14668 366 | 38362 367 | 38791 368 | 4171 369 | 45975 370 | 14623 371 | 62393 372 | 64658 373 | 10963 374 | 9058 375 | 51031 376 | 32425 377 | 45483 378 | 44611 379 | 63664 380 | 54920 381 | 7663 382 | 56480 383 | 1489 384 | 28438 385 | 65449 386 | 12441 387 | 58530 388 | 63570 389 | 26251 390 | 15972 391 | 35826 392 | 5491 393 | 54253 394 | 49655 395 | 5868 396 | 20163 397 | 51079 398 | 21398 399 | 32756 400 | 64196 401 | 43218 402 | 21583 403 | 25086 404 | 45515 405 | 12893 406 | 22914 407 | 58969 408 | 20094 409 | 13730 410 | 44059 411 | 28931 412 | 13533 413 | 33134 414 | 28483 415 | 1220 416 | 38174 417 | 53502 418 | 43328 419 | 4970 420 | 8090 421 | 2661 422 | 53903 423 | 11025 424 | 26627 425 | 18117 426 | 14505 427 | 61528 428 | 20423 429 | 26962 430 | 36392 431 | 11365 432 | 50882 433 | 41668 434 | 30497 435 | 36216 436 | 5619 437 | 36983 438 | 59557 439 | 36663 440 | 36436 441 | 37057 442 | 23585 443 | 58791 444 | 46666 445 | 64475 446 | 21615 447 | 41090 448 | 1771 449 | 47513 450 | 39338 451 | 1390 452 | 38772 453 | 58149 454 | 7196 455 | 9123 456 | 7491 457 | 62616 458 | 15436 459 | 17491 460 | 53656 461 | 26449 462 | 34935 463 | 19864 464 | 51388 465 | 15155 466 | 64775 467 | 47969 468 | 16315 469 | 1342 470 | 51185 471 | 6043 472 | 21398 473 | 3273 474 | 9370 475 | 35463 476 | 28205 477 | 2351 478 | 28999 479 | 47699 480 | 46870 481 | 22311 482 | 22124 483 | 22427 484 | 49344 485 | 23224 486 | 5514 487 | 20504 488 | 376 489 | 2014 490 | 38700 491 | 13098 492 | 62435 493 | 48046 494 | 63464 495 | 12798 496 | 51178 497 | 8627 498 | 27083 499 | 47198 500 | 44021 501 | 32792 502 | 43996 503 | 41126 504 | 64244 505 | 37047 506 | 60281 507 | 52904 508 | 7768 509 | 55359 510 | 3230 511 | 44813 512 | 4116 513 | 65222 514 | 28083 515 | 60660 516 | 39 517 | 328 518 | 47868 519 | 13009 520 | 22378 521 | 39304 522 | 11171 523 | 8079 524 | 52879 525 | 5123 526 | 4356 527 | 45745 528 | 32952 529 | 4657 530 | 24142 531 | 23319 532 | 13607 533 | 46304 534 | 17677 535 | 59691 536 | 50967 537 | 7817 538 | 8545 539 | 55297 540 | 52954 541 | 39720 542 | 18455 543 | 30349 544 | 63270 545 | 27156 546 | 20614 547 | 19372 548 | 48689 549 | 49386 550 | 50584 551 | 51936 552 | 34705 553 | 13653 554 | 50077 555 | 54518 556 | 41482 557 | 4169 558 | 36118 559 | 9584 560 | 18490 561 | 55420 562 | 5708 563 | 23506 564 | 15391 565 | 36368 566 | 38976 567 | 50406 568 | 49236 569 | 65035 570 | 30120 571 | 62551 572 | 46809 573 | 21687 574 | 53839 575 | 2098 576 | 12364 577 | 45366 578 | 50437 579 | 36675 580 | 55382 581 | 11846 582 | 49127 583 | 19900 584 | 20554 585 | 19219 586 | 51483 587 | 58090 588 | 39074 589 | 16060 590 | 10447 591 | 54169 592 | 20634 593 | 57555 594 | 61210 595 | 269 596 | 33154 597 | 64487 598 | 61223 599 | 47292 600 | 21852 601 | 5281 602 | 45912 603 | 32532 604 | 63067 605 | 41683 606 | 20981 607 | 33881 608 | 41785 609 | 4580 610 | 41389 611 | 28572 612 | 782 613 | 30273 614 | 62267 615 | 17922 616 | 63238 617 | 3308 618 | 26545 619 | 44395 620 | 39120 621 | 21706 622 | 7144 623 | 30244 624 | 3725 625 | 54632 626 | 30574 627 | 8473 628 | 12386 629 | 41114 630 | 57930 631 | 15341 632 | 15598 633 | 59922 634 | 18226 635 | 48162 636 | 41250 637 | 1512 638 | 2546 639 | 41682 640 | 322 641 | 880 642 | 20891 643 | 56604 644 | 40166 645 | 26791 646 | 44560 647 | 38698 648 | 64127 649 | 15028 650 | 38669 651 | 45637 652 | 43151 653 | 9465 654 | 2498 655 | 13978 656 | 16326 657 | 51442 658 | 34845 659 | 63667 660 | 39370 661 | 55671 662 | 64496 663 | 7767 664 | 6283 665 | 55884 666 | 61103 667 | 10184 668 | 39543 669 | 9555 670 | 13963 671 | 58975 672 | 19537 673 | 6101 674 | 41421 675 | 45502 676 | 29328 677 | 8149 678 | 25450 679 | 58944 680 | 50666 681 | 23084 682 | 36468 683 | 33645 684 | 25002 685 | 53715 686 | 60173 687 | 46354 688 | 4708 689 | 28208 690 | 58844 691 | 22173 692 | 8535 693 | 42261 694 | 29687 695 | 37799 696 | 22566 697 | 62520 698 | 4098 699 | 47999 700 | 49660 701 | 37063 702 | 41856 703 | 5417 704 | 48856 705 | 10682 706 | 22370 707 | 63281 708 | 62452 709 | 50532 710 | 9022 711 | 59300 712 | 58660 713 | 56401 714 | 8518 715 | 63066 716 | 63250 717 | 48592 718 | 28771 719 | 37673 720 | 60776 721 | 56438 722 | 60424 723 | 39993 724 | 56004 725 | 59002 726 | 33982 727 | 25498 728 | 57047 729 | 1401 730 | 15130 731 | 42960 732 | 61827 733 | 32442 734 | 64304 735 | 30273 736 | 38082 737 | 22404 738 | 3808 739 | 16883 740 | 23111 741 | 62417 742 | 60364 743 | 4542 744 | 14829 745 | 44964 746 | 33924 747 | 2141 748 | 19245 749 | 47168 750 | 24048 751 | 1022 752 | 23075 753 | 24888 754 | 49247 755 | 4900 756 | 22656 757 | 34117 758 | 55555 759 | 48947 760 | 59533 761 | 21312 762 | 21415 763 | 813 764 | 19419 765 | 1999 766 | 20155 767 | 21521 768 | 13670 769 | 19289 770 | 58483 771 | 41318 772 | 16151 773 | 13611 774 | 21514 775 | 13499 776 | 45583 777 | 49013 778 | 64843 779 | 63485 780 | 38697 781 | 59188 782 | 24593 783 | 57641 784 | 36524 785 | 56980 786 | 36810 787 | 6096 788 | 11070 789 | 60124 790 | 37576 791 | 15096 792 | 45247 793 | 32783 794 | 58390 795 | 60873 796 | 23719 797 | 24385 798 | 22307 799 | 17375 800 | 15990 801 | 20526 802 | 25904 803 | 42224 804 | 9311 805 | 7862 806 | 3835 807 | 30535 808 | 65179 809 | 57387 810 | 63579 811 | 4946 812 | 9037 813 | 61033 814 | 55543 815 | 50361 816 | 6480 817 | 14042 818 | 21531 819 | 39195 820 | 37511 821 | 23696 822 | 27440 823 | 28201 824 | 23072 825 | 7814 826 | 6552 827 | 43637 828 | 35113 829 | 34890 830 | 61297 831 | 45633 832 | 61431 833 | 46032 834 | 18774 835 | 62991 836 | 28059 837 | 35229 838 | 51230 839 | 14405 840 | 52242 841 | 43153 842 | 2709 843 | 47963 844 | 36943 845 | 54066 846 | 10054 847 | 43051 848 | 11525 849 | 17684 850 | 41681 851 | 27883 852 | 56909 853 | 45772 854 | 27496 855 | 46842 856 | 38734 857 | 28972 858 | 59684 859 | 11384 860 | 21018 861 | 2192 862 | 18384 863 | 13464 864 | 31018 865 | 62958 866 | 30611 867 | 1913 868 | 18904 869 | 26773 870 | 55491 871 | 21899 872 | 64413 873 | 47134 874 | 23172 875 | 7262 876 | 12705 877 | 7522 878 | 58815 879 | 34916 880 | 3802 881 | 58008 882 | 1239 883 | 63947 884 | 381 885 | 60734 886 | 48769 887 | 41938 888 | 38025 889 | 55099 890 | 56691 891 | 39530 892 | 59003 893 | 6029 894 | 20920 895 | 8077 896 | 42633 897 | 17443 898 | 53570 899 | 22833 900 | 3782 901 | 47758 902 | 22136 903 | 22427 904 | 23867 905 | 59968 906 | 62166 907 | 6972 908 | 63684 909 | 46388 910 | 41942 911 | 36524 912 | 9323 913 | 31114 914 | 22345 915 | 46463 916 | 54671 917 | 9214 918 | 7257 919 | 33150 920 | 41565 921 | 26214 922 | 3595 923 | 17932 924 | 34660 925 | 51961 926 | 58634 927 | 57990 928 | 28848 929 | 49920 930 | 18351 931 | 53669 932 | 33996 933 | 6741 934 | 64098 935 | 606 936 | 27383 937 | 63140 938 | 32228 939 | 63437 940 | 29085 941 | 65080 942 | 38753 943 | 16041 944 | 9041 945 | 42090 946 | 46388 947 | 63650 948 | 36636 949 | 21947 950 | 19833 951 | 36464 952 | 8541 953 | 12712 954 | 48955 955 | 39206 956 | 15578 957 | 49205 958 | 7731 959 | 43046 960 | 60498 961 | 9237 962 | 47706 963 | 43973 964 | 42008 965 | 27460 966 | 24999 967 | 51933 968 | 34070 969 | 65155 970 | 59955 971 | 9277 972 | 20420 973 | 44860 974 | 50992 975 | 10583 976 | 57751 977 | 23195 978 | 27227 979 | 42816 980 | 58219 981 | 37606 982 | 18426 983 | 21238 984 | 11983 985 | 48394 986 | 11036 987 | 30557 988 | 23453 989 | 49847 990 | 30032 991 | 48065 992 | 6957 993 | 2301 994 | 7736 995 | 31260 996 | 17071 997 | 8940 998 | 9929 999 | 45563 1000 | 12107 1001 | -------------------------------------------------------------------------------- /project8/manager: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/project8/manager -------------------------------------------------------------------------------- /project8/manager.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: manager.c 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月19日 星期日 16时20分24秒 8 | ************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "manager.h" 15 | 16 | /* the number of pages */ 17 | int num_pages = 1; 18 | /* page size */ 19 | int page_size = 1; 20 | /* the number of frames */ 21 | int num_frames = 1; 22 | /* frame size */ 23 | int frame_size = 1; 24 | 25 | /* page table */ 26 | int *page_table; 27 | /* the physical memory */ 28 | char **memory; 29 | /* the lru for the memory */ 30 | int *memory_lru; 31 | /* keep track of the free frames */ 32 | int *free_frames; 33 | /* the TLB table to make things faster */ 34 | entry *tlb_table; 35 | 36 | /* the number of hits and visits */ 37 | int num_addresses = 0; 38 | int num_faults = 0; 39 | int tlb_hits = 0; 40 | 41 | int main(int argc, char *argv[]){ 42 | if(argc != 2){ 43 | fprintf(stderr, "Invalid arguments!\n"); 44 | exit(1); 45 | } 46 | /* since we only have 16 bits address at most, 47 | * here int type is sufficient */ 48 | int address; 49 | int page_idx,frame_idx, offset; 50 | int i, min_lru, min_lru_idx; 51 | signed char data; 52 | signed char *buffer; 53 | /* buffer will be used to store the data from backing store */ 54 | FILE *fp = fopen(argv[1], "r"); 55 | //FILE *fp_out = fopen(OUTPUT, "w"); 56 | FILE *fp_back = fopen(BACKING_STORE, "rb"); 57 | assert(fp && fp_back); 58 | init(); 59 | while(!feof(fp)){ 60 | fscanf(fp, "%d", &address); 61 | /* first get the page offset and page number */ 62 | offset = address % page_size; 63 | page_idx = (address / page_size) % num_pages; 64 | /* first look up the TLB table */ 65 | if((frame_idx = lookUpTLB(page_idx)) != -1){ 66 | data = memory[frame_idx][offset]; 67 | updateLRUTLB(page_idx); 68 | tlb_hits++; 69 | }else if(page_table[page_idx] == -1){ 70 | /* loop up the page table */ 71 | 72 | /* -1 means page fault(we don't have a frame number 73 | * at page_idx in page table */ 74 | 75 | /* 1. read data from BACKING_STORE 76 | * find the position */ 77 | buffer = malloc(sizeof(char) * page_size); 78 | fseek(fp_back, (page_idx) * page_size, SEEK_SET); 79 | fread(buffer, sizeof(char), page_size, fp_back); 80 | /* 2. find a free frame and store the data */ 81 | frame_idx = findFreeFrame(); 82 | if(frame_idx == -1){ 83 | /* can not find a free frame, we must use page replacement */ 84 | /* choose a victim and replace the frames */ 85 | min_lru = MAX_LRU; 86 | min_lru_idx = 0; 87 | for(i=0;i %s\n", OUTPUT); 170 | } 171 | 172 | int lookUpTLB(int page_idx){ 173 | for(int i=0;i File Name: manager.h 3 | > Author: Junjie Wang 4 | > Mail: dreamboy.gns@sjtu.edu.cn 5 | > Website:http://www.dbgns.com 6 | > Blog:http://www.dbgns.com/blog 7 | > Created Time: 2019年05月19日 星期日 16时20分35秒 8 | ************************************************************************/ 9 | 10 | #ifndef _MANAGER_H 11 | #define _MANAGER_H 12 | 13 | /* maximum length of each line in the file */ 14 | #define MAX_LENGTH 20 15 | 16 | /* file */ 17 | #define BACKING_STORE "./BACKING_STORE.bin" 18 | #define INPUT "./addresses.txt" 19 | #define OUTPUT "./output.txt" 20 | #define CORRECT "./correct.txt" 21 | 22 | /* page and frames */ 23 | #define PAGE_OFFSET_BITS 8 24 | #define PAGE_NUMBER_BITS 8 25 | #define FRAME_OFFSET_BITS 8 26 | #define FRAME_NUMBER_BITS 8 27 | 28 | /* the number of entries in TLB */ 29 | #define TLB_ENTRIES 16 30 | /* define the maximum value of LRU */ 31 | #define MAX_LRU 1000 32 | 33 | /* TLB entry struct */ 34 | typedef struct _entry{ 35 | int page_idx; 36 | int frame_idx; 37 | int lru; 38 | } entry; 39 | 40 | /* initialization */ 41 | void init(); 42 | /* output the results */ 43 | void testInput(); 44 | /* find a free frame */ 45 | int findFreeFrame(); 46 | int lookUpTLB(int page_idx); 47 | void updateLRUTLB(int page_idx); 48 | /* update the LRUs maintained for the physical memory */ 49 | void updateLRUMemory(int frame_idx); 50 | #endif 51 | -------------------------------------------------------------------------------- /project8/peda-session-manager.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /reports/project1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project1.pdf -------------------------------------------------------------------------------- /reports/project1.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project1: Introduction To Linux Kernel Module} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | 80 | \maketitle 81 | \section{Programming Thoughts} 82 | \subsection{Part 1} 83 | In the first part, first we have to create an initilization function and exiting function for our kernel module. Then we need to include necessary header files(e.g. linux/jiffies.h linux/gcd.h) to use the global variables and functions which are only available in kernel space. Another thing worth attention is the different types for these variables. 84 | \subsection{Part 2} 85 | In the second part, we need to interact with the /proc pseudo file system. First we need to print out the value of jiffies variable in $proc\_read()$ function and then we need to use this equation to get the time interval. 86 | $$t = \frac{jiffies_t - jiffies_0}{HZ} $$ 87 | \section{Execution Results And Snapshots} 88 | The execution results are shown in \ref{fig1} and \ref{fig2}. 89 | \begin{figure}[H] 90 | \centering 91 | \includegraphics[width=0.8\textwidth]{../imgs/1-1.png} 92 | \caption{part 1} 93 | \label{fig1} 94 | \end{figure} 95 | \begin{figure}[htbp] 96 | \centering 97 | \includegraphics[width=0.8\textwidth]{../imgs/1-2.png} 98 | \caption{part 2} 99 | \label{fig2} 100 | \end{figure} 101 | \section{Code Explanation} 102 | The $proc\_init()$ and $proc\_read()$ are shown as belows. We first use a global variable \textbf{start} to record the value of jiffies at the beginning. And then use the formula to get the time interval when the $proc\_read()$ function is invoked. 103 | \begin{lstlisting} 104 | static int proc_init(void) 105 | { 106 | proc_create(PROC_NAME, 0666, NULL, &proc_ops); 107 | printk(KERN_INFO "/proc/%s created\n", PROC_NAME); 108 | start = jiffies; 109 | 110 | return 0; 111 | } 112 | ... 113 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 114 | { 115 | int rv = 0; 116 | static int completed = 0; 117 | char buffer[BUFFER_SIZE]; 118 | 119 | if(completed){ 120 | completed = 0; 121 | return 0; 122 | } 123 | 124 | completed = 1; 125 | 126 | rv = sprintf(buffer, "%lus has eplased since creation.\n", (jiffies-start)/HZ); 127 | 128 | copy_to_user(usr_buf, buffer, rv); 129 | return rv; 130 | } 131 | \end{lstlisting} 132 | 133 | \end{document} -------------------------------------------------------------------------------- /reports/project2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project2.pdf -------------------------------------------------------------------------------- /reports/project2.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project2: Unix Shell Programming \& LKM for task information} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | \subsection{Part 1: Unix Shell Programming} 82 | The main logic is to use a while loop to get inputs from the user. Then create a child process(using $fork()$) to execute the command. \\ 83 | To support the history logic, we simply need to maintain one more variable($char *last\_input)$. And when receving $'!!'$, copy $last\_input$ into the $input$ string.\\ 84 | To support the \& logic, we simply need to modify a little bit about the behavior of the parent process(do not wait until the child process exits). Another thing worth attention here is using $signal()$ to prevent the \textbf{zombies}.\\ 85 | To support the redirection logic, the idea is to use $dup2()$ function, closing the stdin/stdout file descriptors and reset its pointer according to the file descriptor we are going to open(e.g. output.txt). \\ 86 | To support the pipe($'|'$), the idea is to create the child process of the child process(also using $fork()$). Pipe is acommplished through the IPC between these two processes. $dup()$ function is used here, actually quite similar to the $dup2()$. 87 | \subsection{Part 2: Linux Kernel Module For Task Information} 88 | The idea is to get the pid from user's input in $proc\_write()$ function. Then use $task\_pid()$ to get corresponding process and output the pid, command and state of this process. Another thing worth attention is that there should be a logic to handle invalid pid(simply return 0); 89 | \section{Execution Results And Snapshots} 90 | Execution results are shown as belows: 91 | \begin{figure}[H] 92 | \centering 93 | \includegraphics[width=0.8\textwidth]{../imgs/2-1.png} 94 | \label{fig1} 95 | \caption{Primitive Version} 96 | \end{figure} 97 | \begin{figure}[H] 98 | \centering 99 | \includegraphics[width=0.8\textwidth]{../imgs/2-4.png} 100 | \label{fig2} 101 | \caption{Add support for history feature} 102 | \end{figure} 103 | \begin{figure}[H] 104 | \centering 105 | \includegraphics[width=0.8\textwidth]{../imgs/2-2.png} 106 | \label{fig3} 107 | \caption{Add support for \& and the redirection} 108 | \end{figure} 109 | \begin{figure}[H] 110 | \centering 111 | \includegraphics[width=0.8\textwidth]{../imgs/2-3.png} 112 | \label{fig4} 113 | \caption{Add support for the pipe} 114 | \end{figure} 115 | \begin{figure}[H] 116 | \centering 117 | \includegraphics[width=0.8\textwidth]{../imgs/2-5.png} 118 | \label{fig5} 119 | \caption{The part 2, LKM for task information} 120 | \end{figure} 121 | \section{Code Explanation} 122 | \subsection{part 1} 123 | An important part is using the $dup()$, $dup2()$ and $execvp()$ functions. 124 | \begin{lstlisting} 125 | /* find a minimum value in current available file descriptors and set its pointer as the oldfd */ 126 | int dup(int oldfd); 127 | /* only a little different from dup(). In dup2() we can specify the newfd we want to use. It newfd is already open, close it first */ 128 | int dup2(int oldfd, int newfd); 129 | /* exec family functions. Note that the first file parameter will be search in $(PATH) environment variable and the last parameter for the */ 130 | int execvp(const char *file, const char *argv[]); 131 | \end{lstlisting} 132 | The logic for the pipe is as follows. For the child process, we first close the stdin and the write port of the pipe. Then use $dup()$ function to get the $0$ file descriptor and set its pointer to the read port of the pipe. The logic for the parent process is similar. 133 | \begin{lstlisting} 134 | int p[2], ppid; 135 | 136 | pipe(p); 137 | ppid = fork(); 138 | if(ppid < 0) {perror("ppid create error!");exit(1);} 139 | else if(ppid == 0){ 140 | /* for the child of the child process, set it as the executor of the second commmand */ 141 | close(0); 142 | close(p[1]); 143 | if(dup(p[0]) < 0) {perror("dup error!");exit(1);} 144 | res = execvp(pipe_args[0], pipe_args); 145 | if(res < 0) { perror("cmd2 execution error!"); exit(1); } 146 | }else{ 147 | /* for the parent process, it will execute the first command */ 148 | /* close stdout */ 149 | close(1); 150 | /* close one port */ 151 | close(p[0]); 152 | if(dup(p[1]) < 0) {perror("dup error!");exit(1);} 153 | res = execvp(valid_args[0], valid_args); 154 | if(res < 0) { perror("cmd1 execution error!"); exit(1); } 155 | } 156 | \end{lstlisting} 157 | \subsection{part 2} 158 | To get the $command, state, pid$ information, we need to refer to $linux/sched.h$ and use logic as follows in $proc\_read()$ function(Note that $l\_pid$ is parsed from $proc\_write()$ function. 159 | \begin{lstlisting} 160 | static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos) 161 | { 162 | int rv = 0; 163 | char buffer[BUFFER_SIZE]; 164 | static int completed = 0; 165 | struct task_struct *tsk = NULL; 166 | 167 | if (completed) { 168 | completed = 0; 169 | return 0; 170 | } 171 | 172 | tsk = pid_task(find_vpid(l_pid), PIDTYPE_PID); 173 | 174 | completed = 1; 175 | 176 | /* return 0 if no this pid */ 177 | if( tsk == NULL) return 0; 178 | else rv = sprintf(buffer, "command = %s pid = %d state = %ld\n", tsk->comm, tsk->pid, tsk->state); 179 | 180 | // copies the contents of kernel buffer to userspace usr_buf 181 | if (copy_to_user(usr_buf, buffer, rv)) { 182 | rv = -1; 183 | } 184 | 185 | return rv; 186 | } 187 | \end{lstlisting} 188 | 189 | \end{document} -------------------------------------------------------------------------------- /reports/project3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project3.pdf -------------------------------------------------------------------------------- /reports/project3.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project3: Multi-threaded Sorting Application \& Fork-Join Sorting Application} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | \subsection{Part1: Multi-threaded Sorting} 82 | In this part we are going to split a list into two halves and create sort threads to sort these two halves. Then we need to use merge thread to merge these two halves. This idea is a bit similiar to the mergeSort algorithm. Another thing worth attention is that to pass the parameters to the threads, we better define a \textbf{struct}(in this example, consists of start idx and end idx). 83 | \subsection{Part2: Fork-Join Sorting} 84 | In this part we have to implement quickSort and mergeSort algorithms using Java multi-threading APIs. Both algorithms here consist of the \textbf{dividing stage}(where we use new threads to accomplish the sorting of two halves.) and \textbf{conquering stage}(where we set a threshold, smaller than we will simply use sorting algorithm like insertionSort.) 85 | \section{Execution Results And Snapshots} 86 | The execution results are as follows: 87 | \begin{figure}[H] 88 | \centering 89 | \includegraphics[width=1.0\textwidth]{../imgs/3-1.png} 90 | \caption{Multi-threaded Sorting} 91 | \end{figure} 92 | \begin{figure}[H] 93 | \centering 94 | \includegraphics[width=1.0\textwidth]{../imgs/3-2.png} 95 | \caption{Multi-threaded Sorting} 96 | \end{figure} 97 | \section{Code Explanation} 98 | First we show the parameters passing for the first part. 99 | \begin{lstlisting} 100 | /* for multiple arguments to be passed 101 | * we have to define a struct */ 102 | typedef struct _param{ 103 | int start; 104 | int end; 105 | } funcParam; 106 | ... 107 | /* setting the parameters */ 108 | params[0].start = 0; params[0].end = mid; 109 | pthread_attr_init(&attr[0]); 110 | pthread_create(&tid[0], &attr[0], sortThread, ¶ms[0]); 111 | ... 112 | /* getting the parameters by type conversion 113 | and code for the sorting thread */ 114 | void *sortThread(void *param){ 115 | funcParam arg = *(funcParam *)param; 116 | int start = arg.start, end = arg.end; 117 | int min, tmp, idx; 118 | for(int i=start;i= val) high--; 140 | if(low < high) { array[low] = array[high]; low++;} 141 | while(low < high && array[low] <= val) low++; 142 | if(low < high) { array[high] = array[low];high--; } 143 | }while(low!=high); 144 | 145 | array[low] = val; 146 | 147 | /* from the place we put val */ 148 | int mid = low + 1; 149 | quickSortTask left = new quickSortTask(begin, mid - 1, array); 150 | quickSortTask right = new quickSortTask(mid + 1, end, array); 151 | 152 | /* create new threads to accomplish the sorting of the two halves */ 153 | left.fork(); 154 | right.fork(); 155 | 156 | /* wait until the threads exit */ 157 | left.join(); 158 | right.join(); 159 | 160 | /* divide stage for the mergeSort, much simpler*/ 161 | int mid = (begin + end) / 2; 162 | mergeSortTask left = new mergeSortTask(begin, mid, array); 163 | mergeSortTask right = new mergeSortTask(mid + 1, end, array); 164 | left.fork(); 165 | right.fork(); 166 | left.join(); 167 | right.join(); 168 | \end{lstlisting} 169 | 170 | \end{document} -------------------------------------------------------------------------------- /reports/project4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project4.pdf -------------------------------------------------------------------------------- /reports/project4.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project4: Scheduling Algorithms} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | The main logic here is to use the link list to store all the tasks first and then implement different algorithms according to their own conditions. A point that worths attention here is when we construct the link list from the input file(schedule.txt), the task with larger id will be closer to the head. So usually we need to locate to the tail of the link list first.\\ 82 | \textbf{FCFS}: Quite easy. Simply move to the tail of the link list and run the task at that place. \\ 83 | \textbf{SJF}: Each time we traverse the link list, we find the task with the minumum burst time, then running that task. \\ 84 | \textbf{PRIORITY}: Each time we traverse the link list, we find the task with the largest priority number(higher priority according to the rule) and execute that task. \\ 85 | \textbf{ROUND ROBIN(RR)}: First we reverse the chain to make tasks with smaller id closer to the head. Then each time we traverse the chain, we check whether the remaining burst time of a task is smaller than the time quantum. If yes, we execute that job with all its remaining burst time and remove that job from the new link list.If no, we execute that task for a slice of time quantum. \\ 86 | \textbf{PRIORITY ROUND ROBIN}: This is probably the hardest part of these five algorithms. First we also reverse the link list. Then each time we traverse the new link list, we find the tasks with the maximum priority number and record how many tasks have this maximum priority number. If more than one, we use round robin strategy among them. If exactly one, we execute that one task and remove it from the link list. 87 | \section{Execution Results And Snapshots} 88 | The execution results of these five algorithms are listed as follows: 89 | \begin{figure}[H] 90 | \centering 91 | \includegraphics[width=1.0\textwidth]{../imgs/4-1.png} 92 | \caption{FCFS} 93 | \end{figure} 94 | \begin{figure}[H] 95 | \centering 96 | \includegraphics[width=1.0\textwidth]{../imgs/4-2.png} 97 | \caption{SJF} 98 | \end{figure} 99 | \begin{figure}[H] 100 | \centering 101 | \includegraphics[width=1.0\textwidth]{../imgs/4-4.png} 102 | \caption{Priority} 103 | \end{figure} 104 | \begin{figure}[H] 105 | \centering 106 | \includegraphics[width=1.0\textwidth]{../imgs/4-3.png} 107 | \caption{Round Robin} 108 | \end{figure} 109 | \begin{figure}[H] 110 | \centering 111 | \includegraphics[width=1.0\textwidth]{../imgs/4-5.png} 112 | \caption{Priority Round Robin} 113 | \end{figure} 114 | 115 | \section{Code Explanation} 116 | For brevity here I only show the implementation of the priority round robin. First we reverse the link list and use the headNew pointer we get to implement the core logic. 117 | \begin{lstlisting} 118 | void schedule(){ 119 | /* implement the priority round robin schedule algorithm 120 | * first reverse the list */ 121 | struct node **headNew = malloc(sizeof(struct node *)); 122 | /* must maually set it to NULL */ 123 | *headNew = NULL; 124 | 125 | Task *task = malloc(sizeof(Task)); 126 | struct node *newNode; 127 | struct node **p = malloc(sizeof(struct node *)); 128 | while((*head)->next!=NULL){ 129 | task = (*head) -> task; 130 | newNode = malloc(sizeof(struct node)); 131 | newNode -> task = task; 132 | newNode -> next = *headNew; 133 | *headNew = newNode; 134 | *head = (*head)-> next; 135 | } 136 | task = (*head) -> task; 137 | newNode = malloc(sizeof(struct node)); 138 | newNode -> task = task; 139 | newNode -> next = *headNew; 140 | *headNew = newNode; 141 | 142 | /* implement the priority RR based on the headNew 143 | * first use an array to store the priority counts */ 144 | *p = *headNew; 145 | int counts[MAX_PRIORITY+1], i; 146 | for(i=0;i<=MAX_PRIORITY;i++) counts[i] = 0; 147 | while((*p)->next != NULL){ 148 | task = (*p) -> task; 149 | counts[task->priority]++; 150 | *p = (*p) -> next; 151 | } 152 | 153 | i = MAX_PRIORITY; 154 | while(1){ 155 | for(;counts[i] == 0 && i>0; i--) ; 156 | if(i == 0) break; 157 | 158 | if(counts[i] == 1){ 159 | /* with only one task, we just execute it */ 160 | *p = *headNew; 161 | while((*p)->next != NULL){ 162 | if((*p) -> task -> priority == i){ 163 | run((*p)->task, (*p)->task->burst); 164 | delete(headNew, (*p)->task); 165 | break; 166 | } 167 | *p = (*p) -> next; 168 | } 169 | counts[i] = 0; 170 | }else{ 171 | /* with more than one task, we use the round robin */ 172 | *p = *headNew; 173 | while(counts[i]>0){ 174 | if((*p)->task->priority == i){ 175 | task = (*p) -> task; 176 | if(task->burst <= RR_TIME){ 177 | /* with time less than the limit */ 178 | run(task, task->burst); 179 | /* move on */ 180 | delete(headNew, task); 181 | counts[i]--; 182 | }else{ 183 | /* with time more than the Q */ 184 | run(task, RR_TIME); 185 | task->burst -= RR_TIME; 186 | } 187 | } 188 | if((*p)->next == NULL) *p = *headNew; 189 | else *p = (*p) -> next; 190 | } 191 | } 192 | } 193 | free(newNode); 194 | free(headNew); 195 | free(p); 196 | free(task); 197 | } 198 | \end{lstlisting} 199 | \end{document} -------------------------------------------------------------------------------- /reports/project5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project5.pdf -------------------------------------------------------------------------------- /reports/project5.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project5: Designing A Thread-Pool \& Producer-Consumer Algorithm} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | \subsection{Part1: Designing A Thread-Pool} 82 | The main advantage of a thread pool is that it saves the time of creating new threads(it will only create all the threads once at the beginning). In the implementation logic, we need to organize the tasks into a queue(with FIFO property) and then submit the tasks to the thread pool. Once receiving the signal(using semaphores here), an available thread will take over a task from the queue and start execution. Once it finishes execution, it will wait in the pool for new tasks to come. \\ 83 | An important part of this part is using semaphores to inform the threads of coming tasks and using mutex to prevent simultaneous operations on the task queue. 84 | \subsection{Part2: Producer-Consumer Algorithm} 85 | In this part we will create a number of producers and consumers. Producers will sleep for random time and then insert a random item into the buffer. Consumers will sleep for random time and then remove an random item from the buffer. The main logic here is to use semaphores \textbf{full} and \textbf{empty} to indicate whether the buffer is full or empty. Also mutex is needed for fear of simultaneous operations on the same buffer region. All this things will happen permanently, so we need to set a hyperparameter about how long it will take before the termination of the program. 86 | \section{Execution Results And Snapshots} 87 | The execution results are listed as follows: 88 | \begin{figure}[H] 89 | \centering 90 | \includegraphics[width=1.0\textwidth]{../imgs/5-1.png} 91 | \caption{thread pool} 92 | \end{figure} 93 | \begin{figure}[H] 94 | \centering 95 | \includegraphics[width=1.0\textwidth]{../imgs/5-2.png} 96 | \caption{Producer-Consumer Algorithm} 97 | \end{figure} 98 | \section{Code Explanation} 99 | First there are several major functions we will use about the semaphores and mutex. 100 | \begin{lstlisting} 101 | /* if the value of semaphore is larger than 0, we decrease by 1 and continues. 102 | otherwise, we will wait until sem > 0 */ 103 | int sem_wait(sem_t *sem); 104 | /* increase the value of sem by 1 and invoke threads which are waiting on this semaphore. */ 105 | int sem_post(sem_t *sem); 106 | /* lock the mutex */ 107 | int pthread_mutex_lock(pthread_mutex_t *mutex); 108 | /* unlock the mutex */ 109 | int pthread_mutex_unlock(pthread_mutex_t *mutex); 110 | \end{lstlisting} 111 | For part1, we show the code of the $worker$ function, which is the core of the algorithm. 112 | \begin{lstlisting} 113 | void *worker(void *param){ 114 | while(1){ 115 | /* must watch on whether the pool has been shutdown */ 116 | while(num_tasks == 0 && !is_shutdown){ 117 | printf("waiting for the task...\n"); 118 | sem_wait(&sem); 119 | } 120 | if(is_shutdown){ 121 | /* if the pool has been shut down, all the threads must exit */ 122 | printf("The pool has been shut down => threads all exiting...\n"); 123 | pthread_exit(0); 124 | } 125 | /* lock the mutex to avoid race condition */ 126 | pthread_mutex_lock(&mutex); 127 | task = dequeue(); 128 | pthread_mutex_unlock(&mutex); 129 | num_tasks--; 130 | execute(task.function, task.data); 131 | } 132 | } 133 | \end{lstlisting} 134 | For part2, we take the code of the consumer as example to show the logic. 135 | \begin{lstlisting} 136 | void *consumer(void *param){ 137 | /* sleep for random time 138 | * remove an item from the buffer */ 139 | int sleep_time; 140 | int id = *(int *)param; 141 | bufferItem item; 142 | while(1){ 143 | /* avoid endless sleeping */ 144 | sleep_time = rand() % 10; 145 | sleep(sleep_time); 146 | item = removeItem(); 147 | printf("Consumer %d removes item %d.\n", id, item); 148 | } 149 | } 150 | \end{lstlisting} 151 | \end{document} -------------------------------------------------------------------------------- /reports/project6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project6.pdf -------------------------------------------------------------------------------- /reports/project6.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project6: Banker's Algorithm} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | Banker's algorithm is widely used to detect whether the state of a system is safe, then preventing deadlocks by denying requests which will cause a safe state into an unsafe state. \\ 82 | We have to maintain 4 arrays(maximum, allocation, need, available) through the whole process. These 4 arrays will be used to decide whether we can find a sequence to execute all the processes(if such sequence can be found, we claim that the system is safe, otherwise it's unsafe). Note that once a process is finished, we release all the resources allocated to this process and update the 4 arrays accordingly.\\ 83 | The stratey here to handle the request of resources is: assume that we accept the request(in my implementation, I copy the 4 arrays as backup, actually this is not very efficient), then try to find a sequence to execute all the processes. If we can find, we turn back to accept the request, otherwise we deny it. \\ 84 | The strategy the handle the release request is much simpler, we only need to ensure that the release request does not exceed the process's allocation. Then we can update the 4 arrays accordingly. 85 | \section{Execution Results And Snapshots} 86 | As we can see in \ref{fig1}, initialliy the allocation array is empty. If we use input (10,5,7,8)(claiming the maximum amout of the resources), since the maximum array of the fifth customer is (5,6,7,5), we can not find a sequence to satisfy all the customers, indicating that current state is unsafe. So the coming request will be denied for sure. 87 | \begin{figure}[H] 88 | \centering 89 | \includegraphics[width=1.0\textwidth]{../imgs/6-1.png} 90 | \caption{attempt 1} 91 | \label{fig1} 92 | \end{figure} 93 | Next we use a much larger input, (100, 100, 100, 100) for 4 types of resources. This time we can see in \ref{fig2} the resources are allocated successfully. And once we release the resources, the arrays are all restored. 94 | \begin{figure}[H] 95 | \centering 96 | \includegraphics[width=1.0\textwidth]{../imgs/6-2.png} 97 | \caption{attempt 2} 98 | \label{fig2} 99 | \end{figure}\begin{figure}[H] 100 | \centering 101 | \includegraphics[width=0.6\textwidth]{../imgs/6-3.png} 102 | \caption{attempt 2} 103 | \label{fig3} 104 | \end{figure} 105 | \section{Code Explanation} 106 | The core logic is to how to check whether the system will be in safe state. The idea is to use a $checkSafeWrapper()$(where the 4 arrays are restored for later restoration) function to call $checkSafe()$ function, which will determine whether the system will be in safe state. 107 | \begin{lstlisting} 108 | int checkSafe(int *finished){ 109 | int i; 110 | for(i=0;i available[j]) break; 132 | } 133 | if(j == num_resources && !finished[i]) return i; 134 | } 135 | return -1; 136 | } 137 | \end{lstlisting} 138 | \end{document} -------------------------------------------------------------------------------- /reports/project7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project7.pdf -------------------------------------------------------------------------------- /reports/project7.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project7: Contiguous Memory Allocation} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | First store the allocation as blocks into double link list(with head and tail), and all of our operations are done on these blocks. \\ 82 | \subsection{Hit Strategies} Three hit strategies often used are: best/first/worst hit strategy. The first hit is the easiest to implement, where we simply move along the link list and stop once we find one block meeting our requirement. For best/worst strategy, we need to traverse the whole double link list. \\ 83 | \subsection{Handle Memory Request} When we use one of strategies above and find a block to allocate to the process, what we need to do is split the block. After splitting the block, one part of the block will be allocated to the process, and the other part will be unused. \\ 84 | \subsection{Handle Memory Release} When receiving the memory releasing request, we traverse the link list and free the blocks whose "name" is the same as the name given. Note that once the block becomes unused once released, and we have to check whether we can merge it with its previous block and following block. \\ 85 | \subsection{Compaction} After a number of iterations of memory allocation and memory freeing, these may be many holes in our memory, which will reduce the memory utilization rate. Solution here is to use memory compaction strategy, which will merge all the holes into only one large hole on one side of the memory, and place all the processes on the other side. I offer 2 different implementations in my code. One is naive and simply re-allocate a memory space whose size is equal to our original one. Then process the processes and unused memory blocks according to the original one. This is probably \textbf{not what happens in real-world scenerio} because of limitation of memory space. So I offer the second implementation, which shuffles the unused memory forward as it moves along the link list(this can be done by copying the allocated block backward, byte by byte, from start to end). 86 | \section{Execution Results And Snapshots} 87 | We first request 4000 bytes for the process P0 using best hit strategy. Then we request another 4000 bytes for process P0 using worst hit. Now P0 has 8000 bytes memory space, and once we release all the memory which belongs to P0, the expected output should be an completely unused block. As we can see in \ref{fig1}, the real output is correct.\\ 88 | Then we test the compaction logic. The idea is to request 4000 bytes for P0 first and then P1. Then release the memory which belongs to P0. As we can see in \ref{fig1}, the unused memory is shuffled towards one side of the memory. 89 | \begin{figure}[H] 90 | \centering 91 | \includegraphics[width=0.9\textwidth]{../imgs/7-1.png} 92 | \caption{first} 93 | \label{fig1} 94 | \end{figure} 95 | \section{Code Explanation} 96 | First we define some data structures which will be used to represent the memory block and form the link list. Listed as follows: 97 | \begin{lstlisting} 98 | /* define the struct to represent the allocation and hole */ 99 | typedef struct{ 100 | /* type 1: allocation 101 | * type 0: hole(namely unused) */ 102 | int type; 103 | int start; 104 | int end; 105 | /* the process id */ 106 | char *name; 107 | } Block; 108 | 109 | /* use double link list */ 110 | struct node{ 111 | Block *block; 112 | struct node *prev; 113 | struct node *next; 114 | }; 115 | \end{lstlisting} 116 | Then we show the code of splitting the node(which will be used in handling memory requests) 117 | \begin{lstlisting} 118 | void splitNode(int size, char *name, struct node *oldNode){ 119 | block = oldNode -> block; 120 | if(block -> end - block -> start == size){ 121 | /* if we have size == end - start, that's perfect */ 122 | strcpy(block->name, name); 123 | block->type = 1; 124 | }else{ 125 | /* else we have to split the node */ 126 | tmp_block = malloc(sizeof(Block)); 127 | newNode = malloc(sizeof(struct node)); 128 | tmp_block -> start = block -> start; 129 | tmp_block -> end = block -> start + size; 130 | block -> start = block -> start + size; 131 | /* since the first one is the allocation 132 | * its type = 1 */ 133 | tmp_block -> type = 1; 134 | /* if use strcpy() function, 135 | * don't forget tmp_block -> name = malloc(...) */ 136 | tmp_block -> name = name; 137 | newNode -> block = tmp_block; 138 | oldNode -> prev -> next = newNode; 139 | newNode -> prev = oldNode -> prev; 140 | newNode -> next = oldNode; 141 | oldNode -> prev = newNode; 142 | } 143 | } 144 | \end{lstlisting} 145 | Then we show the logic to merge holes(used when releasing memory space) 146 | \begin{lstlisting} 147 | /* check whether we can merge the node with 148 | * its previous one and its following one */ 149 | void mergeHole(struct node *target){ 150 | newNode = malloc(sizeof(struct node)); 151 | block = malloc(sizeof(Block)); 152 | if(target->prev != head && target->prev->block->type == 0){ 153 | /* merge current one with previous one */ 154 | block -> start = target -> prev -> block -> start; 155 | block -> end = target -> block -> end; 156 | block -> type = 0; 157 | newNode -> block = block; 158 | target -> prev -> prev -> next = newNode; 159 | newNode -> prev = target -> prev -> prev; 160 | newNode -> next = target -> next; 161 | target -> next -> prev = newNode; 162 | target = NULL; 163 | } 164 | if(target == NULL) { target = newNode; newNode = malloc(sizeof(struct node)); } 165 | 166 | if(target->next != tail && target->next->block->type == 0){ 167 | /* merge current one with following one */ 168 | block -> start = target -> block -> start; 169 | block -> end = target -> next -> block -> end; 170 | block -> type = 0; 171 | newNode -> block = block; 172 | target -> next -> next -> prev = newNode; 173 | newNode -> next = target -> next -> next; 174 | target -> prev -> next = newNode; 175 | newNode -> prev = target -> prev; 176 | } 177 | } 178 | \end{lstlisting} 179 | At last we show the logic of compaction(the \textbf{shuffle} method). 180 | \begin{lstlisting} 181 | /* As we traverse the link list, whenever we meet 182 | * type 0 block, we shuffle that forward. Finally we 183 | * will have all the holes on one side of memory. */ 184 | void handleCompactShuffle(){ 185 | struct node *p = head->next, *prev; 186 | while(p != tail){ 187 | /* only when we meet unused */ 188 | if(p->block->type == 0 && p->prev != head){ 189 | /* since we merge the holes when 190 | * allocation, the previous one must 191 | * be allocated and we can just exchange */ 192 | prev = p->prev; 193 | /* actually this operation may be implemented as memory copy */ 194 | prev->block->start += (p->block->end - p->block->start); 195 | prev->block->end += (p->block->end - p->block->start); 196 | p->block->start -= (prev->block->end - prev->block->start); 197 | p->block->end -= (prev->block->end - prev->block->start); 198 | /* now exchange these two */ 199 | prev->prev->next = p; 200 | p->prev = prev->prev; 201 | p->next->prev = prev; 202 | prev->next = p->next; 203 | p -> next = prev; 204 | /* merge the the holes */ 205 | mergeHole(p); 206 | /* as we shift p ahead , add one more p -> next step */ 207 | p = p->next ; 208 | } 209 | p = p->next; 210 | } 211 | } 212 | \end{lstlisting} 213 | \end{document} -------------------------------------------------------------------------------- /reports/project8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FishWoWater/Operating-System-Concepts-Projects/33ef990780f5376cee2d0630d7bf1bf10d25ca17/reports/project8.pdf -------------------------------------------------------------------------------- /reports/project8.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{extarticle} 2 | %Some packages I commonly use. 3 | \usepackage[english]{babel} 4 | \usepackage{graphicx} 5 | \usepackage{framed} 6 | \usepackage[normalem]{ulem} 7 | \usepackage{amsmath} 8 | \usepackage{amsthm} 9 | \usepackage{amssymb} 10 | \usepackage{amsfonts} 11 | \usepackage{enumerate} 12 | \usepackage[utf8]{inputenc} 13 | \usepackage{listings} 14 | \usepackage[top=1 in,bottom=1in, left=1 in, right=1 in]{geometry} 15 | \usepackage{color} 16 | \usepackage{float} 17 | 18 | \definecolor{dkgreen}{rgb}{0,0.6,0} 19 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 20 | \definecolor{mauve}{rgb}{0.58,0,0.82} 21 | 22 | %A bunch of definitions that make my life easier 23 | \newcommand{\matlab}{{\sc Matlab} } 24 | \newcommand{\cvec}[1]{{\mathbf #1}} 25 | \newcommand{\rvec}[1]{\vec{\mathbf #1}} 26 | \newcommand{\ihat}{\hat{\textbf{\i}}} 27 | \newcommand{\jhat}{\hat{\textbf{\j}}} 28 | \newcommand{\khat}{\hat{\textbf{k}}} 29 | \newcommand{\minor}{{\rm minor}} 30 | \newcommand{\trace}{{\rm trace}} 31 | \newcommand{\spn}{{\rm Span}} 32 | \newcommand{\rem}{{\rm rem}} 33 | \newcommand{\ran}{{\rm range}} 34 | \newcommand{\range}{{\rm range}} 35 | \newcommand{\mdiv}{{\rm div}} 36 | \newcommand{\proj}{{\rm proj}} 37 | \newcommand{\R}{\mathbb{R}} 38 | \newcommand{\N}{\mathbb{N}} 39 | \newcommand{\Q}{\mathbb{Q}} 40 | \newcommand{\Z}{\mathbb{Z}} 41 | \newcommand{\<}{\langle} 42 | \renewcommand{\>}{\rangle} 43 | \renewcommand{\emptyset}{\varnothing} 44 | \newcommand{\attn}[1]{\textbf{#1}} 45 | \theoremstyle{definition} 46 | \newtheorem{theorem}{Theorem} 47 | \newtheorem{corollary}{Corollary} 48 | \newtheorem*{definition}{Definition} 49 | \newtheorem*{example}{Example} 50 | \newtheorem*{note}{Note} 51 | \newtheorem{exercise}{Exercise} 52 | \newcommand{\bproof}{\bigskip {\bf Proof. }} 53 | \newcommand{\eproof}{\hfill\qedsymbol} 54 | \newcommand{\Disp}{\displaystyle} 55 | \newcommand{\qe}{\hfill\(\bigtriangledown\)} 56 | \setlength{\columnseprule}{1 pt} 57 | 58 | \lstset{frame=tb, 59 | language=C, 60 | aboveskip=3mm, 61 | belowskip=3mm, 62 | showstringspaces=false, 63 | columns=flexible, 64 | basicstyle={\small\ttfamily}, 65 | numbers=none, 66 | numberstyle=\tiny\color{gray}, 67 | keywordstyle=\color{blue}, 68 | commentstyle=\color{dkgreen}, 69 | stringstyle=\color{mauve}, 70 | breaklines=true, 71 | breakatwhitespace=true, 72 | tabsize=3 73 | } 74 | 75 | \title{CS307 Project8: Virtual Memory Manager} 76 | \author{Junjie Wang 517021910093} 77 | 78 | \begin{document} 79 | \maketitle 80 | \section{Programming Thoughts} 81 | First we have to compute the number of pages, size of each page, the number of frames and the size of each frame and then initialize the page table, memory and TLB table. 82 | \subsection{Page Table} 83 | Then we implement the logic for page table. Given a page index, if there is a valid frame index in page table, we can simply use the frame index we get and the offset previously computed to get the physical address of the data and then visit the physical memory. If we meet a page fault(no valid frame index), we should first locate to correct position of the BACKING\_STORE.bin, and then read in page size bytes of data. Then find a free frame in the physical memory, put the data into that frame and update the page table. 84 | \subsection{TLB Table} 85 | As for the logic for TLB table, the logic is quite similar to the page table(since TLB is only to make things faster). When a virtual address comes, we first look up its page index in the TLB table. If TLB hits, we can just use the frame index to compute the physical address, visiting the physical memory. If TLB misses, we turn to the page table. Besides, logic for update TLB table when reading data from BACKING\_STORE should be added. 86 | \subsection{Page Replacement} 87 | As for the logic of page replacement algorithm, I implement the LRU algorithm. Since when the number of pages is equal to the number of frames, we can always find a free frame and no page replacement will happen. So the page replacement only works when the size of physical memory is much smaller than the logical memory(e.g. 128 frames and 256 pages). The idea is to initilize the LRU numbers of all frames to \textbf{INT\_MAX} and each time we visit a frame, we update all the LRU numbers using this strategy: setting the exact frame we are visiting's LRU number to \textbf{INT\_MAX} and decrease all lother LRU numbers by 1. Each time we choose a victim, we choose the frame with the smallest LRU number. 88 | \subsection{TLB LRU} 89 | Similar LRU logic applies to the TLB table. Since an entry in TLB table consists of both the page index and frame index, we better define a new data struct to add in the LRU member. 90 | \section{Execution Results And Snapshots} 91 | \begin{figure}[H] 92 | \centering 93 | \includegraphics[width=1.0\textwidth]{../imgs/8-1.png} 94 | \caption{256 frames} 95 | \label{fig1} 96 | \end{figure} 97 | In \ref{fig2}, the comparsion between the output.txt(the output of the algroithm on addresses.txt) and the correct.txt(the official output for reference) is given. 98 | \begin{figure}[H] 99 | \centering 100 | \includegraphics[width=1.0\textwidth]{../imgs/8-2.png} 101 | \caption{output.txt vs correct.txt} 102 | \label{fig2} 103 | \end{figure} 104 | In \ref{fig3}, the execution results of 128 frames are given. Since the only difference only lies in choosing a victim frame, the output should be the same as in \ref{fig1}. 105 | \begin{figure}[H] 106 | \centering 107 | \includegraphics[width=1.0\textwidth]{../imgs/8-3.png} 108 | \caption{128 frames} 109 | \label{fig3} 110 | \end{figure} 111 | \section{Code Explanation} 112 | The data struct for each TLB entry(we add a member to be the lru number) is as follows: 113 | \begin{lstlisting} 114 | /* TLB entry struct */ 115 | typedef struct _entry{ 116 | int page_idx; 117 | int frame_idx; 118 | int lru; 119 | } entry; 120 | \end{lstlisting} 121 | The logic of updating LRU numbers for the memory and TLB table 122 | \begin{lstlisting} 123 | /* update the lru for the tlb */ 124 | void updateLRUTLB(int page_idx){ 125 | for(int i=0;i