├── .gitignore ├── Operator_System_Lab1 ├── demo.c └── sys.c ├── Operator_System_Lab2 ├── Operator_System_Exp2_1 │ ├── Makefile │ └── show_all_kernel_thread.c └── Operator_System_Exp2_2 │ ├── Makefile │ └── show_task_family.c ├── Operator_System_Lab3 ├── Operator_System_Exp3_1 │ ├── csh │ ├── main │ └── main.c ├── Operator_System_Exp3_2 │ ├── CMakeLists.txt │ ├── main │ └── main.c ├── Operator_System_Exp3_3 │ ├── CMakeLists.txt │ ├── common.h │ └── main.c ├── Operator_System_Exp3_3_fake │ ├── CMakeLists.txt │ ├── common.h │ └── main.c └── Operator_System_Exp3_4 │ ├── CMakeLists.txt │ ├── common.h │ ├── receiver.c │ └── sender.c ├── Operator_System_Lab5 ├── CMakeLists.txt ├── main ├── main.c ├── simplefs.c └── simplefs.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # CLion compile file 55 | .idea/ 56 | cmake-build-debug/ 57 | -------------------------------------------------------------------------------- /Operator_System_Lab1/demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define _SYSCALL_MYSETNICE_ 335 5 | #define EFALUT 14 6 | 7 | int main() 8 | { 9 | int pid, flag, nicevalue; 10 | int prev_prio, prev_nice, cur_prio, cur_nice; 11 | int result; 12 | 13 | printf("Please input variable(pid, flag, nicevalue): "); 14 | scanf("%d%d%d", &pid, &flag, &nicevalue); 15 | 16 | result = syscall(_SYSCALL_MYSETNICE_, pid, 0, nicevalue, &prev_prio, 17 | &prev_nice); 18 | if (result == EFALUT) 19 | { 20 | printf("ERROR!"); 21 | return 1; 22 | } 23 | 24 | if (flag == 1) 25 | { 26 | syscall(_SYSCALL_MYSETNICE_, pid, 1, nicevalue, &cur_prio, &cur_nice); 27 | printf("Original priority is: [%d], original nice is [%d]\n", prev_prio, 28 | prev_nice); 29 | printf("Current priority is : [%d], current nice is [%d]\n", cur_prio, 30 | cur_nice); 31 | } 32 | else if (flag == 0) 33 | { 34 | printf("Current priority is : [%d], current nice is [%d]\n", prev_prio, 35 | prev_nice); 36 | } 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /Operator_System_Lab1/sys.c: -------------------------------------------------------------------------------- 1 | SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, 2 | prio, void __user *, nice) 3 | { 4 | int cur_prio, cur_nice; 5 | struct pid *ppid; 6 | struct task_struct *pcb; 7 | 8 | ppid = find_get_pid(pid); 9 | if (ppid == NULL) 10 | return EFAULT; 11 | 12 | pcb = pid_task(ppid, PIDTYPE_PID); 13 | 14 | if (flag == 1) 15 | { 16 | set_user_nice(pcb, nicevalue); 17 | } 18 | else if (flag != 0) 19 | { 20 | return EFAULT; 21 | } 22 | 23 | cur_prio = task_prio(pcb); 24 | cur_nice = task_nice(pcb); 25 | 26 | copy_to_user(prio, &cur_prio, sizeof(cur_prio)); 27 | copy_to_user(nice, &cur_nice, sizeof(cur_nice)); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Operator_System_Lab2/Operator_System_Exp2_1/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := show_all_kernel_thread.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | default: 5 | make -C $(KDIR) M=$(PWD) modules 6 | clean: 7 | make -C $(KDIR) M=$(PWD) clean -------------------------------------------------------------------------------- /Operator_System_Lab2/Operator_System_Exp2_1/show_all_kernel_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | MODULE_LICENSE("GPL"); 8 | 9 | static int __init show_all_kernel_thread_init(void) 10 | { 11 | struct task_struct *p; 12 | printk("%-20s%-6s%-6s%-6s%-6s", "Name", "PID", "State", "Prio", "PPID"); 13 | printk("--------------------------------------------"); 14 | for_each_process(p) 15 | { 16 | if (p->mm == NULL) 17 | { 18 | printk("%-20s%-6d%-6d%-6d%-6d", p->comm, p->pid, p->state, p->prio, 19 | p->parent->pid); 20 | } 21 | } 22 | return 0; 23 | } 24 | 25 | static void __exit show_all_kernel_thread_exit(void) 26 | { 27 | printk("[ShowAllKernelThread] Module Uninstalled."); 28 | } 29 | 30 | module_init(show_all_kernel_thread_init); 31 | module_exit(show_all_kernel_thread_exit); -------------------------------------------------------------------------------- /Operator_System_Lab2/Operator_System_Exp2_2/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := show_task_family.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | default: 5 | make -C $(KDIR) M=$(PWD) modules 6 | clean: 7 | make -C $(KDIR) M=$(PWD) clean -------------------------------------------------------------------------------- /Operator_System_Lab2/Operator_System_Exp2_2/show_task_family.c: -------------------------------------------------------------------------------- 1 | // show_task_family.c 2 | // created by 19-03-26 3 | // Arcana 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | MODULE_LICENSE("GPL"); 13 | static int pid; 14 | module_param(pid, int, 0644); 15 | 16 | static int __init show_task_family_init(void) 17 | { 18 | struct pid *ppid; 19 | struct task_struct *p; 20 | struct task_struct *pos; 21 | char *ptype[4] = {"[I]", "[P]", "[S]", "[C]"}; 22 | 23 | // 通过进程的PID号pid一步步找到进程的进程控制块p 24 | ppid = find_get_pid(pid); 25 | if (ppid == NULL) 26 | { 27 | printk("[ShowTaskFamily] Error, PID not exists.\n"); 28 | return -1; 29 | } 30 | p = pid_task(ppid, PIDTYPE_PID); 31 | 32 | // 格式化输出表头 33 | printk("%-10s%-20s%-6s%-6s\n", "Type", "Name", "PID", "State"); 34 | printk("------------------------------------------\n"); 35 | 36 | // Itself 37 | // 打印自身信息 38 | printk("%-10s%-20s%-6d%-6d\n", ptype[0], p->comm, p->pid, p->state); 39 | 40 | // Parent 41 | // 打印父进程信息 42 | printk("%-10s%-20s%-6d%-6d\n", ptype[1], p->real_parent->comm, 43 | p->real_parent->pid, p->real_parent->state); 44 | 45 | // Siblings 46 | // 遍历父进程的子,即我的兄弟进程,输出信息 47 | // “我”同样是父进程的子进程,所以当二者进程PID号一致时,跳过不输出 48 | list_for_each_entry(pos, &(p->real_parent->children), sibling) 49 | { 50 | if (pos->pid == pid) 51 | continue; 52 | printk("%-10s%-20s%-6d%-6d\n", ptype[2], pos->comm, pos->pid, 53 | pos->state); 54 | } 55 | 56 | // Children 57 | // 遍历”我“的子进程,输出信息 58 | list_for_each_entry(pos, &(p->children), sibling) 59 | { 60 | printk("%-10s%-20s%-6d%-6d\n", ptype[3], pos->comm, pos->pid, 61 | pos->state); 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | static void __exit show_task_family_exit(void) 68 | { 69 | printk("[ShowTaskFamily] Module Uninstalled.\n"); 70 | } 71 | 72 | module_init(show_task_family_init); 73 | module_exit(show_task_family_exit); -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_1/csh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leslievan/Operator_System/a4ab78afdf3423b6ad0a72783e3d91e75abf0e71/Operator_System_Lab3/Operator_System_Exp3_1/csh -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_1/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leslievan/Operator_System/a4ab78afdf3423b6ad0a72783e3d91e75abf0e71/Operator_System_Lab3/Operator_System_Exp3_1/main -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_1/main.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file main.c 3 | * 4 | * @author Arcana 5 | * 6 | * @date 2018.11.10 7 | * 8 | * @brief CSH (A simple shell in C) 9 | *****************************************************************************/ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* 19 | * Funcion Declarations for builtin shell commands: 20 | */ 21 | int csh_cd(char **args); 22 | int csh_help(char **args); 23 | int csh_exit(char **args); 24 | int csh_hello(char **args); 25 | int csh_print_info(char **args); 26 | 27 | /* 28 | * List of builtin commands, followed by their corresponding functions. 29 | */ 30 | char *builtin_str[] = { 31 | "cd", 32 | "help", 33 | "hello", 34 | "print_info", 35 | "exit" 36 | }; 37 | 38 | int (*builtin_func[]) (char **) = { 39 | &csh_cd, 40 | &csh_help, 41 | &csh_hello, 42 | &csh_print_info, 43 | &csh_exit 44 | }; 45 | 46 | int csh_num_builtins(void) { 47 | return sizeof(builtin_str) / sizeof(char*); 48 | } 49 | 50 | /* 51 | * Builtin function implementations 52 | */ 53 | 54 | /* 55 | * @brief Builtin command: change directory. 56 | * @param args List of args. args[0] is "cd". args[1] is the directory. 57 | * @return Always returns 1, to continue executing. 58 | */ 59 | int csh_cd(char **args) 60 | { 61 | if (args[1] == NULL) { 62 | fprintf(stderr, "csh: expected argument to \"cd\"\n"); 63 | } else { 64 | if (chdir(args[1]) != 0) { 65 | perror("csh"); 66 | } 67 | } 68 | return 1; 69 | } 70 | 71 | /* 72 | * @brief Builtin command: print help. 73 | * @param args List of args. Not examined. 74 | * @return Always return 1, to continue executing. 75 | */ 76 | int csh_help(char **args) 77 | { 78 | int i; 79 | printf("A simple shell in C\n"); 80 | printf("Type program names and arguments, and press enter.\n"); 81 | printf("The following are built in:\n"); 82 | 83 | for (i = 0; i < csh_num_builtins(); i++) { 84 | printf(" %s\n", builtin_str[i]); 85 | } 86 | 87 | printf("Use the man command for information on other programs.\n"); 88 | return 1; 89 | } 90 | 91 | /* 92 | * @brief Builtin command: print hello and current time. 93 | * @param args List of args. Not examined. 94 | * @return Always return 1, to continue executing. 95 | */ 96 | int csh_hello(char **args) 97 | { 98 | time_t rawtime; 99 | struct tm * timeinfo; 100 | 101 | time(&rawtime); 102 | timeinfo = localtime(&rawtime); 103 | printf("Hello, Leslie Van.\n"); 104 | printf("Current local time and date: %s", asctime(timeinfo)); 105 | return 1; 106 | } 107 | 108 | /* 109 | * @brief Builtin command: print kernel info. 110 | * @param args List of args. Not examined. 111 | * @return Always return 1, to continue executing. 112 | */ 113 | int csh_print_info(char **args) 114 | { 115 | system("uname -a"); 116 | return 1; 117 | } 118 | 119 | /* 120 | * @brief Builtin command: exit. 121 | * @param args List of args. Not examined. 122 | * @return Always return 0, to terminate execution. 123 | */ 124 | int csh_exit(char **args) 125 | { 126 | return 0; 127 | } 128 | 129 | /* 130 | * @brief Launch a program and wait for it to terminate 131 | * @param args Null terminated list of arguments. 132 | * @return Always return 1, to continue executing. 133 | */ 134 | int csh_launch(char **args) 135 | { 136 | pid_t pid, wpid; 137 | int status; 138 | 139 | pid = fork(); 140 | if (pid == 0) { 141 | // Child process 142 | if (execvp(args[0], args) == -1) { 143 | perror("csh"); 144 | } 145 | exit(EXIT_FAILURE); 146 | } else if (pid < 0) { 147 | // Error forking 148 | perror("csh"); 149 | } else { 150 | // Parent process 151 | do { 152 | wpid = waitpid(pid, &status, WUNTRACED); 153 | } while (!WIFEXITED(status) && !WIFSIGNALED(status)); 154 | } 155 | 156 | return 1; 157 | } 158 | 159 | /* 160 | * @brief Execute shell built-in or launch program. 161 | * @param args Null terminated list of arguments. 162 | * @return 1 if the shell should continue running, 0 if it should terminate. 163 | */ 164 | int csh_execute(char **args) 165 | { 166 | int i; 167 | if (args[0] == NULL) { 168 | // An empty command was entered 169 | return 1; 170 | } 171 | 172 | for (i = 0; i < csh_num_builtins(); i++) { 173 | if (strcmp(args[0], builtin_str[i]) == 0) { 174 | return (*builtin_func[i])(args); 175 | } 176 | } 177 | 178 | // return csh_launch(args); 179 | printf("Command not found.\n"); 180 | return 1; 181 | } 182 | 183 | /* 184 | * @brief Read a line of input from stdin. 185 | * @return The line from stdin. 186 | */ 187 | char *csh_read_line(void) 188 | { 189 | char *line = NULL; 190 | ssize_t bufsize = 0; 191 | getline(&line, &bufsize, stdin); 192 | return line; 193 | } 194 | 195 | #define CSH_TOK_BUFSIZE 64 196 | #define CSH_TOK_DELIM " \t\r\n\a" 197 | /* 198 | * @brief Split a line into tokens. 199 | * @param line The line. 200 | * @return Null-terminated array of tokens. 201 | */ 202 | char **csh_split_line(char *line) 203 | { 204 | int bufsize = CSH_TOK_BUFSIZE, position = 0; 205 | char **tokens = malloc(bufsize * sizeof(char*)); 206 | char *token; 207 | 208 | if (!tokens) { 209 | fprintf(stderr, "csh: allocation error\n"); 210 | exit(EXIT_FAILURE); 211 | } 212 | 213 | token = strtok(line, CSH_TOK_DELIM); 214 | while (token != NULL) { 215 | tokens[position] = token; 216 | position++; 217 | 218 | if (position >= bufsize) { 219 | bufsize += CSH_TOK_BUFSIZE; 220 | tokens = realloc(tokens, bufsize * sizeof(char*)); 221 | if (!tokens) { 222 | fprintf(stderr, "csh: allocation error\n"); 223 | exit(EXIT_FAILURE); 224 | } 225 | } 226 | 227 | token = strtok(NULL, CSH_TOK_DELIM); 228 | } 229 | tokens[position] = NULL; 230 | return tokens; 231 | } 232 | 233 | /* 234 | * @brief Loop getting input and execting it. 235 | */ 236 | void csh_loop(void) 237 | { 238 | char *line; 239 | char **args; 240 | int status; 241 | 242 | do { 243 | printf("> "); 244 | line = csh_read_line(); 245 | args = csh_split_line(line); 246 | status = csh_execute(args); 247 | 248 | free(line); 249 | free(args); 250 | } while (status); 251 | } 252 | 253 | /* 254 | * @brief Main entry point. 255 | * @param argc Argument count. 256 | * @param argv Argument vector. 257 | * @return status code. 258 | */ 259 | int main(int argc, char **argv) 260 | { 261 | csh_loop(); 262 | 263 | return EXIT_SUCCESS; 264 | } 265 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(exp3_2 C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 6 | 7 | add_executable(exp3_2 main.c) -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_2/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leslievan/Operator_System/a4ab78afdf3423b6ad0a72783e3d91e75abf0e71/Operator_System_Lab3/Operator_System_Exp3_2/main -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_2/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @author Arcana 4 | * @date 2018.11.12 5 | * @brief Children process communicate with parent by pipe. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define BUF_MAX_SIZE 8192 21 | #define CHECK(x) \ 22 | do { \ 23 | if (!(x)) { \ 24 | fprintf(stderr, "%s:%d: ", __func__, __LINE__); \ 25 | perror(#x); \ 26 | exit(-1); \ 27 | } \ 28 | } while (0) 29 | 30 | /** 31 | * Create three children processes to test pipe communication. 32 | * @param argc Argument count. 33 | * @param argv Argument vector. 34 | * @return status code. 35 | */ 36 | int main(int argc, char **argv) { 37 | int pipefd[2], pid, i = 0; 38 | int flag = 0; 39 | ssize_t n; 40 | char buf[BUF_MAX_SIZE]; 41 | char str[BUF_MAX_SIZE]; 42 | sem_t *write_mutex; 43 | sem_t *read_mutex1; 44 | sem_t *read_mutex2; 45 | write_mutex = sem_open("pipe_test_wm", O_CREAT | O_RDWR, 0666, 0); 46 | read_mutex1 = sem_open("pipe_test_rm_1", O_CREAT | O_RDWR, 0666, 0); 47 | read_mutex2 = sem_open("pipe_test_rm_2", O_CREAT | O_RDWR, 0666, 0); 48 | 49 | memset(buf, 0, BUF_MAX_SIZE); 50 | memset(str, 0, BUF_MAX_SIZE); 51 | 52 | CHECK(pipe(pipefd) >= 0); 53 | CHECK((pid = fork()) >= 0); 54 | 55 | if (pid == 0) { 56 | int count = 0; 57 | close(pipefd[0]); 58 | int flags = fcntl(pipefd[1], F_GETFL); 59 | fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK); 60 | while (!flag) { 61 | n = write(pipefd[1], buf, BUF_MAX_SIZE); 62 | if (n == -1) { 63 | flag = 1; 64 | } else { 65 | count++; 66 | printf("children 1 write %dB\n", n); 67 | } 68 | } 69 | printf("space = %dKB\n", (count * BUF_MAX_SIZE) / 1024); 70 | exit(0); 71 | } 72 | 73 | CHECK((pid = fork()) >= 0); 74 | if (pid == 0) { 75 | sem_wait(write_mutex); 76 | close(pipefd[0]); 77 | n = write(pipefd[1], "This is the second children.\n", 29); 78 | printf("children 2 write %dB\n", n); 79 | sem_post(write_mutex); 80 | sem_post(read_mutex1); 81 | exit(0); 82 | } 83 | 84 | CHECK((pid = fork()) >= 0); 85 | if (pid == 0) { 86 | sem_wait(write_mutex); 87 | close(pipefd[0]); 88 | n = write(pipefd[1], "This is the third children.\n", 28); 89 | printf("children 3 write %dB\n", n); 90 | sem_post(write_mutex); 91 | sem_post(read_mutex2); 92 | exit(0); 93 | } 94 | 95 | wait(0); 96 | close(pipefd[1]); 97 | int flags = fcntl(pipefd[0], F_GETFL); 98 | fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK); 99 | while (!flag) { 100 | n = read(pipefd[0], str, BUF_MAX_SIZE); 101 | if (n == -1) { 102 | flag = 1; 103 | } else { 104 | printf("%dB read\n", n); 105 | } 106 | } 107 | sem_post(write_mutex); 108 | 109 | sem_wait(read_mutex1); 110 | sem_wait(read_mutex2); 111 | n = read(pipefd[0], str, BUF_MAX_SIZE); 112 | printf("%dB read\n", n); 113 | for (i = 0; i < n; i++) { 114 | printf("%c", str[i]); 115 | } 116 | 117 | sem_close(write_mutex); 118 | sem_close(read_mutex1); 119 | sem_close(read_mutex2); 120 | sem_unlink("pipe_test_wm"); 121 | sem_unlink("pipe_test_rm_1"); 122 | sem_unlink("pipe_test_rm_2"); 123 | return 0; 124 | } -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(exp3_3 C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 6 | 7 | add_executable(exp3_3 main.c common.h) -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by leslie on 18-12-11. 3 | // 4 | 5 | #ifndef EXP3_3_COMMON_H 6 | #define EXP3_3_COMMON_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define QUEUE_ID 10086 19 | #define MAX_SIZE 1024 20 | #define MSG_STOP "exit" 21 | #define snd_to_rcv1 1 22 | #define snd_to_rcv2 2 23 | #define rcv_to_snd1 3 24 | #define rcv_to_snd2 4 25 | #define CHECK(x) \ 26 | do { \ 27 | if (!(x)) { \ 28 | fprintf(stderr, "%s:%d: ", __func__, __LINE__); \ 29 | perror(#x); \ 30 | exit(-1); \ 31 | } \ 32 | } while (0) \ 33 | 34 | #define P(x) sem_wait(&x) 35 | #define V(x) sem_post(&x) 36 | struct msg_st { 37 | long int message_type; 38 | char buffer[MAX_SIZE + 1]; 39 | }; 40 | 41 | /* function */ 42 | void *sender1(); 43 | void *sender2(); 44 | void *receiver(); 45 | 46 | /* global variable */ 47 | sem_t w_mutex, empty, full, over, rcv_dp, snd_dp; 48 | 49 | #endif //EXP3_3_COMMON_H 50 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @date 2018-11-26 4 | * @author Leslie Van 5 | * @brief Communicate by message queue between a receiver and two senders 6 | */ 7 | #include "common.h" 8 | 9 | /** 10 | * @brief Create mq and send message to receiver. 11 | * @return 12 | */ 13 | void *sender1() { 14 | int mq; 15 | struct msg_st buf; 16 | ssize_t bytes_read; 17 | 18 | /* open the mail queue */ 19 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 20 | CHECK((key_t) -1 != mq); 21 | 22 | do { 23 | P(w_mutex); 24 | P(snd_dp); 25 | printf("sender1> "); 26 | V(rcv_dp); 27 | fflush(stdout); 28 | fgets(buf.buffer, BUFSIZ, stdin); 29 | buf.message_type = snd_to_rcv1; 30 | /* send the message */ 31 | P(empty); 32 | CHECK(0 <= msgsnd(mq, (void*)&buf, MAX_SIZE, 0)); 33 | V(full); 34 | V(w_mutex); 35 | printf("\n"); 36 | } while (strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))); 37 | 38 | /* wait for response */ 39 | P(over); 40 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, rcv_to_snd1, 0); 41 | CHECK(bytes_read >= 0); 42 | printf("%s", buf.buffer); 43 | printf("--------------------------------------------\n"); 44 | V(snd_dp); 45 | pthread_exit(NULL); 46 | } 47 | 48 | /** 49 | * @brief Send message to receiver. 50 | * @return 51 | */ 52 | void *sender2() { 53 | int mq; 54 | struct msg_st buf; 55 | ssize_t bytes_read; 56 | 57 | /* open the mail queue */ 58 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 59 | CHECK((key_t) -1 != mq); 60 | 61 | do { 62 | P(w_mutex); 63 | P(snd_dp); 64 | printf("sender2> "); 65 | V(rcv_dp); 66 | fflush(stdout); 67 | fgets(buf.buffer, BUFSIZ, stdin); 68 | buf.message_type = snd_to_rcv2; 69 | /* send the message */ 70 | P(empty); 71 | CHECK(0 <= msgsnd(mq, (void *) &buf, MAX_SIZE, 0)); 72 | V(full); 73 | V(w_mutex); 74 | printf("\n"); 75 | } while (strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))); 76 | 77 | /* wait for response */ 78 | P(over); 79 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, rcv_to_snd2, 0); 80 | CHECK(bytes_read >= 0); 81 | printf("%s", buf.buffer); 82 | printf("--------------------------------------------\n"); 83 | V(snd_dp); 84 | pthread_exit(NULL); 85 | } 86 | 87 | /** 88 | * @brief Receive message from sender, and response when sender exit. 89 | * @return 90 | */ 91 | void *receiver() { 92 | struct msg_st buf, over1, over2; 93 | int mq, must_stop = 2; 94 | struct msqid_ds t; 95 | over1.message_type = 3; 96 | strcpy(over1.buffer, "over1\n"); 97 | over2.message_type = 4; 98 | strcpy(over2.buffer, "over2\n"); 99 | 100 | /* open the mail queue */ 101 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 102 | CHECK((key_t) -1 != mq); 103 | 104 | do { 105 | ssize_t bytes_read, bytes_write; 106 | /* receive the message */ 107 | P(full); 108 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, 0, 0); 109 | V(empty); 110 | CHECK(bytes_read >= 0); 111 | if (!strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))) { 112 | if (buf.message_type == 1) { 113 | bytes_write = msgsnd(mq, (void *) &over1, MAX_SIZE, 0); 114 | CHECK(bytes_write >= 0); 115 | V(over); 116 | must_stop--; 117 | } else if (buf.message_type == 2) { 118 | bytes_write = msgsnd(mq, (void *) &over2, MAX_SIZE, 0); 119 | CHECK(bytes_write >= 0); 120 | V(over); 121 | must_stop--; 122 | } 123 | } else { 124 | P(rcv_dp); 125 | printf("Received%d: %s", buf.message_type, buf.buffer); 126 | printf("--------------------------------------------\n"); 127 | V(snd_dp); 128 | } 129 | } while (must_stop); 130 | 131 | 132 | /* cleanup */ 133 | P(snd_dp); 134 | CHECK(!msgctl(mq, IPC_RMID, &t)); 135 | pthread_exit(NULL); 136 | } 137 | 138 | /** 139 | * Create three thread to test functions 140 | * @param argc Argument count 141 | * @param argv Argument vector 142 | * @return Always 0 143 | */ 144 | int main(int argc, char **argv) { 145 | pthread_t t1, t2, t3; 146 | int state; 147 | 148 | sem_init(&snd_dp, 1, 1); 149 | sem_init(&rcv_dp, 1, 0); 150 | sem_init(&empty, 1, 10); 151 | sem_init(&full, 1, 0); 152 | sem_init(&w_mutex, 1, 1); 153 | sem_init(&over, 1, 0); 154 | 155 | state = pthread_create(&t1, NULL, receiver, NULL); 156 | CHECK(state == 0); 157 | state = pthread_create(&t3, NULL, sender1, NULL); 158 | CHECK(state == 0); 159 | state = pthread_create(&t2, NULL, sender2, NULL); 160 | CHECK(state == 0); 161 | 162 | pthread_join(t3, NULL); 163 | pthread_join(t2, NULL); 164 | pthread_join(t1, NULL); 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3_fake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(Operator_System_Exp3_3_fake C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 6 | add_executable(Operator_System_Exp3_3_fake main.c common.h) -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3_fake/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by leslie on 18-12-18. 3 | // 4 | 5 | #ifndef OPERATOR_SYSTEM_EXP3_3_FAKE_COMMON_H 6 | #define OPERATOR_SYSTEM_EXP3_3_FAKE_COMMON_H 7 | 8 | #endif //OPERATOR_SYSTEM_EXP3_3_FAKE_COMMON_H 9 | // 10 | // Created by leslie on 18-12-11. 11 | // 12 | 13 | #ifndef EXP3_3_COMMON_H 14 | #define EXP3_3_COMMON_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define QUEUE_ID 10086 27 | #define MAX_SIZE 1024 28 | #define MSG_STOP "exit" 29 | #define snd_to_rcv1 1 30 | #define snd_to_rcv2 2 31 | #define rcv_to_snd1 3 32 | #define rcv_to_snd2 4 33 | #define CHECK(x) \ 34 | do { \ 35 | if (!(x)) { \ 36 | fprintf(stderr, "%s:%d: ", __func__, __LINE__); \ 37 | perror(#x); \ 38 | exit(-1); \ 39 | } \ 40 | } while (0) \ 41 | 42 | #define P(x) sem_wait(&x) 43 | #define V(x) sem_post(&x) 44 | struct msg_st { 45 | long int message_type; 46 | char buffer[MAX_SIZE + 1]; 47 | }; 48 | 49 | /* function */ 50 | void *sender1(); 51 | void *sender2(); 52 | void *receiver(); 53 | 54 | /* global variable */ 55 | sem_t rcv_mutex, snd_mutex; 56 | 57 | #endif //EXP3_3_COMMON_H 58 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_3_fake/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @date 2018-12-18 4 | * @author Leslie Van 5 | * @brief Communicate by message queue between a receiver and two senders(fake). 6 | */ 7 | #include "common.h" 8 | 9 | /** 10 | * @brief Create mq and send message to receiver. 11 | * @return 12 | */ 13 | void *sender1() { 14 | int mq; 15 | struct msg_st buf; 16 | ssize_t bytes_read; 17 | 18 | /* open the mail queue */ 19 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 20 | CHECK((key_t) -1 != mq); 21 | 22 | do { 23 | P(snd_mutex); 24 | printf("sender1> "); 25 | fflush(stdout); 26 | fgets(buf.buffer, BUFSIZ, stdin); 27 | buf.message_type = snd_to_rcv1; 28 | /* send the message */ 29 | CHECK(0 <= msgsnd(mq, (void *) &buf, MAX_SIZE, 0)); 30 | V(rcv_mutex); 31 | } while (strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))); 32 | 33 | /* wait for response */ 34 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, rcv_to_snd1, 0); 35 | CHECK(bytes_read >= 0); 36 | printf("%s", buf.buffer); 37 | printf("--------------------------------------------\n"); 38 | V(snd_mutex); 39 | pthread_exit(NULL); 40 | } 41 | 42 | /** 43 | * @brief Send message to receiver. 44 | * @return 45 | */ 46 | void *sender2() { 47 | int mq; 48 | struct msg_st buf; 49 | ssize_t bytes_read; 50 | 51 | /* open the mail queue */ 52 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 53 | CHECK((key_t) -1 != mq); 54 | 55 | do { 56 | P(snd_mutex); 57 | printf("sender2> "); 58 | fflush(stdout); 59 | fgets(buf.buffer, BUFSIZ, stdin); 60 | buf.message_type = snd_to_rcv2; 61 | /* send the message */ 62 | CHECK(0 <= msgsnd(mq, (void *) &buf, MAX_SIZE, 0)); 63 | V(rcv_mutex); 64 | } while (strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))); 65 | 66 | /* wait for response */ 67 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, rcv_to_snd2, 0); 68 | CHECK(bytes_read >= 0); 69 | printf("%s", buf.buffer); 70 | printf("--------------------------------------------\n"); 71 | V(snd_mutex); 72 | pthread_exit(NULL); 73 | } 74 | 75 | /** 76 | * @brief Receive message from sender, and response when sender exit. 77 | * @return 78 | */ 79 | void *receiver() { 80 | struct msg_st buf, over1, over2; 81 | int mq, must_stop = 2; 82 | struct msqid_ds t; 83 | over1.message_type = 3; 84 | strcpy(over1.buffer, "over1\n"); 85 | over2.message_type = 4; 86 | strcpy(over2.buffer, "over2\n"); 87 | 88 | /* open the mail queue */ 89 | mq = msgget((key_t) QUEUE_ID, 0666 | IPC_CREAT); 90 | CHECK((key_t) -1 != mq); 91 | 92 | do { 93 | ssize_t bytes_read, bytes_write; 94 | /* receive the message */ 95 | P(rcv_mutex); 96 | 97 | bytes_read = msgrcv(mq, (void *) &buf, MAX_SIZE, 0, 0); 98 | CHECK(bytes_read >= 0); 99 | if (!strncmp(buf.buffer, MSG_STOP, strlen(MSG_STOP))) { 100 | if (buf.message_type == 1) { 101 | bytes_write = msgsnd(mq, (void *) &over1, MAX_SIZE, 0); 102 | CHECK(bytes_write >= 0); 103 | must_stop--; 104 | } else if (buf.message_type == 2) { 105 | bytes_write = msgsnd(mq, (void *) &over2, MAX_SIZE, 0); 106 | CHECK(bytes_write >= 0); 107 | must_stop--; 108 | } 109 | } else { 110 | printf("Received%d: %s", buf.message_type, buf.buffer); 111 | printf("--------------------------------------------\n"); 112 | V(snd_mutex); 113 | } 114 | } while (must_stop); 115 | 116 | 117 | /* cleanup */ 118 | CHECK(!msgctl(mq, IPC_RMID, &t)); 119 | pthread_exit(NULL); 120 | } 121 | 122 | /** 123 | * Create three thread to test functions 124 | * @param argc Argument count 125 | * @param argv Argument vector 126 | * @return Always 0 127 | */ 128 | int main(int argc, char **argv) { 129 | pthread_t rcv_pid, snd2_pid, snd1_pid; 130 | int state; 131 | 132 | sem_init(&snd_mutex, 0, 1); 133 | sem_init(&rcv_mutex, 0, 0); 134 | 135 | state = pthread_create(&rcv_pid, NULL, receiver, NULL); 136 | CHECK(state == 0); 137 | state = pthread_create(&snd1_pid, NULL, sender1, NULL); 138 | CHECK(state == 0); 139 | state = pthread_create(&snd2_pid, NULL, sender2, NULL); 140 | CHECK(state == 0); 141 | 142 | pthread_join(snd1_pid, NULL); 143 | pthread_join(snd2_pid, NULL); 144 | pthread_join(rcv_pid, NULL); 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(exp3_4 C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 6 | add_executable(exp3_4_sender sender.c common.h) 7 | add_executable(exp3_4_receiver receiver.c common.h) -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_4/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by leslie on 18-12-11. 3 | // 4 | 5 | #ifndef EXP3_4_COMMON_H 6 | #define EXP3_4_COMMON_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define FULL_PATH "shm_sgn_full" 18 | #define EMPTY_PATH "shm_sgn_empty" 19 | #define RTS_PATH "shm_sgn_rts" 20 | #define MSG_STOP "exit" 21 | #define MAX_SIZE 1024 22 | #define CHECK(x) \ 23 | do { \ 24 | if (!(x)) { \ 25 | fprintf(stderr, "%s:%d: ", __func__, __LINE__); \ 26 | perror(#x); \ 27 | exit(-1); \ 28 | } \ 29 | } while (0) \ 30 | 31 | #define P(x) sem_wait(x) 32 | #define V(x) sem_post(x) 33 | struct sm_st { 34 | char data[MAX_SIZE]; 35 | }; 36 | 37 | sem_t *full, *empty, *rcv_to_snd; 38 | 39 | #endif //EXP3_4_COMMON_H 40 | -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_4/receiver.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file receiver.c 3 | * 4 | * @date 2018-12-11 5 | * 6 | * @author Leslie 7 | * 8 | * @brief Receive message by shared memory. Communicate between two processes with shared memory. 9 | */ 10 | 11 | #include "common.h" 12 | 13 | int main(int argc, char **argv) { 14 | full = sem_open("shm_sgn_full", O_CREAT | O_RDWR, 0666, 0); 15 | empty = sem_open("shm_sgn_empty", O_CREAT | O_RDWR, 0666, 1); 16 | rcv_to_snd = sem_open("shm_sgn_rts", O_CREAT | O_RDWR, 0666, 0); 17 | void *shm = NULL; 18 | struct sm_st *shared; 19 | int shmid, count = 0, must_stop = 0; 20 | key_t sm_id = ftok("tok", 1); 21 | 22 | shmid = shmget(sm_id, sizeof(struct sm_st), 0666 | IPC_CREAT); 23 | CHECK(shmid >= 0); 24 | shm = shmat(shmid, 0, 0); 25 | CHECK(shm >= 0); 26 | shared = (struct sm_st *) shm; 27 | 28 | do { 29 | P(full); 30 | if (!strncmp(shared->data, MSG_STOP, strlen(MSG_STOP))) { 31 | must_stop = 1; 32 | } else { 33 | count++; 34 | printf("[%d]\n", count); 35 | printf("[*]receive: %s\n", shared->data); 36 | } 37 | V(empty); 38 | } while (!must_stop); 39 | 40 | P(empty); 41 | strcpy(shared->data, "over"); 42 | V(rcv_to_snd); 43 | V(full); 44 | 45 | CHECK(shmdt(shared) == 0); 46 | CHECK(sem_close(full) == 0); 47 | CHECK(sem_close(empty) == 0); 48 | CHECK(sem_close(rcv_to_snd) == 0); 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /Operator_System_Lab3/Operator_System_Exp3_4/sender.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file receiver.c 3 | * 4 | * @date 2018-12-11 5 | * 6 | * @author Leslie 7 | * 8 | * @brief Send message by shared memory. 9 | */ 10 | 11 | #include "common.h" 12 | 13 | int main() { 14 | full = sem_open(FULL_PATH, O_CREAT | O_RDWR, 0666, 0); 15 | empty = sem_open(EMPTY_PATH, O_CREAT | O_RDWR, 0666, 1); 16 | rcv_to_snd = sem_open(RTS_PATH, O_CREAT | O_RDWR, 0666, 0); 17 | void *shm = NULL; 18 | struct sm_st *shared; 19 | int shmid, count = 0; 20 | key_t sm_id = ftok("tok", 1); 21 | 22 | shmid = shmget(sm_id, sizeof(struct sm_st), 0666 | IPC_CREAT); 23 | CHECK(shmid >= 0); 24 | shm = shmat(shmid, 0, 0); 25 | CHECK(shm >= 0); 26 | shared = (struct sm_st *) shm; 27 | 28 | do { 29 | P(empty); 30 | printf("sender> "); 31 | fflush(stdout); 32 | memset(shared->data, 0, MAX_SIZE); 33 | fgets(shared->data, MAX_SIZE, stdin); 34 | V(full); 35 | } while (strncmp(shared->data, MSG_STOP, strlen(MSG_STOP))); 36 | 37 | P(rcv_to_snd); 38 | P(full); 39 | printf("---------------------------\n"); 40 | printf("receive: %s\n", shared->data); 41 | V(empty); 42 | 43 | sleep(1); 44 | CHECK(shmdt(shared) == 0); 45 | CHECK(shmctl(shmid, IPC_RMID, 0) == 0); 46 | CHECK(sem_close(full) == 0); 47 | CHECK(sem_close(empty) == 0); 48 | CHECK(sem_close(rcv_to_snd) == 0); 49 | CHECK(sem_unlink(EMPTY_PATH) == 0); 50 | CHECK(sem_unlink(FULL_PATH) == 0); 51 | CHECK(sem_unlink(RTS_PATH) == 0); 52 | return 0; 53 | } -------------------------------------------------------------------------------- /Operator_System_Lab5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(Operator_System_Exp5 C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | 6 | add_executable(Operator_System_Exp5 main.c simplefs.h simplefs.c) -------------------------------------------------------------------------------- /Operator_System_Lab5/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leslievan/Operator_System/a4ab78afdf3423b6ad0a72783e3d91e75abf0e71/Operator_System_Lab5/main -------------------------------------------------------------------------------- /Operator_System_Lab5/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @brief 4 | * @author 5 | * @date 2018-12-19 to 2019-1-3 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "simplefs.h" 15 | 16 | 17 | /** List of builtin commands, followed by their corresponding functions. */ 18 | char *builtin_str[] = { 19 | "format", 20 | "cd", 21 | "mkdir", 22 | "rmdir", 23 | "ls", 24 | "create", 25 | "rm", 26 | "write", 27 | "read", 28 | "exit", 29 | "open", 30 | "close", 31 | "pwd" 32 | }; 33 | 34 | int (*builtin_func[])(char **) = { 35 | &my_format, 36 | &my_cd, 37 | &my_mkdir, 38 | &my_rmdir, 39 | &my_ls, 40 | &my_create, 41 | &my_rm, 42 | &my_write, 43 | &my_read, 44 | &my_exit_sys, 45 | &my_open, 46 | &my_close, 47 | &my_pwd 48 | }; 49 | 50 | int csh_num_builtins(void) { 51 | return sizeof(builtin_str) / sizeof(char*); 52 | } 53 | /* 54 | * @brief Launch a program and wait for it to terminate 55 | * @param args Null terminated list of arguments. 56 | * @return Always return 1, to continue executing. 57 | */ 58 | int csh_launch(char **args) 59 | { 60 | pid_t pid, wpid; 61 | int status; 62 | 63 | pid = fork(); 64 | if (pid == 0) { 65 | // Child process 66 | if (execvp(args[0], args) == -1) { 67 | perror("csh"); 68 | } 69 | exit(EXIT_FAILURE); 70 | } else if (pid < 0) { 71 | // Error forking 72 | perror("csh"); 73 | } else { 74 | // Parent process 75 | do { 76 | wpid = waitpid(pid, &status, WUNTRACED); 77 | } while (!WIFEXITED(status) && !WIFSIGNALED(status)); 78 | } 79 | 80 | return 1; 81 | } 82 | 83 | /* 84 | * @brief Execute shell built-in or launch program. 85 | * @param args Null terminated list of arguments. 86 | * @return 1 if the shell should continue running, 0 if it should terminate. 87 | */ 88 | int csh_execute(char **args) 89 | { 90 | int i; 91 | if (args[0] == NULL) { 92 | // An empty command was entered 93 | return 1; 94 | } 95 | 96 | for (i = 0; i < csh_num_builtins(); i++) { 97 | if (strcmp(args[0], builtin_str[i]) == 0) { 98 | return (*builtin_func[i])(args); 99 | } 100 | } 101 | 102 | return csh_launch(args); 103 | } 104 | 105 | /* 106 | * @brief Read a line of input from stdin. 107 | * @return The line from stdin. 108 | */ 109 | char *csh_read_line(void) 110 | { 111 | char *line = NULL; 112 | ssize_t bufsize = 0; 113 | getline(&line, &bufsize, stdin); 114 | return line; 115 | } 116 | 117 | #define CSH_TOK_BUFSIZE 64 118 | #define CSH_TOK_DELIM " \t\r\n\a" 119 | /* 120 | * @brief Split a line into tokens. 121 | * @param line The line. 122 | * @return Null-terminated array of tokens. 123 | */ 124 | char **csh_split_line(char *line) 125 | { 126 | int bufsize = CSH_TOK_BUFSIZE, position = 0; 127 | char **tokens = malloc(bufsize * sizeof(char*)); 128 | char *token; 129 | 130 | if (!tokens) { 131 | fprintf(stderr, "csh: allocation error\n"); 132 | exit(EXIT_FAILURE); 133 | } 134 | 135 | token = strtok(line, CSH_TOK_DELIM); 136 | while (token != NULL) { 137 | tokens[position] = token; 138 | position++; 139 | 140 | if (position >= bufsize) { 141 | bufsize += CSH_TOK_BUFSIZE; 142 | tokens = realloc(tokens, bufsize * sizeof(char*)); 143 | if (!tokens) { 144 | fprintf(stderr, "csh: allocation error\n"); 145 | exit(EXIT_FAILURE); 146 | } 147 | } 148 | 149 | token = strtok(NULL, CSH_TOK_DELIM); 150 | } 151 | tokens[position] = NULL; 152 | return tokens; 153 | } 154 | 155 | /* 156 | * @brief Loop getting input and execting it. 157 | */ 158 | void csh_loop(void) 159 | { 160 | char *line; 161 | char **args; 162 | int status; 163 | 164 | do { 165 | printf("\n\e[1mleslie\e[0m@leslie-PC \e[1m%s\e[0m\n", current_dir); 166 | printf("> \e[032m$\e[0m "); 167 | line = csh_read_line(); 168 | args = csh_split_line(line); 169 | status = csh_execute(args); 170 | 171 | free(line); 172 | free(args); 173 | } while (status); 174 | } 175 | 176 | /* 177 | * @brief Main entry point. 178 | * @param argc Argument count. 179 | * @param argv Argument vector. 180 | * @return status code. 181 | */ 182 | int main(int argc, char **argv) 183 | { 184 | start_sys(); 185 | csh_loop(); 186 | 187 | return EXIT_SUCCESS; 188 | } 189 | -------------------------------------------------------------------------------- /Operator_System_Lab5/simplefs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simplefs.c 3 | * @brief Definition in FAT16 file system. 4 | * @details Macro definitions, structs such as FCB and FAT, and some global variable. 5 | * @author Leslie Van 6 | * @date 2018-12-19 to 2019-1-3 7 | */ 8 | 9 | #include "simplefs.h" 10 | 11 | 12 | /* Definition of functions */ 13 | /** 14 | * Start file system and initial variable. 15 | * @author Leslie Van 16 | */ 17 | int start_sys(void) { 18 | fs_head = (unsigned char *) malloc(DISK_SIZE); 19 | memset(fs_head, 0, DISK_SIZE); 20 | FILE *fp; 21 | int i; 22 | 23 | if ((fp = fopen(SYS_PATH, "r")) != NULL) { 24 | fread(fs_head, DISK_SIZE, 1, fp); 25 | fclose(fp); 26 | } else { 27 | printf("System is not initialized, now install it and create system file.\n"); 28 | printf("Please don't leave program.\n"); 29 | printf("Initialed success!\n"); 30 | do_format(); 31 | } 32 | 33 | /**< Init the first openfile entry. */ 34 | fcb_cpy(&openfile_list[0].open_fcb, ((fcb *) (fs_head + 5 * BLOCK_SIZE))); 35 | strcpy(openfile_list[0].dir, ROOT); 36 | openfile_list[0].count = 0; 37 | openfile_list[0].fcb_state = 0; 38 | openfile_list[0].free = 1; 39 | curdir = 0; 40 | 41 | /**< Init the other openfile entry. */ 42 | fcb *empty = (fcb *) malloc(sizeof(fcb)); 43 | set_fcb(empty, "\0", "\0", 0, 0, 0, 0); 44 | for (i = 1; i < MAX_OPENFILE; i++) { 45 | fcb_cpy(&openfile_list[i].open_fcb, empty); 46 | strcpy(openfile_list[i].dir, "\0"); 47 | openfile_list[i].free = 0; 48 | openfile_list[i].count = 0; 49 | openfile_list[i].fcb_state = 0; 50 | } 51 | 52 | /**< Init global variables. */ 53 | strcpy(current_dir, openfile_list[curdir].dir); 54 | start = ((block0 *) fs_head)->start_block; 55 | free(empty); 56 | return 0; 57 | } 58 | 59 | /** 60 | * Entry for command "format". 61 | * @author Leslie Van 62 | */ 63 | int my_format(char **args) { 64 | unsigned char *ptr; 65 | FILE *fp; 66 | int i; 67 | 68 | /**< Check argument count. */ 69 | for (i = 0; args[i] != NULL; i++); 70 | if (i > 2) { 71 | fprintf(stderr, "format: expected argument to \"format\"\n"); 72 | return 1; 73 | } 74 | 75 | /**< Check argument value. */ 76 | if (args[1] != NULL) { 77 | /**< Fill with 0. */ 78 | if (!strcmp(args[1], "-x")) { 79 | ptr = (unsigned char *) malloc(DISK_SIZE); 80 | memset(ptr, 0, DISK_SIZE); 81 | fp = fopen(SYS_PATH, "w"); 82 | fwrite(ptr, DISK_SIZE, 1, fp); 83 | free(ptr); 84 | fclose(fp); 85 | } else { 86 | fprintf(stderr, "format: expected argument to \"format\"\n"); 87 | return 1; 88 | } 89 | } 90 | do_format(); 91 | 92 | return 1; 93 | } 94 | 95 | /** 96 | * Fast format file system. 97 | * Create boot block, file allocation tables and root directory. 98 | * @author Leslie Van 99 | */ 100 | int do_format(void) { 101 | unsigned char *ptr = fs_head; 102 | int i; 103 | int first, second; 104 | FILE *fp; 105 | 106 | /**< Init the boot block(block0). */ 107 | block0 *init_block = (block0 *) ptr; 108 | strcpy(init_block->information, 109 | "Disk Size = 1MB, Block Size = 1KB, Block0 in 0, FAT0/1 in 1/3, Root Directory in 5"); 110 | init_block->root = 5; 111 | init_block->start_block = (unsigned char *) (init_block + BLOCK_SIZE * 7); 112 | ptr += BLOCK_SIZE; 113 | 114 | /**< Init FAT0/1. */ 115 | set_free(0, 0, 2); 116 | 117 | /**< Allocate 5 blocks to one block0(1) and two fat(2). */ 118 | set_free(get_free(1), 1, 0); 119 | set_free(get_free(2), 2, 0); 120 | set_free(get_free(2), 2, 0); 121 | 122 | ptr += BLOCK_SIZE * 4; 123 | 124 | /**< 2 blocks to root directory. */ 125 | fcb *root = (fcb *) ptr; 126 | first = get_free(ROOT_BLOCK_NUM); 127 | set_free(first, ROOT_BLOCK_NUM, 0); 128 | set_fcb(root, ".", "di", 0, first, BLOCK_SIZE * 2, 1); 129 | root++; 130 | set_fcb(root, "..", "di", 0, first, BLOCK_SIZE * 2, 1); 131 | root++; 132 | 133 | for (i = 2; i < BLOCK_SIZE * 2 / sizeof(fcb); i++, root++) { 134 | root->free = 0; 135 | } 136 | 137 | memset(fs_head + BLOCK_SIZE * 7, 'a', 15); 138 | /**< Write back. */ 139 | fp = fopen(SYS_PATH, "w"); 140 | fwrite(fs_head, DISK_SIZE, 1, fp); 141 | fclose(fp); 142 | } 143 | 144 | /** 145 | * Change current directory. 146 | * @param args 147 | * @return Always 1. 148 | */ 149 | int my_cd(char **args) { 150 | int i; 151 | int fd; 152 | char abspath[PATHLENGTH]; 153 | fcb *dir; 154 | 155 | /**< Check argument count. */ 156 | for (i = 0; args[i] != NULL; i++); 157 | if (i != 2) { 158 | fprintf(stderr, "cd: expected argument to \"format\"\n"); 159 | return 1; 160 | } 161 | 162 | /**< Check argument value. */ 163 | memset(abspath, '\0', PATHLENGTH); 164 | get_abspath(abspath, args[1]); 165 | dir = find_fcb(abspath); 166 | if (dir == NULL || dir->attribute == 1) { 167 | fprintf(stderr, "cd: No such folder\n"); 168 | return 1; 169 | } 170 | 171 | /**< Check if the folder fcb exist in openfile_list. */ 172 | for (i = 0; i < MAX_OPENFILE; i++) { 173 | if (openfile_list[i].free == 0) { 174 | continue; 175 | } 176 | 177 | if (!strcmp(dir->filename, openfile_list[i].open_fcb.filename) && 178 | dir->first == openfile_list[i].open_fcb.first) { 179 | /**< Folder is open. */ 180 | do_chdir(i); 181 | return 1; 182 | } 183 | } 184 | 185 | /**< Folder is close, open it and change current directory. */ 186 | if ((fd = do_open(abspath)) > 0) { 187 | do_chdir(fd); 188 | } 189 | 190 | return 1; 191 | } 192 | 193 | /** 194 | * Just do change directory action. 195 | * @param fd File descriptor of directory. 196 | */ 197 | void do_chdir(int fd) { 198 | curdir = fd; 199 | memset(current_dir, '\0', sizeof(current_dir)); 200 | strcpy(current_dir, openfile_list[curdir].dir); 201 | } 202 | 203 | /** 204 | * Display current directory. 205 | * @param args No argument. 206 | * @return Always 1. 207 | */ 208 | int my_pwd(char **args) { 209 | /**< Check argument count. */ 210 | if (args[1] != NULL) { 211 | fprintf(stderr, "pwd: too many arguments\n"); 212 | return 1; 213 | } 214 | 215 | printf("%s\n", current_dir); 216 | return 1; 217 | } 218 | 219 | /** 220 | * Create one or many directory once. 221 | * Provide function to create two or more directory once. 222 | * If par folder not exists, print error, others will continue. 223 | * @param args Folder names. 224 | * @return Always 1. 225 | */ 226 | int my_mkdir(char **args) { 227 | int i; 228 | char path[PATHLENGTH]; 229 | char parpath[PATHLENGTH], dirname[NAMELENGTH]; 230 | char *end; 231 | 232 | /**< Check argument count. */ 233 | if (args[1] == NULL) { 234 | fprintf(stderr, "mkdir: missing operand\n"); 235 | return 1; 236 | } 237 | 238 | /**< Do mkdir. */ 239 | for (i = 1; args[i] != NULL; i++) { 240 | /**< Split path into parent folder and current child folder. */ 241 | get_abspath(path, args[i]); 242 | end = strrchr(path, '/'); 243 | if (end == path) { 244 | strcpy(parpath, "/"); 245 | strcpy(dirname, path + 1); 246 | } else { 247 | strncpy(parpath, path, end - path); 248 | strcpy(dirname, end + 1); 249 | } 250 | 251 | if (find_fcb(parpath) == NULL) { 252 | fprintf(stderr, "create: cannot create \'%s\': Parent folder not exists\n", parpath); 253 | continue; 254 | } 255 | if (find_fcb(path) != NULL) { 256 | fprintf(stderr, "create: cannot create \'%s\': Folder or file exists\n", args[i]); 257 | continue; 258 | } 259 | 260 | do_mkdir(parpath, dirname); 261 | } 262 | 263 | return 1; 264 | } 265 | 266 | /** 267 | * Just do create directory. 268 | * @param parpath Par folder of the folder you want to create. 269 | * @param dirname Folder name you want to create. 270 | * @return Error with -1, else return 0. 271 | */ 272 | int do_mkdir(const char *parpath, const char *dirname) { 273 | int second = get_free(1); 274 | int i, flag = 0, first = find_fcb(parpath)->first; 275 | fcb *dir = (fcb *) (fs_head + BLOCK_SIZE * first); 276 | 277 | /**< Check for free fcb. */ 278 | for (i = 0; i < BLOCK_SIZE / sizeof(fcb); i++, dir++) { 279 | if (dir->free == 0) { 280 | flag = 1; 281 | break; 282 | } 283 | } 284 | if (!flag) { 285 | fprintf(stderr, "mkdir: Cannot create more file in %s\n", parpath); 286 | return -1; 287 | } 288 | 289 | /**< Check for free space. */ 290 | if (second == -1) { 291 | fprintf(stderr, "mkdir: No more space\n"); 292 | return -1; 293 | } 294 | set_free(second, 1, 0); 295 | 296 | /**< Set fcb and init folder. */ 297 | set_fcb(dir, dirname, "di", 0, second, BLOCK_SIZE, 1); 298 | init_folder(first, second); 299 | return 0; 300 | } 301 | 302 | /** 303 | * Remove folder one or more once. 304 | * @param args Folders name you want remove. 305 | */ 306 | int my_rmdir(char **args) { 307 | int i, j; 308 | fcb *dir; 309 | 310 | /**< Check argument count. */ 311 | if (args[1] == NULL) { 312 | fprintf(stderr, "rmdir: missing operand\n"); 313 | return 1; 314 | } 315 | 316 | /**< Do remove. */ 317 | for (i = 1; args[i] != NULL; i++) { 318 | if (!strcmp(args[i], ".") || !strcmp(args[i], "..")) { 319 | fprintf(stderr, "rmdir: cannot remove %s: '.' or '..' is read only \n", args[i]); 320 | return 1; 321 | } 322 | 323 | if (!strcmp(args[i], "/")) { 324 | fprintf(stderr, "rmdir: Permission denied\n"); 325 | return 1; 326 | } 327 | 328 | dir = find_fcb(args[i]); 329 | if (dir == NULL) { 330 | fprintf(stderr, "rmdir: cannot remove %s: No such folder\n", args[i]); 331 | return 1; 332 | } 333 | 334 | if (dir->attribute == 1) { 335 | fprintf(stderr, "rmdir: cannot remove %s: Is a directory\n", args[i]); 336 | return 1; 337 | } 338 | 339 | /**< Check if the folder fcb exist in openfile_list. */ 340 | for (j = 0; j < MAX_OPENFILE; j++) { 341 | if (openfile_list[j].free == 0) { 342 | continue; 343 | } 344 | 345 | if (!strcmp(dir->filename, openfile_list[j].open_fcb.filename) && 346 | dir->first == openfile_list[j].open_fcb.first) { 347 | /**< Folder is open. */ 348 | fprintf(stderr, "rmdir: cannot remove %s: File is open\n", args[i]); 349 | return 1; 350 | } 351 | } 352 | 353 | do_rmdir(dir); 354 | } 355 | return 1; 356 | } 357 | 358 | /** 359 | * Just do remove directory. 360 | */ 361 | void do_rmdir(fcb *dir) { 362 | int first = dir->first; 363 | 364 | dir->free = 0; 365 | dir = (fcb *) (fs_head + BLOCK_SIZE * first); 366 | dir->free = 0; 367 | dir++; 368 | dir->free = 0; 369 | 370 | set_free(first, 1, 1); 371 | } 372 | 373 | /** 374 | * Show all thing in folder. 375 | * @param args Empty to show current folder. '-l' to show by a long format. 'path' to show a specific folder. 376 | * @return Always 1. 377 | */ 378 | int my_ls(char **args) { 379 | int first = openfile_list[curdir].open_fcb.first; 380 | int i, mode = 'n'; 381 | int flag[3]; 382 | fcb *dir; 383 | 384 | /**< Check argument count. */ 385 | for (i = 0; args[i] != NULL; i++) { 386 | flag[i] = 0; 387 | } 388 | if (i > 3) { 389 | fprintf(stderr, "ls: expected argument\n"); 390 | return 1; 391 | } 392 | 393 | flag[0] = 1; 394 | for (i = 1; args[i] != NULL; i++) { 395 | if (args[i][0] == '-') { 396 | flag[i] = 1; 397 | if (!strcmp(args[i], "-l")) { 398 | mode = 'l'; 399 | break; 400 | } else { 401 | fprintf(stderr, "ls: wrong operand\n"); 402 | return 1; 403 | } 404 | } 405 | } 406 | 407 | for (i = 1; args[i] != NULL; i++) { 408 | if (flag[i] == 0) { 409 | dir = find_fcb(args[i]); 410 | if (dir != NULL && dir->attribute == 0) { 411 | first = dir->first; 412 | } else { 413 | fprintf(stderr, "ls: cannot access '%s': No such file or directory\n", args[i]); 414 | return 1; 415 | } 416 | break; 417 | } 418 | } 419 | 420 | do_ls(first, mode); 421 | 422 | return 1; 423 | } 424 | 425 | /** 426 | * Just do ls. 427 | * @param first First block of folder you want to show. 428 | * @param mode 'n' to normal format, and 'l' to long format. 429 | */ 430 | void do_ls(int first, char mode) { 431 | int i, count, length = BLOCK_SIZE; 432 | char fullname[NAMELENGTH], date[16], time[16]; 433 | fcb *root = (fcb *) (fs_head + BLOCK_SIZE * first); 434 | block0 *init_block = (block0 *) fs_head; 435 | if (first == init_block->root) { 436 | length = ROOT_BLOCK_NUM * BLOCK_SIZE; 437 | } 438 | 439 | if (mode == 'n') { 440 | for (i = 0, count = 1; i < length / sizeof(fcb); i++, root++) { 441 | /**< Check if the fcb is used. */ 442 | if (root->free == 0) { 443 | continue; 444 | } 445 | 446 | if (root->attribute == 0) { 447 | printf("%s", FOLDER_COLOR); 448 | printf("%s\t", root->filename); 449 | printf("%s", DEFAULT_COLOR); 450 | } else { 451 | get_fullname(fullname, root); 452 | printf("%s\t", fullname); 453 | } 454 | if (count % 5 == 0) { 455 | printf("\n"); 456 | } 457 | count++; 458 | } 459 | } else if (mode == 'l') { 460 | for (i = 0, count = 1; i < length / sizeof(fcb); i++, root++) { 461 | /**< Check if the fcb is used. */ 462 | if (root->free == 0) { 463 | continue; 464 | } 465 | 466 | trans_date(date, root->date); 467 | trans_time(time, root->time); 468 | get_fullname(fullname, root); 469 | printf("%d\t%6d\t%6ld\t%s\t%s\t", root->attribute, root->first, root->length, date, time); 470 | if (root->attribute == 0) { 471 | printf("%s", FOLDER_COLOR); 472 | printf("%s\n", fullname); 473 | printf("%s", DEFAULT_COLOR); 474 | } else { 475 | printf("%s\n", fullname); 476 | } 477 | count++; 478 | } 479 | } 480 | printf("\n"); 481 | } 482 | 483 | /** 484 | * Create one or more files once. 485 | * @param args Filename you want to create. 486 | * @return Always 1. 487 | */ 488 | int my_create(char **args) { 489 | int i; 490 | char path[PATHLENGTH]; 491 | char parpath[PATHLENGTH], filename[NAMELENGTH]; 492 | char *end; 493 | 494 | /**< Check argument count. */ 495 | if (args[1] == NULL) { 496 | fprintf(stderr, "create: missing operand\n"); 497 | return 1; 498 | } 499 | 500 | memset(parpath, '\0', PATHLENGTH); 501 | memset(filename, '\0', NAMELENGTH); 502 | 503 | /**< Do create */ 504 | for (i = 1; args[i] != NULL; i++) { 505 | /**< Split parent folder and filename. */ 506 | get_abspath(path, args[i]); 507 | end = strrchr(path, '/'); 508 | if (end == path) { 509 | strcpy(parpath, "/"); 510 | strcpy(filename, path + 1); 511 | } else { 512 | strncpy(parpath, path, end - path); 513 | strcpy(filename, end + 1); 514 | } 515 | 516 | if (find_fcb(parpath) == NULL) { 517 | fprintf(stderr, "create: cannot create \'%s\': Parent folder not exists\n", parpath); 518 | continue; 519 | } 520 | if (find_fcb(path) != NULL) { 521 | fprintf(stderr, "create: cannot create \'%s\': Folder or file exists\n", args[i]); 522 | continue; 523 | } 524 | 525 | do_create(parpath, filename); 526 | } 527 | 528 | return 1; 529 | } 530 | 531 | /** 532 | * Just do create file. 533 | * @param parpath File par folder. 534 | * @param filename File name. 535 | * @return Error with -1, else return 0. 536 | */ 537 | int do_create(const char *parpath, const char *filename) { 538 | char fullname[NAMELENGTH], fname[16], exname[8]; 539 | char *token; 540 | int first = get_free(1); 541 | int i, flag = 0; 542 | fcb *dir = (fcb *) (fs_head + BLOCK_SIZE * find_fcb(parpath)->first); 543 | 544 | /**< Check for free fcb. */ 545 | for (i = 0; i < BLOCK_SIZE / sizeof(fcb); i++, dir++) { 546 | if (dir->free == 0) { 547 | flag = 1; 548 | break; 549 | } 550 | } 551 | if (!flag) { 552 | fprintf(stderr, "create: Cannot create more file in %s\n", parpath); 553 | return -1; 554 | } 555 | 556 | /**< Check for free space. */ 557 | if (first == -1) { 558 | fprintf(stderr, "create: No more space\n"); 559 | return -1; 560 | } 561 | set_free(first, 1, 0); 562 | 563 | /**< Split name and initial variables. */ 564 | memset(fullname, '\0', NAMELENGTH); 565 | memset(fname, '\0', 8); 566 | memset(exname, '\0', 3); 567 | strcpy(fullname, filename); 568 | token = strtok(fullname, "."); 569 | strncpy(fname, token, 8); 570 | token = strtok(NULL, "."); 571 | if (token != NULL) { 572 | strncpy(exname, token, 3); 573 | } else { 574 | strncpy(exname, "d", 2); 575 | } 576 | 577 | /**< Set fcb. */ 578 | set_fcb(dir, fname, exname, 1, first, 0, 1); 579 | 580 | return 0; 581 | } 582 | 583 | /** 584 | * Remove files. 585 | * @param args Filename you want to remove. 586 | * @return Always return 1. 587 | */ 588 | int my_rm(char **args) { 589 | int i, j; 590 | fcb *file; 591 | 592 | /**< Check argument count. */ 593 | if (args[1] == NULL) { 594 | fprintf(stderr, "rm: missing operand\n"); 595 | return 1; 596 | } 597 | 598 | /**< Do remove. */ 599 | for (i = 1; args[i] != NULL; i++) { 600 | file = find_fcb(args[i]); 601 | if (file == NULL) { 602 | fprintf(stderr, "rm: cannot remove %s: No such file\n", args[i]); 603 | return 1; 604 | } 605 | 606 | if (file->attribute == 0) { 607 | fprintf(stderr, "rm: cannot remove %s: Is a directory\n", args[i]); 608 | return 1; 609 | } 610 | 611 | /**< Check if the file exist in openfile_list. */ 612 | for (j = 0; j < MAX_OPENFILE; j++) { 613 | if (openfile_list[j].free == 0) { 614 | continue; 615 | } 616 | 617 | if (!strcmp(file->filename, openfile_list[j].open_fcb.filename) && 618 | file->first == openfile_list[j].open_fcb.first) { 619 | /**< Folder is open. */ 620 | fprintf(stderr, "rm: cannot remove %s: File is open\n", args[i]); 621 | return 1; 622 | } 623 | } 624 | 625 | do_rm(file); 626 | } 627 | 628 | return 1; 629 | } 630 | 631 | /** 632 | * Just do remove file. 633 | * @param file FCB pointer which file you want to remove. 634 | */ 635 | void do_rm(fcb *file) { 636 | int first = file->first; 637 | 638 | file->free = 0; 639 | set_free(first, 0, 1); 640 | } 641 | 642 | /** 643 | * Open file. 644 | * @param args '-l' to show all files opened. 'path' to open file. 645 | * @return Always 1. 646 | */ 647 | int my_open(char **args) { 648 | int i, j; 649 | fcb *file; 650 | char path[PATHLENGTH]; 651 | 652 | /**< Check argument count. */ 653 | if (args[1] == NULL) { 654 | fprintf(stderr, "open: missing operand\n"); 655 | return 1; 656 | } 657 | if (args[1][0] == '-') { 658 | if (!strcmp(args[1], "-l")) { 659 | printf("fd filename exname state path\n"); 660 | for (i = 0; i < MAX_OPENFILE; i++) { 661 | if (openfile_list[i].free == 0) { 662 | continue; 663 | } 664 | 665 | printf("%2d %8s %-6s %-5d %s\n", i, openfile_list[i].open_fcb.filename, 666 | openfile_list[i].open_fcb.exname, 667 | openfile_list[i].fcb_state, openfile_list[i].dir); 668 | } 669 | return 1; 670 | } else { 671 | fprintf(stderr, "open: wrong argument\n"); 672 | return 1; 673 | } 674 | } 675 | 676 | /**< Do open. */ 677 | for (i = 1; args[i] != NULL; i++) { 678 | file = find_fcb(args[i]); 679 | if (file == NULL) { 680 | fprintf(stderr, "open: cannot open %s: No such file or folder\n", args[i]); 681 | return 1; 682 | } 683 | 684 | /**< Check if the file exist in openfile_list. */ 685 | for (j = 0; j < MAX_OPENFILE; j++) { 686 | if (openfile_list[j].free == 0) { 687 | continue; 688 | } 689 | 690 | if (!strcmp(file->filename, openfile_list[j].open_fcb.filename) && 691 | file->first == openfile_list[j].open_fcb.first) { 692 | /**< file is open. */ 693 | fprintf(stderr, "open: cannot open %s: File or folder is open\n", args[i]); 694 | continue; 695 | } 696 | } 697 | 698 | do_open(get_abspath(path, args[i])); 699 | } 700 | return 1; 701 | } 702 | 703 | /** 704 | * Just do open file. 705 | * @param path Abspath of file you want to open.. 706 | * @return Error with -1, else return fd; 707 | */ 708 | int do_open(char *path) { 709 | int fd = get_useropen(); 710 | fcb *file = find_fcb(path); 711 | 712 | if (fd == -1) { 713 | fprintf(stderr, "open: cannot open file, no more useropen entry\n"); 714 | return -1; 715 | } 716 | fcb_cpy(&openfile_list[fd].open_fcb, file); 717 | openfile_list[fd].free = 1; 718 | openfile_list[fd].count = 0; 719 | memset(openfile_list[fd].dir, '\0', 80); 720 | strcpy(openfile_list[fd].dir, path); 721 | 722 | return fd; 723 | } 724 | 725 | /** 726 | * Close file and save it. 727 | * @param args '-a' to close all file. 'path' to close file. 728 | * @return Always 1. 729 | */ 730 | int my_close(char **args) { 731 | int i, j; 732 | fcb *file; 733 | 734 | /**< Check argument count. */ 735 | if (args[1] == NULL) { 736 | fprintf(stderr, "close: missing operand\n"); 737 | return 1; 738 | } 739 | if (args[1][0] == '-') { 740 | if (!strcmp(args[1], "-a")) { 741 | for (i = 0; i < MAX_OPENFILE; i++) { 742 | if (i == curdir) { 743 | continue; 744 | } 745 | openfile_list[i].free = 0; 746 | } 747 | return 1; 748 | } else { 749 | fprintf(stderr, "close: wrong argument\n"); 750 | return 1; 751 | } 752 | } 753 | 754 | 755 | /**< Do close. */ 756 | for (i = 1; args[i] != NULL; i++) { 757 | file = find_fcb(args[i]); 758 | if (file == NULL) { 759 | fprintf(stderr, "close: cannot close %s: No such file or folder\n", args[i]); 760 | return 1; 761 | } 762 | 763 | /**< Check if the file exist in openfile_list. */ 764 | for (j = 0; j < MAX_OPENFILE; j++) { 765 | if (openfile_list[j].free == 0) { 766 | continue; 767 | } 768 | 769 | if (!strcmp(file->filename, openfile_list[j].open_fcb.filename) && 770 | file->first == openfile_list[j].open_fcb.first) { 771 | /**< File is open. */ 772 | do_close(j); 773 | } 774 | } 775 | } 776 | return 1; 777 | } 778 | 779 | /** 780 | * Just do close file. 781 | * @param fd File descriptor. 782 | */ 783 | void do_close(int fd) { 784 | if (openfile_list[fd].fcb_state == 1) { 785 | fcb_cpy(find_fcb(openfile_list[fd].dir), &openfile_list[fd].open_fcb); 786 | } 787 | openfile_list[fd].free = 0; 788 | } 789 | 790 | /** 791 | * Write file. 792 | * @param args [-a|-c|-w] append|cover|write, 'path' path of file. 793 | * @return 794 | */ 795 | int my_write(char **args) { 796 | int i, j = 0, flag = 0; 797 | int mode = 'w'; 798 | char c; 799 | char path[PATHLENGTH]; 800 | char str[WRITE_SIZE]; 801 | fcb *file; 802 | 803 | /**< Check for arguments count. */ 804 | for (i = 1; args[i] != NULL; i++) { 805 | if (args[i][0] == '-') { 806 | if (!strcmp(args[i], "-w")) { 807 | mode = 'w'; 808 | } else if (!strcmp(args[i], "-c")) { 809 | mode = 'c'; 810 | } else if (!strcmp(args[i], "-a")) { 811 | mode = 'a'; 812 | } else { 813 | fprintf(stderr, "write: wrong argument\n"); 814 | return 1; 815 | } 816 | } else { 817 | flag += 1 << i; 818 | } 819 | } 820 | if ((flag == 0) || (flag > 4) || i > 3) { 821 | fprintf(stderr, "write: wrong argument\n"); 822 | return 1; 823 | } 824 | 825 | /**< Check if it's a file or folder. */ 826 | strcpy(path, args[flag >> 1]); 827 | if ((file = find_fcb(path)) == NULL) { 828 | fprintf(stderr, "write: File not exists\n"); 829 | return 1; 830 | } 831 | if (file->attribute == 0) { 832 | fprintf(stderr, "write: cannot access a folder\n"); 833 | return 1; 834 | } 835 | 836 | memset(str, '\0', WRITE_SIZE); 837 | /**< Check if it's open. */ 838 | for (i = 0; i < MAX_OPENFILE; i++) { 839 | if (openfile_list[i].free == 0) { 840 | continue; 841 | } 842 | 843 | if (!strcmp(file->filename, openfile_list[i].open_fcb.filename) && 844 | file->first == openfile_list[i].open_fcb.first) { 845 | /**< File is open. */ 846 | if (mode == 'c') { 847 | printf("Please input location: "); 848 | scanf("%d", &openfile_list[i].count); 849 | getchar(); 850 | } 851 | while (1) { 852 | for (; (str[j] = getchar()) != '\n'; j++); 853 | j++; 854 | if ((c = getchar()) == '\n') { 855 | break; 856 | } else { 857 | str[j] = c; 858 | j++; 859 | } 860 | } 861 | 862 | if (mode == 'c') { 863 | do_write(i, str, j - 1, mode); 864 | } else { 865 | do_write(i, str, j + 1, mode); 866 | } 867 | 868 | return 1; 869 | } 870 | } 871 | 872 | fprintf(stderr, "write: file is not open\n"); 873 | return 1; 874 | } 875 | 876 | /** 877 | * @param fd File descriptor. 878 | * @param wstyle Write style. 879 | * @return Bytes write 880 | */ 881 | int do_write(int fd, char *content, size_t len, int wstyle) { 882 | //fat1表 883 | 884 | fat *fat1 = (fat *) (fs_head + BLOCK_SIZE); 885 | fat *fat2 = (fat *) (fs_head + 3*BLOCK_SIZE); 886 | 887 | //定义输入字符串数组,初始化 888 | char text[WRITE_SIZE] = {0}; 889 | 890 | int write = openfile_list[fd].count; 891 | openfile_list[fd].count = 0; 892 | do_read(fd, openfile_list[fd].open_fcb.length, text); //读取 893 | openfile_list[fd].count = write; 894 | 895 | int i = openfile_list[fd].open_fcb.first; 896 | 897 | char input[WRITE_SIZE] = {0}; 898 | strncpy(input, content, len); 899 | //文件处理:截断写、覆盖写、追加写 900 | if (wstyle == 'w') { 901 | memset(text, 0, WRITE_SIZE); 902 | memcpy(text, input, len); 903 | // strncpy(text, input, len); 904 | } else if (wstyle == 'c') { 905 | memcpy(text + openfile_list[fd].count, input, len); 906 | // strncpy(&text[openfile_list[fd].count], input, len); 907 | } else if (wstyle == 'a') { 908 | memcpy(text + openfile_list[fd].count, input, len); 909 | // strncpy(&text[openfile_list[fd].open_fcb.length], input, len); 910 | } 911 | //写入文件系统 912 | int length = strlen(text); //需要写入的长度 913 | int num = length / BLOCK_SIZE + 1; 914 | int static_num = num; 915 | 916 | while (num) { 917 | char buf[BLOCK_SIZE] = {0}; 918 | memcpy(buf, &text[(static_num - num) * BLOCK_SIZE], BLOCK_SIZE); 919 | unsigned char *p = fs_head + i * BLOCK_SIZE; 920 | memcpy(p, buf, BLOCK_SIZE); 921 | num = num - 1; 922 | if (num > 0) // 是否还有下一次循环 923 | { 924 | fat *fat_cur = fat1 + i; 925 | 926 | if (fat_cur->id == END) //需要申请索引块 927 | { 928 | int next = get_free(1); 929 | fat_cur->id = next; 930 | fat_cur = fat1 + next; 931 | fat_cur->id = END; 932 | } 933 | i = (fat1 + i)->id; 934 | } 935 | } 936 | //这时的i是刚写完的最后一个磁盘块,剩下的磁盘块可以free掉 937 | 938 | if (fat1[i].id != END) { 939 | int j = fat1[i].id; 940 | fat1[i].id = END; 941 | i = j; 942 | while (fat1[i].id != END) { 943 | int m = fat1[i].id; 944 | fat1[i].id = FREE; 945 | i = m; 946 | } 947 | fat1[i].id = FREE; 948 | } 949 | 950 | memcpy(fat2, fat1, 2*BLOCK_SIZE); 951 | openfile_list[fd].open_fcb.length = length; 952 | openfile_list[fd].fcb_state = 1; 953 | return (strlen(input)); 954 | 955 | 956 | } 957 | 958 | /** 959 | * Read file. 960 | * @param args [-s|-a] select|all, 'path' path of file. 961 | * @return Bytes read. 962 | */ 963 | int my_read(char **args) { 964 | int i, flag = 0; 965 | int length; 966 | int mode = 'a'; 967 | char path[PATHLENGTH]; 968 | char str[WRITE_SIZE]; 969 | fcb *file; 970 | 971 | /**< Check for arguments count. */ 972 | for (i = 1; args[i] != NULL; i++) { 973 | if (args[i][0] == '-') { 974 | if (!strcmp(args[i], "-s")) { 975 | mode = 's'; 976 | } else if (!strcmp(args[i], "-a")) { 977 | mode = 'a'; 978 | } else { 979 | fprintf(stderr, "read: wrong argument\n"); 980 | return 1; 981 | } 982 | } else { 983 | flag += 1 << i; 984 | } 985 | } 986 | if ((flag == 0) || (flag > 4) || i > 3) { 987 | fprintf(stderr, "read: wrong argument\n"); 988 | return 1; 989 | } 990 | 991 | /**< Check if it's a file or folder. */ 992 | strcpy(path, args[flag >> 1]); 993 | if ((file = find_fcb(path)) == NULL) { 994 | fprintf(stderr, "read: File not exists\n"); 995 | return 1; 996 | } 997 | if (file->attribute == 0) { 998 | fprintf(stderr, "read: cannot access a folder\n"); 999 | return 1; 1000 | } 1001 | 1002 | memset(str, '\0', WRITE_SIZE); 1003 | /**< Check if it's open. */ 1004 | for (i = 0; i < MAX_OPENFILE; i++) { 1005 | if (openfile_list[i].free == 0) { 1006 | continue; 1007 | } 1008 | 1009 | if (!strcmp(file->filename, openfile_list[i].open_fcb.filename) && 1010 | file->first == openfile_list[i].open_fcb.first) { 1011 | /**< File is open. */ 1012 | if (mode == 'a') { 1013 | openfile_list[i].count = 0; 1014 | length = UINT16_MAX; 1015 | } 1016 | if (mode == 's') { 1017 | printf("Please input location: "); 1018 | scanf("%d", &openfile_list[i].count); 1019 | printf("Please input length: "); 1020 | scanf("%d", &length); 1021 | printf("-----------------------\n"); 1022 | } 1023 | do_read(i, length, str); 1024 | fputs(str, stdout); 1025 | return 1; 1026 | } 1027 | } 1028 | 1029 | fprintf(stderr, "read: file is not open\n"); 1030 | return 1; 1031 | } 1032 | 1033 | /** 1034 | * @param fd File descriptor. 1035 | * @param len Length of text. 1036 | * @param text Read file into text. 1037 | * @return 1038 | */ 1039 | int do_read(int fd, int len, char *text) { 1040 | memset(text, '\0', BLOCK_SIZE * 20); 1041 | 1042 | if (len <= 0) //想要读取0个字符 1043 | { 1044 | return 0; 1045 | } 1046 | 1047 | fat *fat1 = (fat *) (fs_head + BLOCK_SIZE); //FAT1表 1048 | int location = 0;//text的写入位置 1049 | int length; 1050 | int count = openfile_list[fd].count; //读写指针位置 1051 | //排除了id出现end的情况 1052 | if ((openfile_list[fd].open_fcb.length - count) >= len) //可以读取的字符多于想要读取的字符 1053 | { 1054 | length = len; //想要读取的字符 1055 | } else { 1056 | length = openfile_list[fd].open_fcb.length - count; //只能读取这些字符 1057 | } 1058 | while (length) //需要读取的字符串个数 1059 | { 1060 | char *buf = (char *) malloc(BLOCK_SIZE); //申请空闲缓冲区 1061 | int count = openfile_list[fd].count; //读写指针位置 1062 | int logic_block_num = count / BLOCK_SIZE;//逻辑块号(起始为0) 1063 | int off = count % BLOCK_SIZE;//块内偏移量 1064 | int physics_block_num = openfile_list[fd].open_fcb.first;//文件起始物理块号(引导块号为0) 1065 | 1066 | for (int i = 0; i < logic_block_num; i++) //物理块号 1067 | { 1068 | physics_block_num = (fat1 + physics_block_num)->id; //FAT第一项为0,若为1则physics_block_num-1 1069 | } 1070 | unsigned char *p = fs_head + BLOCK_SIZE * physics_block_num; //该物理块起始地址 1071 | memcpy(buf, p, BLOCK_SIZE); 1072 | 1073 | if ((off + length) <= BLOCK_SIZE) { 1074 | memcpy(&text[location], &buf[off], length); 1075 | openfile_list[fd].count = openfile_list[fd].count + length; 1076 | location += length; //下一次写的位置 1077 | length = length - length; //lenght = 0 将退出循环 1078 | } else { 1079 | memcpy(&text[location], &buf[off], BLOCK_SIZE - off); 1080 | openfile_list[fd].count += BLOCK_SIZE - off; 1081 | location += BLOCK_SIZE - off; 1082 | length = length - BLOCK_SIZE - off; //还剩下的想要读取的字节数 1083 | } 1084 | } 1085 | 1086 | return location; 1087 | } 1088 | 1089 | /** 1090 | * Exit system, save changes. 1091 | * @author 1092 | */ 1093 | int my_exit_sys(void) { 1094 | int i; 1095 | FILE *fp; 1096 | 1097 | for (i = 0; i < MAX_OPENFILE; i++) { 1098 | do_close(i); 1099 | } 1100 | 1101 | fp = fopen(SYS_PATH, "w"); 1102 | fwrite(fs_head, DISK_SIZE, 1, fp); 1103 | free(fs_head); 1104 | fclose(fp); 1105 | return 0; 1106 | } 1107 | 1108 | /** 1109 | * Detect free blocks in FAT. 1110 | * @param count Count of needed blocks. 1111 | * @return 0 without enough space, else return the first block number. 1112 | * @author Leslie Van 1113 | */ 1114 | int get_free(int count) { 1115 | unsigned char *ptr = fs_head; 1116 | fat *fat0 = (fat *) (ptr + BLOCK_SIZE); 1117 | int i, j, flag = 0; 1118 | int fat[BLOCK_NUM]; 1119 | 1120 | /** Copy FAT. */ 1121 | for (i = 0; i < BLOCK_NUM; i++, fat0++) { 1122 | fat[i] = fat0->id; 1123 | } 1124 | 1125 | /** Find a continuous space. */ 1126 | for (i = 0; i < BLOCK_NUM - count; i++) { 1127 | for (j = i; j < i + count; j++) { 1128 | if (fat[j] > 0) { 1129 | flag = 1; 1130 | break; 1131 | } 1132 | } 1133 | if (flag) { 1134 | flag = 0; 1135 | i = j; 1136 | } else { 1137 | return i; 1138 | } 1139 | } 1140 | 1141 | return -1; 1142 | } 1143 | 1144 | /** 1145 | * Change value of FAT. 1146 | * @param first The starting block number. 1147 | * @param length The blocks count. 1148 | * @param mode 0 to allocate, 1 to reclaim and 2 to format. 1149 | * @author Leslie Van 1150 | */ 1151 | int set_free(unsigned short first, unsigned short length, int mode) { 1152 | fat *flag = (fat *) (fs_head + BLOCK_SIZE); 1153 | fat *fat0 = (fat *) (fs_head + BLOCK_SIZE); 1154 | fat *fat1 = (fat *) (fs_head + BLOCK_SIZE * 3); 1155 | int i; 1156 | int offset; 1157 | 1158 | for (i = 0; i < first; i++, fat0++, fat1++); 1159 | 1160 | if (mode == 1) { 1161 | /**< Reclaim space. */ 1162 | while (fat0->id != END) { 1163 | offset = fat0->id - (fat0 - flag) / sizeof(fat); 1164 | fat0->id = FREE; 1165 | fat1->id = FREE; 1166 | fat0 += offset; 1167 | fat1 += offset; 1168 | } 1169 | fat0->id = FREE; 1170 | fat1->id = FREE; 1171 | } else if (mode == 2) { 1172 | /**< Format FAT */ 1173 | for (i = 0; i < BLOCK_NUM; i++, fat0++, fat1++) { 1174 | fat0->id = FREE; 1175 | fat1->id = FREE; 1176 | } 1177 | } else { 1178 | /**< Allocate consecutive space. */ 1179 | for (; i < first + length - 1; i++, fat0++, fat1++) { 1180 | fat0->id = first + 1; 1181 | fat1->id = first + 1; 1182 | } 1183 | fat0->id = END; 1184 | fat1->id = END; 1185 | } 1186 | 1187 | return 0; 1188 | } 1189 | 1190 | /** 1191 | * Set fcb attribute. 1192 | * @param f The pointer of fcb. 1193 | * @param filename FCB filename. 1194 | * @param exname FCB file extensions name. 1195 | * @param attr FCB file attribute. 1196 | * @param first FCB starting block number. 1197 | * @param length FCB file length. 1198 | * @param ffree 1 when file occupied, else 0. 1199 | * @author Leslie Van 1200 | */ 1201 | int set_fcb(fcb *f, const char *filename, const char *exname, unsigned char attr, unsigned short first, 1202 | unsigned long length, char ffree) { 1203 | time_t *now = (time_t *) malloc(sizeof(time_t)); 1204 | struct tm *timeinfo; 1205 | time(now); 1206 | timeinfo = localtime(now); 1207 | 1208 | memset(f->filename, 0, 8); 1209 | memset(f->exname, 0, 3); 1210 | strncpy(f->filename, filename, 7); 1211 | strncpy(f->exname, exname, 2); 1212 | f->attribute = attr; 1213 | f->time = get_time(timeinfo); 1214 | f->date = get_date(timeinfo); 1215 | f->first = first; 1216 | f->length = length; 1217 | f->free = ffree; 1218 | 1219 | free(now); 1220 | return 0; 1221 | } 1222 | 1223 | /** 1224 | * Translate ISO time to short time. 1225 | * @param timeinfo Current time structure. 1226 | * @return Time number after translation. 1227 | */ 1228 | unsigned short get_time(struct tm *timeinfo) { 1229 | int hour, min, sec; 1230 | unsigned short result; 1231 | 1232 | hour = timeinfo->tm_hour; 1233 | min = timeinfo->tm_min; 1234 | sec = timeinfo->tm_sec; 1235 | result = (hour << 11) + (min << 5) + (sec >> 1); 1236 | 1237 | return result; 1238 | } 1239 | 1240 | /** 1241 | * Translate ISO date to short date. 1242 | * @param timeinfo local 1243 | * @return Date number after translation. 1244 | */ 1245 | unsigned short get_date(struct tm *timeinfo) { 1246 | int year, mon, day; 1247 | unsigned short result; 1248 | 1249 | year = timeinfo->tm_year; 1250 | mon = timeinfo->tm_mon; 1251 | day = timeinfo->tm_mday; 1252 | result = (year << 9) + (mon << 5) + day; 1253 | 1254 | return result; 1255 | } 1256 | 1257 | /** 1258 | * Copy a fcb. 1259 | * @param dest Destination fcb. 1260 | * @param src Source fcb. 1261 | * @return Destination fcb pointer. 1262 | */ 1263 | fcb *fcb_cpy(fcb *dest, fcb *src) { 1264 | memset(dest->filename, '\0', 8); 1265 | memset(dest->exname, '\0', 3); 1266 | 1267 | strcpy(dest->filename, src->filename); 1268 | strcpy(dest->exname, src->exname); 1269 | dest->attribute = src->attribute; 1270 | dest->time = src->time; 1271 | dest->date = src->date; 1272 | dest->first = src->first; 1273 | dest->length = src->length; 1274 | dest->free = src->free; 1275 | 1276 | return dest; 1277 | } 1278 | 1279 | /** 1280 | * Translate relative path to absolute path 1281 | * @param abspath Absolute path. 1282 | * @param relpath Relative path. 1283 | * @return Absolute path. 1284 | */ 1285 | char *get_abspath(char *abspath, const char *relpath) { 1286 | /**< If relpath is abspath. */ 1287 | if (!strcmp(relpath, DELIM) || relpath[0] == '/') { 1288 | strcpy(abspath, relpath); 1289 | return 0; 1290 | } 1291 | 1292 | char str[PATHLENGTH]; 1293 | char *token, *end; 1294 | 1295 | memset(abspath, '\0', PATHLENGTH); 1296 | abspath[0] = '/'; 1297 | strcpy(abspath, current_dir); 1298 | 1299 | strcpy(str, relpath); 1300 | token = strtok(str, DELIM); 1301 | 1302 | do { 1303 | if (!strcmp(token, ".")) { 1304 | continue; 1305 | } 1306 | if (!strcmp(token, "..")) { 1307 | if (!strcmp(abspath, ROOT)) { 1308 | continue; 1309 | } else { 1310 | end = strrchr(abspath, '/'); 1311 | if (end == abspath) { 1312 | strcpy(abspath, ROOT); 1313 | continue; 1314 | } 1315 | memset(end, '\0', 1); 1316 | continue; 1317 | } 1318 | } 1319 | if (strcmp(abspath, "/")) { 1320 | strcat(abspath, DELIM); 1321 | } 1322 | strcat(abspath, token); 1323 | } while ((token = strtok(NULL, DELIM)) != NULL); 1324 | 1325 | return abspath; 1326 | } 1327 | 1328 | /** 1329 | * Find fcb by abspath. 1330 | * @param path File path. 1331 | * @return File fcb pointer. 1332 | */ 1333 | fcb *find_fcb(const char *path) { 1334 | char abspath[PATHLENGTH]; 1335 | get_abspath(abspath, path); 1336 | char *token = strtok(abspath, DELIM); 1337 | if (token == NULL) { 1338 | return (fcb *) (fs_head + BLOCK_SIZE * 5); 1339 | } 1340 | return find_fcb_r(token, 5); 1341 | } 1342 | 1343 | /** 1344 | * A procedure to find fcb recursively. 1345 | * @param token File name in (ptr). 1346 | * @param first Par fcb pointer. 1347 | * @return FCB pointer of token. 1348 | */ 1349 | fcb *find_fcb_r(char *token, int first) { 1350 | int i, length = BLOCK_SIZE; 1351 | char fullname[NAMELENGTH] = "\0"; 1352 | fcb *root = (fcb *) (BLOCK_SIZE * first + fs_head); 1353 | fcb *dir; 1354 | block0 *init_block = (block0 *) fs_head; 1355 | if (first == init_block->root) { 1356 | length = ROOT_BLOCK_NUM * BLOCK_SIZE; 1357 | } 1358 | 1359 | for (i = 0, dir = root; i < length / sizeof(fcb); i++, dir++) { 1360 | if (dir->free == 0) { 1361 | continue; 1362 | } 1363 | get_fullname(fullname, dir); 1364 | if (!strcmp(token, fullname)) { 1365 | token = strtok(NULL, DELIM); 1366 | if (token == NULL) { 1367 | return dir; 1368 | } 1369 | return find_fcb_r(token, dir->first); 1370 | } 1371 | } 1372 | return NULL; 1373 | } 1374 | 1375 | /** 1376 | * Get a empty useropen entry. 1377 | * @return If empty useropen exist return entry index, else return -1; 1378 | */ 1379 | int get_useropen() { 1380 | int i; 1381 | 1382 | for (i = 0; i < MAX_OPENFILE; i++) { 1383 | if (openfile_list[i].free == 0) { 1384 | return i; 1385 | } 1386 | } 1387 | 1388 | return -1; 1389 | } 1390 | 1391 | /** 1392 | * Init a folder. 1393 | * @param first Parent folder block num. 1394 | * @param second Current folder block num. 1395 | */ 1396 | void init_folder(int first, int second) { 1397 | int i; 1398 | fcb *par = (fcb *) (fs_head + BLOCK_SIZE * first); 1399 | fcb *cur = (fcb *) (fs_head + BLOCK_SIZE * second); 1400 | 1401 | set_fcb(cur, ".", "di", 0, second, BLOCK_SIZE, 1); 1402 | cur++; 1403 | set_fcb(cur, "..", "di", 0, first, par->length, 1); 1404 | cur++; 1405 | for (i = 2; i < BLOCK_SIZE / sizeof(fcb); i++, cur++) { 1406 | cur->free = 0; 1407 | } 1408 | } 1409 | 1410 | /** 1411 | * Get file full name. 1412 | * @param fullname A char array[NAMELENGTH]. 1413 | * @param fcb1 Source fcb pointer. 1414 | */ 1415 | void get_fullname(char *fullname, fcb *fcb1) { 1416 | memset(fullname, '\0', NAMELENGTH); 1417 | 1418 | strcat(fullname, fcb1->filename); 1419 | if (fcb1->attribute == 1) { 1420 | strncat(fullname, ".", 2); 1421 | strncat(fullname, fcb1->exname, 3); 1422 | } 1423 | } 1424 | 1425 | /** 1426 | * Translate unsigned short number to date string. 1427 | * @param sdate Date to string. 1428 | * @param date A number to represent date. 1429 | * @return sdate. 1430 | */ 1431 | char *trans_date(char *sdate, unsigned short date) { 1432 | int year, month, day; 1433 | memset(sdate, '\0', 16); 1434 | 1435 | year = date & 0xfe00; 1436 | month = date & 0x01e0; 1437 | day = date & 0x001f; 1438 | sprintf(sdate, "%04d-%02d-%02d", (year >> 9) + 1900, (month >> 5) + 1, day); 1439 | return sdate; 1440 | } 1441 | 1442 | /** 1443 | * Translate unsigned short number to time string. 1444 | * @param stime Time to string. 1445 | * @param time A number to represent time. 1446 | * @return stime. 1447 | */ 1448 | char *trans_time(char *stime, unsigned short time) { 1449 | int hour, min, sec; 1450 | memset(stime, '\0', 16); 1451 | 1452 | hour = time & 0xfc1f; 1453 | min = time & 0x03e0; 1454 | sec = time & 0x001f; 1455 | sprintf(stime, "%02d:%02d:%02d", hour >> 11, min >> 5, sec << 1); 1456 | return stime; 1457 | } -------------------------------------------------------------------------------- /Operator_System_Lab5/simplefs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simplefs.h 3 | * @brief Setup in FAT16 file system. 4 | * @details Macro definitions, structs such as FCB and FAT, and some global variable. 5 | * @author Leslie Van 6 | * @date 2018-12-19 to 2019-1-3 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifndef OPERATOR_SYSTEM_EXP4_SIMPLEFS_H 16 | #define OPERATOR_SYSTEM_EXP4_SIMPLEFS_H 17 | #define BLOCK_SIZE 1024 18 | #define BLOCK_NUM 1024 19 | #define DISK_SIZE 1048576 20 | #define SYS_PATH "./fsfile" 21 | #define END 0xffff /**< End of the block, a flag in FAT. */ 22 | #define FREE 0x0000 /**< Unused block, a flag in FAT. */ 23 | #define ROOT "/" /**< Root directory name.*/ 24 | #define ROOT_BLOCK_NUM 2 /**< Block of the initial root directory. */ 25 | #define MAX_OPENFILE 10 /**< Max files to open at the same time. */ 26 | #define NAMELENGTH 32 27 | #define PATHLENGTH 128 28 | #define DELIM "/" 29 | #define FOLDER_COLOR "\e[1;32m" 30 | #define DEFAULT_COLOR "\e[0m" 31 | #define WRITE_SIZE 20 * BLOCK_SIZE 32 | 33 | /** 34 | * @brief Store virtual disk information. 35 | * Contain info like block size, block count and some other information about disk. 36 | */ 37 | typedef struct BLOCK0 { 38 | char information[200]; 39 | unsigned short root; /**< Block number of the root directory. */ 40 | unsigned char *start_block; /**< Location of the first data block. */ 41 | } block0; 42 | 43 | /** 44 | * @brief File control block. 45 | * Store file info both the description and current state. 46 | */ 47 | typedef struct FCB { 48 | char filename[8]; 49 | char exname[3]; 50 | unsigned char attribute; /**< 0: directory or 1: file. */ 51 | unsigned char reserve[10]; 52 | unsigned short time; /**< File create time. */ 53 | unsigned short date; /**< File create date. */ 54 | unsigned short first; /**< First block num of the file. */ 55 | unsigned long length; /**< Block count of the file. */ 56 | char free; 57 | } fcb; 58 | 59 | /** 60 | * @brief File allocation table. 61 | * Record the next block num of file. 62 | * When value is 0xffff, this block is the last block of the file. 63 | */ 64 | typedef struct FAT { 65 | unsigned short id; 66 | } fat; 67 | 68 | /** 69 | * @brief A file entry opened by user. 70 | * Contain file control block and current state. 71 | */ 72 | typedef struct USEROPEN { 73 | /** FCB. */ 74 | fcb open_fcb; 75 | /** Current state. */ 76 | char dir[80]; 77 | int count; 78 | char fcb_state; 79 | char free; 80 | } useropen; 81 | 82 | /** Global variables. */ 83 | unsigned char *fs_head; /**< Initial address of the virtual disk. */ 84 | useropen openfile_list[MAX_OPENFILE]; /**< File array opened by user. */ 85 | int curdir; /**< File descriptor of current directory. */ 86 | char current_dir[80]; /**< Current directory name. */ 87 | unsigned char *start; /**< Location of the first data block. */ 88 | 89 | /** Declaration of functions */ 90 | int start_sys(void); 91 | 92 | int my_format(char **args); 93 | 94 | int do_format(void); 95 | 96 | int my_cd(char **args); 97 | 98 | void do_chdir(int fd); 99 | 100 | int my_pwd(char **args); 101 | 102 | int my_mkdir(char **args); 103 | 104 | int do_mkdir(const char *parpath, const char *dirname); 105 | 106 | int my_rmdir(char **args); 107 | 108 | void do_rmdir(fcb *dir); 109 | 110 | int my_ls(char **args); 111 | 112 | void do_ls(int first, char mode); 113 | 114 | int my_create(char **args); 115 | 116 | int do_create(const char *parpath, const char *filename); 117 | 118 | int my_rm(char **args); 119 | 120 | void do_rm(fcb *file); 121 | 122 | int my_open(char **args); 123 | 124 | int do_open(char *path); 125 | 126 | int my_close(char **args); 127 | 128 | void do_close(int fd); 129 | 130 | int my_write(char **args); 131 | 132 | int do_write(int fd, char *content, size_t len, int wstyle); 133 | 134 | int my_read(char **args); 135 | 136 | int do_read(int fd, int len, char *text); 137 | 138 | int my_exit_sys(); 139 | 140 | int get_free(int count); 141 | 142 | int set_free(unsigned short first, unsigned short length, int mode); 143 | 144 | int set_fcb(fcb *f, const char *filename, const char *exname, unsigned char attr, unsigned short first, 145 | unsigned long length, 146 | char ffree); 147 | 148 | unsigned short get_time(struct tm *timeinfo); 149 | 150 | unsigned short get_date(struct tm *timeinfo); 151 | 152 | fcb * fcb_cpy(fcb *dest, fcb *src); 153 | 154 | char * get_abspath(char *abspath, const char *relpath); 155 | 156 | int get_useropen(); 157 | 158 | fcb *find_fcb(const char *path); 159 | 160 | fcb *find_fcb_r(char *token, int root); 161 | 162 | void init_folder(int first, int second); 163 | 164 | void get_fullname(char *fullname, fcb *fcb1); 165 | 166 | char *trans_date(char *sdate, unsigned short date); 167 | 168 | char *trans_time(char *stime, unsigned short time); 169 | 170 | #endif //OPERATOR_SYSTEM_EXP4_SIMPLEFS_H 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 杭州电子科技大学操作系统课程设计 2 | 3 | - categories: ["Project"] 4 | - tags: ["OS", "Lab", "HDU", "project"] 5 | - keywords: ["杭电","杭州电子科技大学","HDU","操作系统实验","操作系统","实验","Linux","内核编译","进程管理"] 6 | - alias: ["杭电操作系统实验", "HDU操作系统实验", "HDU操作系统"] 7 | 8 | 9 | 10 | **实验列表** 11 | 12 | - [x] [Lab1-Linux内核编译及添加系统调用](https://lsvm.xyz/2019/01/os-lab1/) 13 | - [x] [Lab2-Linux内核模块编程](https://lsvm.xyz/2019/03/os-lab2/) 14 | - [x] [Lab3-Linux进程管理(二)管道通信](https://lsvm.xyz/2019/04/os-lab-3-2/) 15 | - [x] [Lab3-Linux进程管理(三)消息队列](https://github.com/leslievan/Operator_System/tree/master/Operator_System_Lab3) 16 | - [x] [Lab3-Linux进程管理(四)共享内存](https://github.com/leslievan/Operator_System/tree/master/Operator_System_Lab5) 17 | - [x] [Lab5-Linux文件系统](https://github.com/leslievan/Operator_System/tree/master/Operator_System_Lab5) 18 | 19 | 20 | 21 | 22 | 23 | ## HDU-OS-Lab1-Linux内核编译及添加系统调用 24 | 25 | 添加一个系统调用,实现对指定进程的nice值的修改或读取功能,并返回进程最新的nice值及优先级prio。 26 | 27 | > 视频教程地址: 28 | > 29 | > 源码地址: 30 | 31 | [阅读更多](https://lsvm.xyz/2019/01/os-lab1/) 32 | 33 | ## HDU-OS-Lab2-Linux内核模块编程 34 | 35 | Linux内核采用了整体结构,上一个实验体会了编译内核时间的冗长与繁杂,一步错就要重新编译,这虽然提高了效率,但同时也让后续的维护变得困难,在这个基础上,Linux内核引入了动态模块机制加以改进。 36 | 37 | > 视频教程地址: 38 | > 39 | > 源码地址: 40 | 41 | [阅读更多](https://lsvm.xyz/2019/03/os-lab2) 42 | 43 | ## HDU-OS-Lab3-Linux进程管理(二)管道通信 44 | 45 | 实验三的知识点是进程通信,进程通信的方式多种多样,既包括锁机制、信号量机制在内的低级通信方式,低级在于其交换的信息量少且效率较低,又包括共享服务器、消息传递系统、管道通信以及客户-服务器系统通信在内的高级通信方式,本实验是实验三的第二个部分,介绍了管道通信方式的基本原理以及具体实现。 46 | 47 | > 源码地址: 48 | 49 | [阅读更多](https://lsvm.xyz/2019/04/os-lab-3-2) 50 | --------------------------------------------------------------------------------