Operating_Systems/Lab/Lab4/source/21281280-柯劲帆-第4次实验.md
2024-09-05 13:31:02 +08:00

825 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h1><center>北京交通大学实验报告</center></h1>
<div style="text-align: center;">
<div><span style="display: inline-block; width: 65px; text-align: center;">课程名称</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">操作系统</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">实验题目</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">动态可重定位分区内存管理模拟设计与实现</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">学号</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">21281280</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">姓名</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">柯劲帆</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">班级</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">物联网2101班</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">指导老师</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">何永忠</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">报告日期</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">2023年11月26日</span></div>
</div>
---
## 目录
[TOC]
---
# 1. 开发运行环境和工具
| 操作系统 | Linux内核版本 | 处理器 | GCC版本 |
| :---------: | :-----------------------: | :--------------------------------------: | :-------------------------------: |
| Deepin 20.9 | 5.18.17-amd64-desktop-hwe | Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz | gcc (Uos 8.3.0.3-3+rebuild) 8.3.0 |
- **其他工具**
- **编辑**VSCode
- **编译和运行**Terminal
# 2. 实验过程、分析和结论
## 2.1. 初始化
```c
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NUM_TASKS 128
struct Block {
int start;
int size;
int pid;
struct Block* next, * last;
};
struct Task {
int start;
int size;
int pid;
struct Block* block;
};
struct Request {
int size;
struct Request* next;
};
int preprocess_task_size(int);
int find_free_block_ff(int, struct Block**);
int find_free_block_bf(int, struct Block**);
void queue_push(int);
int queue_pop();
int get_command(FILE*);
int fork_process(int);
void kill_process(int);
int run(char*);
void init();
void clean_stdin();
void execute_wait_list();
void print();
int sys_size = 128 << 20, usr_size = 384 << 20;
struct Block* sys_space = NULL, * usr_space = NULL;
struct Task* tasks = NULL;
struct Request* waitlist_begin = NULL, * waitlist_end = NULL;
int waitlist_size = 0;
int last_pid = -1;
int match_method = -1;
int main() {
init();
while (get_command(stdin) >= 0);
return 0;
}
void init() {
sys_space = (struct Block*)malloc(sizeof(struct Block));
sys_space->pid = -1;
sys_space->start = 0;
sys_space->size = sys_size;
sys_space->next = NULL;
sys_space->last = NULL;
usr_space = (struct Block*)malloc(sizeof(struct Block));
usr_space->pid = -1;
usr_space->start = sys_size;
usr_space->size = usr_size;
usr_space->next = NULL;
usr_space->last = NULL;
tasks = (struct Task*)malloc(MAX_NUM_TASKS * sizeof(struct Task));
for (int i = 0; i < MAX_NUM_TASKS; i++) tasks[i].pid = -1;
ask_match_method:
printf("Choose a matching method:\n 1. First Fit\n 2. Best Fit\n");
printf("choose> ");
scanf("%d", &match_method);
clean_stdin();
if (match_method != 1 && match_method != 2) {
printf("Bad input. Choose again.\n");
goto ask_match_method;
}
waitlist_begin = (struct Request*)malloc(sizeof(struct Request));
waitlist_end = waitlist_begin;
waitlist_begin->next = NULL;
waitlist_begin->size = -1;
}
```
## 2.2. 申请内存分配操作
```c
int fork_process(int size) {
int pid;
int task_index = -1;
repeat:
last_pid++;
if (last_pid < 0) last_pid = 0;
pid = last_pid;
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid >= 0 && tasks[i].pid == pid) goto repeat;
}
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid >= 0) continue;
task_index = i;
break;
}
if (task_index == -1) return -1;
size = preprocess_task_size(size);
tasks[task_index].size = size;
int start_loc = -1;
if (match_method == 1) start_loc = find_free_block_ff(size, &tasks[task_index].block);
else start_loc = find_free_block_bf(size, &tasks[task_index].block);
if (start_loc >= 0) {
tasks[task_index].start = start_loc;
tasks[task_index].pid = pid;
tasks[task_index].size = size;
tasks[task_index].block->pid = pid;
printf("Fork succeed. PID is %d . Block size is %d bits.\n", pid, size);
return pid;
}
printf("Fork failed. Out of Memory. Trying to push into wait list.\n");
queue_push(size);
return -1;
}
int find_free_block_ff(int size, struct Block** block_p) {
struct Block* now = usr_space;
int cnt = 1;
while (1) {
if (now == NULL) return -1;
if (now->pid < 0 && now->size >= size) break;
now = now->next;
cnt++;
}
printf("Use %d times to find free block.\n", cnt);
*block_p = now;
if (now->size == size) return now->start;
struct Block* free_space = (struct Block*)malloc(sizeof(struct Block));
free_space->pid = -1;
free_space->last = now;
free_space->next = now->next;
free_space->size = now->size - size;
free_space->start = now->start + size;
now->pid = -2;
now->next = free_space;
now->size = size;
return now->start;
}
int find_free_block_bf(int size, struct Block** block_p) {
struct Block* now = usr_space, * best_block;
int best_size = 0x7fffffff;
int cnt = 1;
while (1) {
if (now == NULL) break;
if (now->pid < 0 && now->size >= size && best_size >= now->size) {
best_block = now;
best_size = now->size;
}
now = now->next;
cnt++;
}
if (best_size == 0x7fffffff) return -1;
printf("Use %d times to find free block.\n", cnt);
*block_p = best_block;
if (best_block->size == size) return best_block->start;
struct Block* free_space = (struct Block*)malloc(sizeof(struct Block));
free_space->pid = -1;
free_space->last = best_block;
free_space->next = best_block->next;
free_space->size = best_block->size - size;
free_space->start = best_block->start + size;
best_block->pid = -2;
best_block->next = free_space;
best_block->size = size;
return best_block->start;
}
int run(char* path) {
FILE* f = NULL;
f = fopen(path, "r+");
if (f == NULL) {
printf("Error: Invalid file path.\n");
return 0;
}
int result = 0;
while (!feof(f) && result != -1) result = get_command(f);
fclose(f);
return result;
}
int preprocess_task_size(int size) {
int lower = size & 0x3ff;
if (lower == 0) return size;
int upper = size - lower;
size = upper + 0x400;
return size;
}
void queue_push(int size) {
waitlist_begin->next = (struct Request*)malloc(sizeof(struct Request));
waitlist_begin = waitlist_begin->next;
waitlist_begin->next = NULL;
waitlist_begin->size = size;
waitlist_size++;
}
int queue_pop() {
if (!waitlist_size) {
printf("Wait list empty.\n");
return -1;
}
struct Request* tmp = waitlist_end;
waitlist_end = waitlist_end->next;
free(tmp);
waitlist_size--;
return waitlist_end->size;
}
```
## 2.3. 回收
```c
void kill_process(int pid) {
struct Block* block = NULL;
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid != pid) continue;
block = tasks[i].block;
break;
}
if (block == NULL) {
printf("Error: PID dosen't exist.\n");
return;
}
if (block->last && block->last->pid < 0 && block->next && block->next->pid < 0) {
struct Block* free_block = block->last;
free_block->next = block->next->next;
free_block->size += block->size + block->next->size;
if (free_block->next) free_block->next->last = free_block;
free(block->next);
free(block);
}
else if (block->last && block->last->pid < 0) {
struct Block* free_block = block->last;
free_block->next = block->next;
free_block->size += block->size;
if (free_block->next) free_block->next->last = free_block;
free(block);
}
else if (block->next && block->next->pid < 0) {
struct Block* free_block = block;
free_block->size += block->next->size;
free_block->next = block->next->next;
free_block->pid = -1;
if (free_block->next) free_block->next->last = free_block;
free(block->next);
}
else {
block->pid = -1;
}
execute_wait_list();
return;
}
void execute_wait_list() {
int size = -1, loop_num = waitlist_size;
for (int i = 0; i < loop_num; i++) {
size = queue_pop();
fork_process(size);
}
}
```
## 2.4. 其他代码
```c
int get_command(FILE* stream) {
printf("user> ");
char input_str[128] = { 0 };
fgets(input_str, 127, stream);
if (stream != stdin) printf("%s", input_str);
int split_index = 0;
for (int i = 0; i < 127; i++) {
if (input_str[i] == '\0') break;
if (input_str[i] == ' ') {
input_str[i] = '\0';
split_index = i;
}
if (input_str[i] == '\n') {
input_str[i] = '\0';
break;
}
}
char* command = input_str, * arguments = input_str + split_index + 1;
if (!strcmp(command, "exit")) {
return -1;
}
else if (strcmp(command, "fork") == 0) {
int input_size = atoi(arguments);
if (input_size <= 0) {
printf("Bad input size. Input number must larger than ZERO.\n");
return 0;
}
else if (input_size > usr_size) {
printf("Bad input size. Input number must smaller than %d bits.\n", usr_size);
return 0;
}
int pid = fork_process(input_size);
return 1;
}
else if (!strcmp(command, "kill")) {
int input_pid = atoi(arguments);
if (input_pid < 0) {
printf("Bad input PID. Input number must not smaller than ZERO.\n");
return 0;
}
kill_process(input_pid);
return 1;
}
else if (!strcmp(input_str, "print")) {
print();
return 1;
}
else if (!strcmp(input_str, "run")) {
int result = run(arguments);
return result;
}
else if (input_str[0] == '\0');
else {
printf("Command not found.\n");
return 0;
}
}
void print() {
char str[2][13] = { {" True"}, {" False"} };
char* s;
struct Block* p = sys_space;
printf("+----------------------------------------------------------------+\n");
printf("| System Space |\n");
printf("+------------+------------+------------+------------+------------+\n");
printf("| Free | Begin | Size | End | PID |\n");
printf("+------------+------------+------------+------------+------------+\n");
while (p != NULL) {
s = p->pid < 0 ? str[0] : str[1];
printf("|%s|%12d|%12d|%12d|%12d|\n", s, p->start, p->size, p->start + p->size - 1, p->pid);
printf("+------------+------------+------------+------------+------------+\n");
p = p->next;
}
printf("+----------------------------------------------------------------+\n\n");
p = usr_space;
printf("+----------------------------------------------------------------+\n");
printf("| User Space |\n");
printf("+------------+------------+------------+------------+------------+\n");
printf("| Free | Begin | Size | End | PID |\n");
printf("+------------+------------+------------+------------+------------+\n");
while (p != NULL) {
s = p->pid < 0 ? str[0] : str[1];
printf("|%s|%12d|%12d|%12d|%12d|\n", s, p->start, p->size, p->start + p->size - 1, p->pid);
printf("+------------+------------+------------+------------+------------+\n");
p = p->next;
}
printf("+----------------------------------------------------------------+\n");
}
void clean_stdin() {
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
int run(char* path) {
FILE* f = NULL;
f = fopen(path, "r+");
if (f == NULL) {
printf("Error: Invalid file path.\n");
return 0;
}
int result = 0;
while (!feof(f) && result != -1) result = get_command(f);
fclose(f);
return result;
}
```
# 附录
```c
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NUM_TASKS 128
struct Block {
int start;
int size;
int pid;
struct Block* next, * last;
};
struct Task {
int start;
int size;
int pid;
struct Block* block;
};
struct Request {
int size;
struct Request* next;
};
int preprocess_task_size(int);
int find_free_block_ff(int, struct Block**);
int find_free_block_bf(int, struct Block**);
void queue_push(int);
int queue_pop();
int get_command(FILE*);
int fork_process(int);
void kill_process(int);
int run(char*);
void init();
void clean_stdin();
void execute_wait_list();
void print();
int sys_size = 128 << 20, usr_size = 384 << 20;
struct Block* sys_space = NULL, * usr_space = NULL;
struct Task* tasks = NULL;
struct Request* waitlist_begin = NULL, * waitlist_end = NULL;
int waitlist_size = 0;
int last_pid = -1;
int match_method = -1;
int main() {
init();
while (get_command(stdin) >= 0);
return 0;
}
int get_command(FILE* stream) {
printf("user> ");
char input_str[128] = { 0 };
fgets(input_str, 127, stream);
if (stream != stdin) printf("%s", input_str);
int split_index = 0;
for (int i = 0; i < 127; i++) {
if (input_str[i] == '\0') break;
if (input_str[i] == ' ') {
input_str[i] = '\0';
split_index = i;
}
if (input_str[i] == '\n') {
input_str[i] = '\0';
break;
}
}
char* command = input_str, * arguments = input_str + split_index + 1;
if (!strcmp(command, "exit")) {
return -1;
}
else if (strcmp(command, "fork") == 0) {
int input_size = atoi(arguments);
if (input_size <= 0) {
printf("Bad input size. Input number must larger than ZERO.\n");
return 0;
}
else if (input_size > usr_size) {
printf("Bad input size. Input number must smaller than %d bits.\n", usr_size);
return 0;
}
int pid = fork_process(input_size);
return 1;
}
else if (!strcmp(command, "kill")) {
int input_pid = atoi(arguments);
if (input_pid < 0) {
printf("Bad input PID. Input number must not smaller than ZERO.\n");
return 0;
}
kill_process(input_pid);
return 1;
}
else if (!strcmp(input_str, "print")) {
print();
return 1;
}
else if (!strcmp(input_str, "run")) {
int result = run(arguments);
return result;
}
else if (input_str[0] == '\0');
else {
printf("Command not found.\n");
return 0;
}
}
void kill_process(int pid) {
struct Block* block = NULL;
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid != pid) continue;
block = tasks[i].block;
break;
}
if (block == NULL) {
printf("Error: PID dosen't exist.\n");
return;
}
if (block->last && block->last->pid < 0 && block->next && block->next->pid < 0) {
struct Block* free_block = block->last;
free_block->next = block->next->next;
free_block->size += block->size + block->next->size;
if (free_block->next) free_block->next->last = free_block;
free(block->next);
free(block);
}
else if (block->last && block->last->pid < 0) {
struct Block* free_block = block->last;
free_block->next = block->next;
free_block->size += block->size;
if (free_block->next) free_block->next->last = free_block;
free(block);
}
else if (block->next && block->next->pid < 0) {
struct Block* free_block = block;
free_block->size += block->next->size;
free_block->next = block->next->next;
free_block->pid = -1;
if (free_block->next) free_block->next->last = free_block;
free(block->next);
}
else {
block->pid = -1;
}
execute_wait_list();
return;
}
void init() {
sys_space = (struct Block*)malloc(sizeof(struct Block));
sys_space->pid = -1;
sys_space->start = 0;
sys_space->size = sys_size;
sys_space->next = NULL;
sys_space->last = NULL;
usr_space = (struct Block*)malloc(sizeof(struct Block));
usr_space->pid = -1;
usr_space->start = sys_size;
usr_space->size = usr_size;
usr_space->next = NULL;
usr_space->last = NULL;
tasks = (struct Task*)malloc(MAX_NUM_TASKS * sizeof(struct Task));
for (int i = 0; i < MAX_NUM_TASKS; i++) tasks[i].pid = -1;
ask_match_method:
printf("Choose a matching method:\n 1. First Fit\n 2. Best Fit\n");
printf("choose> ");
scanf("%d", &match_method);
clean_stdin();
if (match_method != 1 && match_method != 2) {
printf("Bad input. Choose again.\n");
goto ask_match_method;
}
waitlist_begin = (struct Request*)malloc(sizeof(struct Request));
waitlist_end = waitlist_begin;
waitlist_begin->next = NULL;
waitlist_begin->size = -1;
}
int fork_process(int size) {
int pid;
int task_index = -1;
repeat:
last_pid++;
if (last_pid < 0) last_pid = 0;
pid = last_pid;
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid >= 0 && tasks[i].pid == pid) goto repeat;
}
for (int i = 0; i < MAX_NUM_TASKS; i++) {
if (tasks[i].pid >= 0) continue;
task_index = i;
break;
}
if (task_index == -1) return -1;
size = preprocess_task_size(size);
tasks[task_index].size = size;
int start_loc = -1;
if (match_method == 1) start_loc = find_free_block_ff(size, &tasks[task_index].block);
else start_loc = find_free_block_bf(size, &tasks[task_index].block);
if (start_loc >= 0) {
tasks[task_index].start = start_loc;
tasks[task_index].pid = pid;
tasks[task_index].size = size;
tasks[task_index].block->pid = pid;
printf("Fork succeed. PID is %d . Block size is %d bits.\n", pid, size);
return pid;
}
printf("Fork failed. Out of Memory. Trying to push into wait list.\n");
queue_push(size);
return -1;
}
int find_free_block_ff(int size, struct Block** block_p) {
struct Block* now = usr_space;
int cnt = 1;
while (1) {
if (now == NULL) return -1;
if (now->pid < 0 && now->size >= size) break;
now = now->next;
cnt++;
}
printf("Use %d times to find free block.\n", cnt);
*block_p = now;
if (now->size == size) return now->start;
struct Block* free_space = (struct Block*)malloc(sizeof(struct Block));
free_space->pid = -1;
free_space->last = now;
free_space->next = now->next;
free_space->size = now->size - size;
free_space->start = now->start + size;
now->pid = -2;
now->next = free_space;
now->size = size;
return now->start;
}
int find_free_block_bf(int size, struct Block** block_p) {
struct Block* now = usr_space, * best_block;
int best_size = 0x7fffffff;
int cnt = 1;
while (1) {
if (now == NULL) break;
if (now->pid < 0 && now->size >= size && best_size >= now->size) {
best_block = now;
best_size = now->size;
}
now = now->next;
cnt++;
}
if (best_size == 0x7fffffff) return -1;
printf("Use %d times to find free block.\n", cnt);
*block_p = best_block;
if (best_block->size == size) return best_block->start;
struct Block* free_space = (struct Block*)malloc(sizeof(struct Block));
free_space->pid = -1;
free_space->last = best_block;
free_space->next = best_block->next;
free_space->size = best_block->size - size;
free_space->start = best_block->start + size;
best_block->pid = -2;
best_block->next = free_space;
best_block->size = size;
return best_block->start;
}
int run(char* path) {
FILE* f = NULL;
f = fopen(path, "r+");
if (f == NULL) {
printf("Error: Invalid file path.\n");
return 0;
}
int result = 0;
while (!feof(f) && result != -1) result = get_command(f);
fclose(f);
return result;
}
int preprocess_task_size(int size) {
int lower = size & 0x3ff;
if (lower == 0) return size;
int upper = size - lower;
size = upper + 0x400;
return size;
}
void queue_push(int size) {
waitlist_begin->next = (struct Request*)malloc(sizeof(struct Request));
waitlist_begin = waitlist_begin->next;
waitlist_begin->next = NULL;
waitlist_begin->size = size;
waitlist_size++;
}
int queue_pop() {
if (!waitlist_size) {
printf("Wait list empty.\n");
return -1;
}
struct Request* tmp = waitlist_end;
waitlist_end = waitlist_end->next;
free(tmp);
waitlist_size--;
return waitlist_end->size;
}
void clean_stdin() {
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
void execute_wait_list() {
int size = -1, loop_num = waitlist_size;
for (int i = 0; i < loop_num; i++) {
size = queue_pop();
fork_process(size);
}
}
void print() {
char str[2][13] = { {" True"}, {" False"} };
char* s;
struct Block* p = sys_space;
printf("+----------------------------------------------------------------+\n");
printf("| System Space |\n");
printf("+------------+------------+------------+------------+------------+\n");
printf("| Free | Begin | Size | End | PID |\n");
printf("+------------+------------+------------+------------+------------+\n");
while (p != NULL) {
s = p->pid < 0 ? str[0] : str[1];
printf("|%s|%12d|%12d|%12d|%12d|\n", s, p->start, p->size, p->start + p->size - 1, p->pid);
printf("+------------+------------+------------+------------+------------+\n");
p = p->next;
}
printf("+----------------------------------------------------------------+\n\n");
p = usr_space;
printf("+----------------------------------------------------------------+\n");
printf("| User Space |\n");
printf("+------------+------------+------------+------------+------------+\n");
printf("| Free | Begin | Size | End | PID |\n");
printf("+------------+------------+------------+------------+------------+\n");
while (p != NULL) {
s = p->pid < 0 ? str[0] : str[1];
printf("|%s|%12d|%12d|%12d|%12d|\n", s, p->start, p->size, p->start + p->size - 1, p->pid);
printf("+------------+------------+------------+------------+------------+\n");
p = p->next;
}
printf("+----------------------------------------------------------------+\n");
}
```