├── .gitignore ├── 1-fileio ├── 1-myecho │ ├── build.sh │ └── myecho.c ├── 2-mycat │ ├── build.sh │ └── mycat.c └── 3-mycp │ ├── build.sh │ └── mycp.c ├── 2-multi-process ├── 1-mysys │ ├── build.sh │ └── mysys.c ├── 2-sh1 │ ├── build.sh │ └── sh1.c ├── 3-sh2 │ ├── build.sh │ └── sh2.c └── 4-sh3 │ ├── build.sh │ └── sh3.c ├── 3-multi-thread ├── 1-pi1 │ ├── build.sh │ └── pi1.c ├── 2-pi2 │ ├── build.sh │ └── pi2.c ├── 3-sort │ ├── build.sh │ └── sort.c ├── 4-pc1 │ ├── build.sh │ └── pc1.c ├── 5-pc2 │ ├── build.sh │ └── pc2.c └── 6-ring │ ├── build.sh │ └── ring.c ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | /.vscode 3 | 4 | # Mac OS 5 | /.DS_Store 6 | /*/.DS_Store 7 | /*/*/.DS_Store 8 | 9 | # dist 10 | /*/*/*.out 11 | /*/*/*.run 12 | -------------------------------------------------------------------------------- /1-fileio/1-myecho/build.sh: -------------------------------------------------------------------------------- 1 | gcc myecho.c -o myecho.run 2 | -------------------------------------------------------------------------------- /1-fileio/1-myecho/myecho.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | // 输出所有参数 5 | while (argc --> 1) { 6 | printf("%s ", *++argv); 7 | } 8 | // 输出一个换行 9 | printf("\n"); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /1-fileio/2-mycat/build.sh: -------------------------------------------------------------------------------- 1 | gcc mycat.c -o mycat.run 2 | -------------------------------------------------------------------------------- /1-fileio/2-mycat/mycat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | char buffer[1024]; 8 | int file, count; 9 | 10 | // 打开文件 11 | file = open(argv[1], O_RDONLY); 12 | if (file < 0) 13 | printf("Can't open the file %s", argv[1]); 14 | 15 | // 不断输出 16 | while ((count = read(file, buffer, 1023)) > 0) { 17 | write(1, buffer, count); 18 | } 19 | 20 | // 关闭文件 21 | close(file); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /1-fileio/3-mycp/build.sh: -------------------------------------------------------------------------------- 1 | gcc mycp.c -o mycp.run 2 | -------------------------------------------------------------------------------- /1-fileio/3-mycp/mycp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | int src, dst; 7 | char buffer[1024]; 8 | int count; 9 | 10 | // 打开文件 11 | src = open(argv[1], O_RDONLY); 12 | dst = open(argv[2], O_WRONLY | O_CREAT, 0666); 13 | 14 | if (src < 0 || dst < 0) printf("can't open the file\n"); 15 | 16 | // 一遍从源文件读,一边向目标文件写 17 | while ((count = read(src, buffer, 1023)) > 0) { 18 | write(dst, buffer, count); 19 | } 20 | 21 | // 关闭文件 22 | close(src); 23 | close(dst); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /2-multi-process/1-mysys/build.sh: -------------------------------------------------------------------------------- 1 | gcc mysys.c -o mysys.run 2 | -------------------------------------------------------------------------------- /2-multi-process/1-mysys/mysys.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int mysys(char *arg) { 7 | // fork一个子进程 8 | pid_t fpid = fork(); 9 | if (fpid < 0) { 10 | // 如果获取子进程失败 11 | return -1; 12 | } else if (fpid == 0) { 13 | // 如果是子进程 14 | if (execl("/bin/sh", "sh", "-c", arg, (char *) 0) < 0) { 15 | return 127; 16 | } 17 | } else { 18 | // 等待子进程结束 19 | wait(NULL); 20 | return 0; 21 | } 22 | return 0; 23 | } 24 | 25 | int main(int argc, char *argv[]) { 26 | int i; 27 | char buffer[200]; 28 | buffer[0] = '\0'; 29 | int count = 0; 30 | // 将参数拼成一个字符串传递给mysys函数 31 | for (i = 1; i < argc; i++) { 32 | count += strlen(argv[i]); 33 | if (count < 200) { 34 | strcat(buffer, argv[i]); 35 | if (i < argc - 1) 36 | strcat(buffer, " "); 37 | } 38 | } 39 | 40 | // 调用mysys 41 | mysys(buffer); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /2-multi-process/2-sh1/build.sh: -------------------------------------------------------------------------------- 1 | gcc sh1.c -o sh1.run 2 | -------------------------------------------------------------------------------- /2-multi-process/2-sh1/sh1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUFFER_LEN 1024 7 | 8 | // 读入一行进入缓冲区 9 | int readLine(char *, int); 10 | // 伪造system函数 11 | int mysys(char *); 12 | // 清空缓冲区 13 | void bufferClear(char *, int); 14 | 15 | int main(int argc, char *argv[]) { 16 | char *p; 17 | char buffer[BUFFER_LEN]; 18 | char temp[BUFFER_LEN]; 19 | char path[BUFFER_LEN]; 20 | 21 | // 开始主循环 22 | while (1) { 23 | // 输出shell标识符 24 | printf("$"); 25 | // 清空缓冲区 26 | bufferClear(buffer, BUFFER_LEN); 27 | bufferClear(temp, BUFFER_LEN); 28 | bufferClear(path, BUFFER_LEN); 29 | // 读取一行,如果溢出了就报错 30 | if (readLine(buffer, BUFFER_LEN)) { 31 | // 拷贝原始输入 32 | strcpy(temp, buffer); 33 | // 分割参数 34 | p = strtok(temp, " "); 35 | // 根据指令的不同做不同的事情 36 | if (p) { 37 | if (!strcmp(p, "cd")) { 38 | p = strtok(NULL, ""); 39 | if (chdir(p) < 0) printf("no such directory\n"); 40 | } else if (!strcmp(p, "pwd")) { 41 | getcwd(path, BUFFER_LEN); 42 | printf("%s\n", path); 43 | } else if (!strcmp(p, "exit")) { 44 | // 退出程序 45 | return 0; 46 | } else { 47 | mysys(buffer); 48 | } 49 | } 50 | } else { 51 | printf("You can't input so much char at one time!\n"); 52 | } 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | int mysys(char *arg) { 59 | // fork一个子进程 60 | pid_t fpid = fork(); 61 | if (fpid < 0) { 62 | // 如果获取子进程失败 63 | return -1; 64 | } else if (fpid == 0) { 65 | // 如果是子进程 66 | if (execl("/bin/sh", "sh", "-c", arg, (char *) 0) < 0) { 67 | return 127; 68 | } 69 | } else { 70 | // 等待子进程结束 71 | wait(NULL); 72 | return 0; 73 | } 74 | return 0; 75 | } 76 | 77 | int readLine(char *buffer, int length) { 78 | char c; 79 | int count = 0; 80 | c = getchar(); 81 | while (c != '\n') { 82 | count++; 83 | if (count < length - 1) { 84 | buffer[count - 1] = c; 85 | } else return 0; 86 | c = getchar(); 87 | } 88 | buffer[count] = '\0'; 89 | return 1; 90 | } 91 | 92 | void bufferClear(char *buffer, int length) { 93 | for (int i = 0; i < length; i++) buffer[i] = '\0'; 94 | } 95 | -------------------------------------------------------------------------------- /2-multi-process/3-sh2/build.sh: -------------------------------------------------------------------------------- 1 | gcc sh2.c -o sh2.run 2 | -------------------------------------------------------------------------------- /2-multi-process/3-sh2/sh2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUFFER_LEN 1024 9 | 10 | #define RE_NO 0 11 | #define RE_OUT 1 12 | #define RE_IN 2 13 | #define RE_ALL 3 14 | 15 | // 读入一行进入缓冲区 16 | int readLine(char *, int); 17 | // 清空缓冲区 18 | void bufferClear(char *, int); 19 | // 伪造system函数 20 | int mysys(char *); 21 | // 判断是否要重定向 22 | int needRedirect(char *); 23 | // 执行指令 24 | void doSomething(char *); 25 | // 处理字符串中的输出重定向 26 | char *dealReOutStr(char *); 27 | // 处理字符串中的输入重定向 28 | char *dealReInStr(char *); 29 | // 寻找特定字符在字符串中的位置 30 | int findCharInStr(char *, char); 31 | // 删除字符串的一部分 32 | void deleteFromStr(char *, int, int); 33 | 34 | int main(int argc, char *argv[]) { 35 | char buffer[BUFFER_LEN]; 36 | 37 | // 开始主循环 38 | while (1) { 39 | // 输出shell标识符 40 | printf("$"); 41 | // 清空缓冲区 42 | bufferClear(buffer, BUFFER_LEN); 43 | // 读取一行,如果溢出了就报错 44 | if (readLine(buffer, BUFFER_LEN)) { 45 | // 执行指令 46 | doSomething(buffer); 47 | } else { 48 | printf("You can't input so much char at one time!\n"); 49 | } 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | int readLine(char *buffer, int length) { 56 | char c; 57 | int count = 0; 58 | c = getchar(); 59 | while (c != '\n') { 60 | count++; 61 | if (count < length - 1) { 62 | buffer[count - 1] = c; 63 | } else return 0; 64 | c = getchar(); 65 | } 66 | buffer[count] = '\0'; 67 | return 1; 68 | } 69 | 70 | void bufferClear(char *buffer, int length) { 71 | for (int i = 0; i < length; i++) buffer[i] = '\0'; 72 | } 73 | 74 | int needRedirect(char *str) { 75 | // 寻找 < 符号和 > 符号 76 | int findLeft = 0; 77 | int findRight = 0; 78 | for (int i = 0; i < strlen(str); i++) { 79 | if (str[i] == '<') findLeft = 1; 80 | if (str[i] == '>') findRight = 1; 81 | } 82 | if (!findLeft && findRight) return RE_OUT; 83 | if (findLeft && !findRight) return RE_IN; 84 | if (findLeft && findRight) return RE_ALL; 85 | return RE_NO; 86 | } 87 | 88 | void doSomething(char *str) { 89 | // 缓冲区 90 | char buffer[BUFFER_LEN]; 91 | char str2[BUFFER_LEN]; 92 | strcpy(str2, str); 93 | char path[BUFFER_LEN]; 94 | char *p = NULL; 95 | char *name = NULL; 96 | // 文件描述符 97 | int fd; 98 | // 子进程 99 | pid_t pid; 100 | 101 | if (strcmp(str, "")) { 102 | // 判断指令类型 103 | int type = needRedirect(str); 104 | // 根据指令情况进行处理 105 | switch (type) { 106 | case RE_NO: 107 | // 拷贝输入 108 | strcpy(buffer, str); 109 | // 分割参数 110 | p = strtok(buffer, " "); 111 | // 根据指令的不同做不同的事情 112 | if (p) { 113 | if (!strcmp(p, "cd")) { 114 | p = strtok(NULL, ""); 115 | if (chdir(p) < 0) printf("no such directory\n"); 116 | } else if (!strcmp(p, "pwd")) { 117 | getcwd(path, BUFFER_LEN); 118 | printf("%s\n", path); 119 | } else if (!strcmp(p, "exit")) { 120 | // 退出程序 121 | exit(0); 122 | } else { 123 | mysys(str); 124 | } 125 | } 126 | break; 127 | case RE_ALL: 128 | case RE_OUT: 129 | // 获取重定向文件名 130 | name = dealReOutStr(str2); 131 | if (name) { 132 | pid = fork(); 133 | if (pid == 0) { 134 | // 执行重定向 135 | fd = open(name, O_CREAT | O_RDWR, 0666); 136 | dup2(fd, 1); 137 | close(fd); 138 | // 递归 139 | doSomething(str2); 140 | exit(0); 141 | } else waitpid(pid, NULL, 0); 142 | } 143 | break; 144 | case RE_IN: 145 | name = dealReInStr(str2); 146 | if (name) { 147 | pid = fork(); 148 | if (pid == 0) { 149 | fd = open(name, O_CREAT | O_RDWR, 0666); 150 | dup2(fd, 0); 151 | close(fd); 152 | doSomething(str2); 153 | exit(0); 154 | } else waitpid(pid, NULL, 0); 155 | } 156 | break; 157 | } 158 | } 159 | } 160 | 161 | char *dealReOutStr(char *str) { 162 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 163 | int end; 164 | 165 | int symbol = findCharInStr(str, '>'); 166 | if (symbol < 0 || symbol == strlen(str) - 1) return NULL; 167 | 168 | // 寻找 > 符号后面的第一个单词 169 | if (str[symbol + 1] == ' ') { 170 | end = symbol + 2; 171 | for (int i = symbol + 2; i < strlen(str); i++) { 172 | if (str[i] == ' ') break; 173 | end++; 174 | } 175 | // 拷贝到name 176 | strncpy(name, &str[symbol + 2], end - (symbol + 2)); 177 | // 从原来的指令中删除重定向 178 | deleteFromStr(str, symbol, end); 179 | } else { 180 | end = symbol + 1; 181 | for (int i = symbol + 1; i < strlen(str); i++) { 182 | if (str[i] == ' ') break; 183 | end++; 184 | } 185 | strncpy(name, &str[symbol + 1], end - (symbol + 1)); 186 | deleteFromStr(str, symbol, end); 187 | } 188 | return name; 189 | } 190 | 191 | char *dealReInStr(char *str) { 192 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 193 | int end; 194 | 195 | int symbol = findCharInStr(str, '<'); 196 | if (symbol < 0 || symbol == strlen(str) - 1) return NULL; 197 | 198 | // 寻找 < 符号后面的第一个单词 199 | if (str[symbol + 1] == ' ') { 200 | end = symbol + 2; 201 | for (int i = symbol + 2; i < strlen(str); i++) { 202 | if (str[i] == ' ') break; 203 | end++; 204 | } 205 | // 拷贝到name 206 | strncpy(name, &str[symbol + 2], end - (symbol + 2)); 207 | // 从原来的指令中删除重定向 208 | deleteFromStr(str, symbol, end); 209 | } else { 210 | end = symbol + 1; 211 | for (int i = symbol + 1; i < strlen(str); i++) { 212 | if (str[i] == ' ') break; 213 | end++; 214 | } 215 | strncpy(name, &str[symbol + 1], end - (symbol + 1)); 216 | deleteFromStr(str, symbol, end); 217 | } 218 | return name; 219 | } 220 | 221 | void deleteFromStr(char *str, int start, int end) { 222 | int length = end - start; 223 | if (length > 0) { 224 | for (int i = start; i < strlen(str) - 1; i++) str[i] = str[i + 1]; 225 | str[strlen(str) - 1] = '\0'; 226 | deleteFromStr(str, start, end - 1); 227 | } 228 | } 229 | 230 | int findCharInStr(char *str, char c) { 231 | int symbol = -1; 232 | int i, j, end; 233 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 234 | for (i = 0; i < strlen(str); i++) { 235 | if (str[i] == c) { 236 | symbol = i; 237 | break; 238 | } 239 | } 240 | return symbol; 241 | } 242 | 243 | int mysys(char *arg) { 244 | // fork一个子进程 245 | pid_t fpid = fork(); 246 | if (fpid < 0) { 247 | // 如果获取子进程失败 248 | return -1; 249 | } else if (fpid == 0) { 250 | // 如果是子进程 251 | if (execl("/bin/sh", "sh", "-c", arg, (char *) 0) < 0) { 252 | return 127; 253 | } 254 | } else { 255 | // 等待子进程结束 256 | waitpid(fpid, NULL, 0); 257 | return 0; 258 | } 259 | return 0; 260 | } 261 | -------------------------------------------------------------------------------- /2-multi-process/4-sh3/build.sh: -------------------------------------------------------------------------------- 1 | gcc sh3.c -o sh3.run 2 | -------------------------------------------------------------------------------- /2-multi-process/4-sh3/sh3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUFFER_LEN 1024 9 | 10 | #define RE_NO 0 11 | #define RE_OUT 1 12 | #define RE_IN 2 13 | #define RE_ALL 3 14 | 15 | // 读入一行进入缓冲区 16 | int readLine(char *, int); 17 | // 清空缓冲区 18 | void bufferClear(char *, int); 19 | // 伪造system函数 20 | int mysys(char *); 21 | // 判断是否要重定向 22 | int needRedirect(char *); 23 | // 执行指令 24 | void do1(char *); 25 | void do2(char *); 26 | // 处理字符串中的输出重定向 27 | char *dealReOutStr(char *); 28 | // 处理字符串中的输入重定向 29 | char *dealReInStr(char *); 30 | // 寻找特定字符在字符串中的位置 31 | int findCharInStr(char *, char); 32 | // 删除字符串的一部分 33 | void deleteFromStr(char *, int, int); 34 | // 将字符串分成两半 35 | char *split2(char *, int); 36 | 37 | int main(int argc, char *argv[]) { 38 | char buffer[BUFFER_LEN]; 39 | 40 | // 开始主循环 41 | while (1) { 42 | // 输出shell标识符 43 | printf("$"); 44 | // 清空缓冲区 45 | bufferClear(buffer, BUFFER_LEN); 46 | // 读取一行,如果溢出了就报错 47 | if (readLine(buffer, BUFFER_LEN)) { 48 | // 执行指令 49 | do2(buffer); 50 | } else { 51 | printf("You can't input so much char at one time!\n"); 52 | } 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | int readLine(char *buffer, int length) { 59 | char c; 60 | int count = 0; 61 | c = getchar(); 62 | while (c != '\n') { 63 | count++; 64 | if (count < length - 1) { 65 | buffer[count - 1] = c; 66 | } else return 0; 67 | c = getchar(); 68 | } 69 | buffer[count] = '\0'; 70 | return 1; 71 | } 72 | 73 | void bufferClear(char *buffer, int length) { 74 | for (int i = 0; i < length; i++) buffer[i] = '\0'; 75 | } 76 | 77 | int needRedirect(char *str) { 78 | // 寻找 < 符号和 > 符号 79 | int findLeft = 0; 80 | int findRight = 0; 81 | for (int i = 0; i < strlen(str); i++) { 82 | if (str[i] == '<') findLeft = 1; 83 | if (str[i] == '>') findRight = 1; 84 | } 85 | if (!findLeft && findRight) return RE_OUT; 86 | if (findLeft && !findRight) return RE_IN; 87 | if (findLeft && findRight) return RE_ALL; 88 | return RE_NO; 89 | } 90 | 91 | void do1(char *str) { 92 | // 寻找 | 的位置 93 | char right[BUFFER_LEN]; 94 | strcpy(right, str); 95 | int symbol = findCharInStr(right, '|'); 96 | pid_t pid; 97 | int fd[2]; 98 | 99 | if (symbol > 0) { 100 | // 将前后分开 101 | char *left = split2(right, symbol); 102 | // 创建子进程 103 | pipe(fd); 104 | pid = fork(); 105 | if (pid == 0) { 106 | dup2(fd[1], 1); 107 | close(fd[0]); 108 | close(fd[1]); 109 | // 执行指令 110 | do2(left); 111 | exit(0); 112 | } else { 113 | dup2(fd[0], 0); 114 | close(fd[0]); 115 | close(fd[1]); 116 | waitpid(pid, NULL, 0); 117 | // 递归执行右半边 118 | do1(right); 119 | } 120 | } else { 121 | do2(right); 122 | } 123 | } 124 | 125 | void do2(char *str) { 126 | // 缓冲区 127 | char buffer[BUFFER_LEN]; 128 | char str2[BUFFER_LEN]; 129 | strcpy(str2, str); 130 | char path[BUFFER_LEN]; 131 | char *p = NULL; 132 | char *name = NULL; 133 | // 文件描述符 134 | int fd; 135 | // 子进程 136 | pid_t pid; 137 | 138 | if (strcmp(str, "")) { 139 | // 判断指令类型 140 | int type = needRedirect(str); 141 | // 根据指令情况进行处理 142 | switch (type) { 143 | case RE_NO: 144 | // 拷贝输入 145 | strcpy(buffer, str); 146 | // 分割参数 147 | p = strtok(buffer, " "); 148 | // 根据指令的不同做不同的事情 149 | if (p) { 150 | if (!strcmp(p, "cd")) { 151 | p = strtok(NULL, ""); 152 | if (chdir(p) < 0) printf("no such directory\n"); 153 | } else if (!strcmp(p, "pwd")) { 154 | getcwd(path, BUFFER_LEN); 155 | printf("%s\n", path); 156 | } else if (!strcmp(p, "exit")) { 157 | // 退出程序 158 | exit(0); 159 | } else { 160 | mysys(str); 161 | } 162 | } 163 | break; 164 | case RE_ALL: 165 | case RE_OUT: 166 | // 获取重定向文件名 167 | name = dealReOutStr(str2); 168 | if (name) { 169 | pid = fork(); 170 | if (pid == 0) { 171 | // 执行重定向 172 | fd = open(name, O_CREAT | O_RDWR, 0666); 173 | dup2(fd, 1); 174 | close(fd); 175 | // 递归 176 | do2(str2); 177 | exit(0); 178 | } else waitpid(pid, NULL, 0); 179 | } 180 | break; 181 | case RE_IN: 182 | name = dealReInStr(str2); 183 | if (name) { 184 | pid = fork(); 185 | if (pid == 0) { 186 | fd = open(name, O_CREAT | O_RDWR, 0666); 187 | dup2(fd, 0); 188 | close(fd); 189 | do2(str2); 190 | exit(0); 191 | } else waitpid(pid, NULL, 0); 192 | } 193 | break; 194 | } 195 | } 196 | } 197 | 198 | char *dealReOutStr(char *str) { 199 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 200 | int end; 201 | 202 | int symbol = findCharInStr(str, '>'); 203 | if (symbol < 0 || symbol == strlen(str) - 1) return NULL; 204 | 205 | // 寻找 > 符号后面的第一个单词 206 | if (str[symbol + 1] == ' ') { 207 | end = symbol + 2; 208 | for (int i = symbol + 2; i < strlen(str); i++) { 209 | if (str[i] == ' ') break; 210 | end++; 211 | } 212 | // 拷贝到name 213 | strncpy(name, &str[symbol + 2], end - (symbol + 2)); 214 | // 从原来的指令中删除重定向 215 | deleteFromStr(str, symbol, end); 216 | } else { 217 | end = symbol + 1; 218 | for (int i = symbol + 1; i < strlen(str); i++) { 219 | if (str[i] == ' ') break; 220 | end++; 221 | } 222 | strncpy(name, &str[symbol + 1], end - (symbol + 1)); 223 | deleteFromStr(str, symbol, end); 224 | } 225 | return name; 226 | } 227 | 228 | char *dealReInStr(char *str) { 229 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 230 | int end; 231 | 232 | int symbol = findCharInStr(str, '<'); 233 | if (symbol < 0 || symbol == strlen(str) - 1) return NULL; 234 | 235 | // 寻找 < 符号后面的第一个单词 236 | if (str[symbol + 1] == ' ') { 237 | end = symbol + 2; 238 | for (int i = symbol + 2; i < strlen(str); i++) { 239 | if (str[i] == ' ') break; 240 | end++; 241 | } 242 | // 拷贝到name 243 | strncpy(name, &str[symbol + 2], end - (symbol + 2)); 244 | // 从原来的指令中删除重定向 245 | deleteFromStr(str, symbol, end); 246 | } else { 247 | end = symbol + 1; 248 | for (int i = symbol + 1; i < strlen(str); i++) { 249 | if (str[i] == ' ') break; 250 | end++; 251 | } 252 | strncpy(name, &str[symbol + 1], end - (symbol + 1)); 253 | deleteFromStr(str, symbol, end); 254 | } 255 | return name; 256 | } 257 | 258 | void deleteFromStr(char *str, int start, int end) { 259 | int length = end - start; 260 | if (length > 0) { 261 | for (int i = start; i < strlen(str) - 1; i++) str[i] = str[i + 1]; 262 | str[strlen(str) - 1] = '\0'; 263 | deleteFromStr(str, start, end - 1); 264 | } 265 | } 266 | 267 | int findCharInStr(char *str, char c) { 268 | int symbol = -1; 269 | int i, j, end; 270 | char *name = (char *) malloc(sizeof(char) * BUFFER_LEN); 271 | for (i = 0; i < strlen(str); i++) { 272 | if (str[i] == c) { 273 | symbol = i; 274 | break; 275 | } 276 | } 277 | return symbol; 278 | } 279 | 280 | int mysys(char *arg) { 281 | // fork一个子进程 282 | pid_t fpid = fork(); 283 | if (fpid < 0) { 284 | // 如果获取子进程失败 285 | return -1; 286 | } else if (fpid == 0) { 287 | // 如果是子进程 288 | if (execl("/bin/sh", "sh", "-c", arg, (char *) 0) < 0) { 289 | return 127; 290 | } 291 | } else { 292 | // 等待子进程结束 293 | waitpid(fpid, NULL, 0); 294 | return 0; 295 | } 296 | return 0; 297 | } 298 | 299 | char *split2(char *str, int location) { 300 | str[location] = '\0'; 301 | return &str[location + 1]; 302 | } 303 | -------------------------------------------------------------------------------- /3-multi-thread/1-pi1/build.sh: -------------------------------------------------------------------------------- 1 | gcc pi1.c -o pi1.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/1-pi1/pi1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 级数深度 5 | int depth = 0; 6 | // 前半部分的结果 7 | float left = 0; 8 | // 后半部分的结果 9 | float right = 0; 10 | 11 | // 子线程函数 12 | void *thread_func(void *); 13 | // 计算莱布尼茨级数深度从start到end的一部分 14 | float calculate(int, int); 15 | 16 | int main(int argc, char *argv[]) { 17 | // 输入参数判断 18 | if (argc < 2) { 19 | printf("too few arguments\nusage: ./pi1.run depth\n"); 20 | return 0; 21 | } 22 | sscanf(argv[1], "%d", &depth); 23 | if (depth <= 0) { 24 | printf("the depth is too small\n"); 25 | return 0; 26 | } 27 | if (depth == 1) { 28 | printf("1\n"); 29 | return 0; 30 | } 31 | 32 | // 创建子线程 33 | pthread_t child_thread; 34 | pthread_create(&child_thread, NULL, &thread_func, NULL); 35 | 36 | // 计算莱布尼茨技术前半部分 37 | left = calculate(1, depth / 2); 38 | 39 | // 等待子线程执行完毕 40 | pthread_join(child_thread, NULL); 41 | 42 | // 输出结果 43 | printf("%f\n", left + right); 44 | return 0; 45 | } 46 | 47 | void *thread_func(void *args) { 48 | right = calculate(depth / 2 + 1, depth); 49 | return NULL; 50 | } 51 | 52 | float calculate(int start, int end) { 53 | float result; 54 | for (int i = start; i <= end; i++) 55 | result += i % 2 == 0 ? (0 - 1.0 / (i * 2 - 1)) : 1.0 / (i * 2 - 1); 56 | return result; 57 | } 58 | -------------------------------------------------------------------------------- /3-multi-thread/2-pi2/build.sh: -------------------------------------------------------------------------------- 1 | gcc pi2.c -o pi2.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/2-pi2/pi2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // 线程参数结构体 6 | typedef struct { 7 | int start; 8 | int end; 9 | float result; 10 | } thread_args, *thread_args_ptr; 11 | 12 | // 计算莱布尼茨级数深度从start到end的一部分 13 | void *thread_func(void *); 14 | float calculate(int, int); 15 | 16 | int main(int argc, char *argv[]) { 17 | // 参数校验 18 | if (argc < 3) { 19 | printf("too few argument\nusage: ./pi2.run depth thread_num\n"); 20 | } 21 | // 读入参数 22 | int depth = 0; 23 | int thread_num = 0; 24 | sscanf(argv[1], "%d", &depth); 25 | sscanf(argv[2], "%d", &thread_num); 26 | 27 | // 一点判断 28 | if (depth <= 0) { 29 | printf("the depth is too small\n"); 30 | return 0; 31 | } 32 | if (thread_num <= 1) { 33 | printf("the thread is too few\n"); 34 | return 0; 35 | } 36 | if (thread_num > 100) { 37 | printf("you can't get so many thread at one time\n"); 38 | } 39 | if (depth < thread_num) { 40 | printf("the depth can't small then thread_num\n"); 41 | return 0; 42 | } 43 | 44 | // 创建进程 45 | pthread_t *tid_array = (pthread_t *) malloc( 46 | sizeof(pthread_t) * (thread_num - 1) 47 | ); 48 | thread_args_ptr thread_args_array = (thread_args_ptr) malloc( 49 | sizeof(thread_args) * (thread_num - 1) 50 | ); 51 | for (int i = 0; i < thread_num - 1; i++) { 52 | thread_args_array[i].start = i * depth / thread_num + 1; 53 | thread_args_array[i].end = (i + 1) * depth / thread_num; 54 | thread_args_array[i].result = 0; 55 | 56 | pthread_create( 57 | &tid_array[i], NULL, &thread_func, (void *) &thread_args_array[i] 58 | ); 59 | } 60 | 61 | // 自己完成剩下的任务 62 | float result = calculate((thread_num - 1) * depth / thread_num + 1, depth); 63 | 64 | // 等待线程执行完毕 65 | for (int i = 0; i < thread_num - 1; i++) 66 | pthread_join(tid_array[i], NULL); 67 | 68 | // 计算结果并且输出 69 | for (int i = 0; i < thread_num - 1; i++) { 70 | result += thread_args_array[i].result; 71 | } 72 | printf("%f\n", result); 73 | return 0; 74 | } 75 | 76 | void *thread_func(void *args) { 77 | thread_args_ptr temp = (thread_args_ptr) args; 78 | temp->result = calculate( 79 | temp->start, temp->end 80 | ); 81 | 82 | return NULL; 83 | } 84 | 85 | float calculate(int start, int end) { 86 | float result; 87 | for (int i = start; i <= end; i++) 88 | result += i % 2 == 0 ? (0 - 1.0 / (i * 2 - 1)) : 1.0 / (i * 2 - 1); 89 | return result; 90 | } 91 | -------------------------------------------------------------------------------- /3-multi-thread/3-sort/build.sh: -------------------------------------------------------------------------------- 1 | gcc sort.c -o sort.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/3-sort/sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ARR_LEN 1024 5 | 6 | int length = 0; 7 | int numbers[ARR_LEN]; 8 | 9 | // 子线程 10 | void *thread_func(void *); 11 | // 选择排序 12 | void selectSort(int *, int); 13 | 14 | int main(int argc, char *argv[]) { 15 | // 输入数据 16 | printf("array length: "); 17 | scanf("%d", &length); 18 | if (length <= 0) { 19 | printf("the length is too small\n"); 20 | return 0; 21 | } 22 | printf("array: "); 23 | for (int i = 0; i < length; i++) scanf("%d", &numbers[i]); 24 | if (length == 1) { 25 | printf("result: %d\n", numbers[0]); 26 | return 0; 27 | } 28 | 29 | // 创建线程辅助运算 30 | pthread_t child; 31 | pthread_create(&child, NULL, &thread_func, NULL); 32 | 33 | // 选择排序前半部分 34 | selectSort(numbers, length / 2); 35 | 36 | // 等待线程执行完毕 37 | pthread_join(child, NULL); 38 | 39 | // 进行归并排序 40 | int result[ARR_LEN]; 41 | int p = 0, q = length / 2, r = 0; 42 | while (p < length / 2 || q < length) { 43 | if (p >= length / 2 && q < length) result[r++] = numbers[q++]; 44 | if (p < length / 2 && q >= length) result[r++] = numbers[p++]; 45 | if (p < length / 2 || q < length) 46 | result[r++] = numbers[p] < numbers[q] ? numbers[p++] : numbers[q++]; 47 | } 48 | 49 | printf("result: "); 50 | for (int i = 0; i < length; i++) printf("%d ", result[i]); 51 | printf("\n"); 52 | 53 | return 0; 54 | } 55 | 56 | void *thread_func(void *args) { 57 | // 选择排序后半部分 58 | selectSort(&numbers[length / 2], length - length / 2); 59 | 60 | return NULL; 61 | } 62 | 63 | void selectSort(int *arr, int len) { 64 | for (int i = 0; i < len; i++) { 65 | int min = i; 66 | for (int j = i; j < len; j++) 67 | if (arr[j] < arr[min]) min = j; 68 | int temp = arr[i]; 69 | arr[i] = arr[min]; 70 | arr[min] = temp; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /3-multi-thread/4-pc1/build.sh: -------------------------------------------------------------------------------- 1 | gcc pc1.c -o pc1.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/4-pc1/pc1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BUFFER_LEN 4 5 | #define START_CHAR 'a' 6 | #define CHAR_NUM 8 7 | 8 | // 两个缓冲区 9 | char buffer1[BUFFER_LEN]; 10 | char buffer2[BUFFER_LEN]; 11 | // 四个 io 指针 12 | int in1 = 0, out1 = 0, in2 = 0, out2 = 0; 13 | 14 | // buffer 是否为空 15 | int buffer_is_empty(int, int); 16 | // buffer 是否为满 17 | int buffer_is_full(int, int); 18 | // 获取一个 item 并且移动 out 指针 19 | char get_item(char *, int *); 20 | //放入一个 item 并且移动 in 指针 21 | void put_item(char *, int *, char item); 22 | 23 | // 临界区 24 | pthread_mutex_t mutex1, mutex2; 25 | // 条件变量 26 | pthread_cond_t wait_empty_buffer1, wait_empty_buffer2; 27 | pthread_cond_t wait_full_buffer1, wait_full_buffer2; 28 | 29 | // 三个子线程 30 | void *producer_func(void *); 31 | void *calculator_func(void *); 32 | void *consumer_func(void *); 33 | 34 | int main(int argc, char *argv[]) { 35 | // 线程 tid 36 | pthread_t calculator_thread, consumer_thread; 37 | 38 | // 初始化条件变量 39 | pthread_mutex_init(&mutex1, NULL); 40 | pthread_cond_init(&wait_empty_buffer1, NULL); 41 | pthread_cond_init(&wait_full_buffer1, NULL); 42 | pthread_mutex_init(&mutex2, NULL); 43 | pthread_cond_init(&wait_empty_buffer2, NULL); 44 | pthread_cond_init(&wait_full_buffer2, NULL); 45 | 46 | // 创建计算者和消费者线程 47 | pthread_create(&calculator_thread, NULL, &calculator_func, NULL); 48 | pthread_create(&consumer_thread, NULL, &consumer_func, NULL); 49 | 50 | // 执行生产者线程 51 | producer_func(NULL); 52 | 53 | // 等待计算者和消费者线程执行完毕 54 | pthread_join(calculator_thread, NULL); 55 | pthread_join(consumer_thread, NULL); 56 | 57 | printf("\n"); 58 | 59 | return 0; 60 | } 61 | 62 | int buffer_is_empty(int in, int out) { 63 | return in == out; 64 | } 65 | 66 | int buffer_is_full(int in, int out) { 67 | return (in + 1) % BUFFER_LEN == out; 68 | } 69 | 70 | char get_item(char *buffer, int *out) { 71 | char item; 72 | item = buffer[*out]; 73 | *out = (*out + 1) % BUFFER_LEN; 74 | return item; 75 | } 76 | 77 | void put_item(char *buffer, int *in, char item) { 78 | buffer[*in] = item; 79 | *in = (*in + 1) % BUFFER_LEN; 80 | } 81 | 82 | void *producer_func(void *args) { 83 | for (int i = 0; i < CHAR_NUM; i++) { 84 | // 加锁 85 | pthread_mutex_lock(&mutex1); 86 | // 如果缓冲区是满的,就等待一个空的缓冲区 87 | while (buffer_is_full(in1, out1)) 88 | pthread_cond_wait(&wait_empty_buffer1, &mutex1); 89 | char item = START_CHAR + i; 90 | put_item(buffer1, &in1, item); 91 | // printf("produce item: %c\n", item); 92 | // 改变条件变量并且解锁 93 | pthread_cond_signal(&wait_full_buffer1); 94 | pthread_mutex_unlock(&mutex1); 95 | } 96 | return NULL; 97 | } 98 | 99 | void *calculator_func(void *args) { 100 | for (int i = 0; i < CHAR_NUM; i++) { 101 | pthread_mutex_lock(&mutex1); 102 | while (buffer_is_empty(in1, out1)) 103 | pthread_cond_wait(&wait_full_buffer1, &mutex1); 104 | char item = get_item(buffer1, &out1); 105 | pthread_cond_signal(&wait_empty_buffer1); 106 | pthread_mutex_unlock(&mutex1); 107 | 108 | pthread_mutex_lock(&mutex2); 109 | while (buffer_is_full(in2, out2)) 110 | pthread_cond_wait(&wait_empty_buffer2, &mutex2); 111 | put_item(buffer2, &in2, item - 32); 112 | // printf("calculate item: %c to %c\n", item, item - 21); 113 | pthread_cond_signal(&wait_full_buffer2); 114 | pthread_mutex_unlock(&mutex2); 115 | } 116 | return NULL; 117 | } 118 | 119 | void *consumer_func(void *args) { 120 | for (int i = 0; i < CHAR_NUM; i++) { 121 | pthread_mutex_lock(&mutex2); 122 | while (buffer_is_empty(in2, out2)) 123 | pthread_cond_wait(&wait_full_buffer2, &mutex2); 124 | char item = get_item(buffer2, &out2); 125 | printf("%c ", item); 126 | pthread_cond_signal(&wait_empty_buffer2); 127 | pthread_mutex_unlock(&mutex2); 128 | } 129 | return NULL; 130 | } 131 | -------------------------------------------------------------------------------- /3-multi-thread/5-pc2/build.sh: -------------------------------------------------------------------------------- 1 | gcc pc2.c -o pc2.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/5-pc2/pc2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BUFFER_LEN 4 5 | #define START_CHAR 'a' 6 | #define CHAR_NUM 8 7 | 8 | // 两个缓冲区 9 | char buffer1[BUFFER_LEN]; 10 | char buffer2[BUFFER_LEN]; 11 | // 四个 io 指针 12 | int in1 = 0, out1 = 0, in2 = 0, out2 = 0; 13 | 14 | // buffer 是否为空 15 | int buffer_is_empty(int, int); 16 | // buffer 是否为满 17 | int buffer_is_full(int, int); 18 | // 获取一个 item 并且移动 out 指针 19 | char get_item(char *, int *); 20 | //放入一个 item 并且移动 in 指针 21 | void put_item(char *, int *, char item); 22 | 23 | // 信号量 24 | typedef struct { 25 | int value; 26 | pthread_mutex_t mutex; 27 | pthread_cond_t cond; 28 | } sema_t; 29 | 30 | // 信号量初始化 31 | void sema_init(sema_t *, int); 32 | // 等待条件变量 33 | void sema_wait(sema_t *); 34 | // 唤醒等待条件变量的线程 35 | void sema_signal(sema_t *); 36 | 37 | // 三个子线程 38 | void *producer_func(void *); 39 | void *calculator_func(void *); 40 | void *consumer_func(void *); 41 | 42 | // 定义信号量 43 | sema_t mutex_sema1, mutex_sema2; 44 | sema_t empty_buffer_sema1, empty_buffer_sema2; 45 | sema_t full_buffer_sema1, full_buffer_sema2; 46 | 47 | int main(int argc, char *argv[]) { 48 | // 线程标识符 49 | pthread_t calculator_thread, consumer_thread; 50 | 51 | // 初始化信号量 52 | sema_init(&mutex_sema1, 1); 53 | sema_init(&empty_buffer_sema1, 1); 54 | sema_init(&full_buffer_sema1, 0); 55 | sema_init(&mutex_sema2, 1); 56 | sema_init(&empty_buffer_sema2, 1); 57 | sema_init(&full_buffer_sema2, 0); 58 | 59 | // 创建计算者和消费者进程 60 | pthread_create(&calculator_thread, NULL, &calculator_func, NULL); 61 | pthread_create(&consumer_thread, NULL, &consumer_func, NULL); 62 | // 执行生产者线程 63 | producer_func(NULL); 64 | 65 | // 等待线程执行完毕 66 | pthread_join(calculator_thread, NULL); 67 | pthread_join(consumer_thread, NULL); 68 | 69 | printf("\n"); 70 | return 0; 71 | } 72 | 73 | int buffer_is_empty(int in, int out) { 74 | return in == out; 75 | } 76 | 77 | int buffer_is_full(int in, int out) { 78 | return (in + 1) % BUFFER_LEN == out; 79 | } 80 | 81 | char get_item(char *buffer, int *out) { 82 | char item; 83 | item = buffer[*out]; 84 | *out = (*out + 1) % BUFFER_LEN; 85 | return item; 86 | } 87 | 88 | void put_item(char *buffer, int *in, char item) { 89 | buffer[*in] = item; 90 | *in = (*in + 1) % BUFFER_LEN; 91 | } 92 | 93 | void sema_init(sema_t *sema, int value) { 94 | sema->value = value; 95 | pthread_mutex_init(&sema->mutex, NULL); 96 | pthread_cond_init(&sema->cond, NULL); 97 | } 98 | 99 | void sema_wait(sema_t *sema) { 100 | pthread_mutex_lock(&sema->mutex); 101 | sema->value--; 102 | while (sema->value < 0) 103 | pthread_cond_wait(&sema->cond, &sema->mutex); 104 | pthread_mutex_unlock(&sema->mutex); 105 | } 106 | 107 | void sema_signal(sema_t *sema) { 108 | pthread_mutex_lock(&sema->mutex); 109 | sema->value++; 110 | pthread_cond_signal(&sema->cond); 111 | pthread_mutex_unlock(&sema->mutex); 112 | } 113 | 114 | void *producer_func(void *args) { 115 | for (int i = 0; i < CHAR_NUM; i++) { 116 | sema_wait(&empty_buffer_sema1); 117 | sema_wait(&mutex_sema1); 118 | char item = START_CHAR + i; 119 | put_item(buffer1, &in1, item); 120 | sema_signal(&mutex_sema1); 121 | sema_signal(&full_buffer_sema1); 122 | } 123 | return NULL; 124 | } 125 | 126 | void *calculator_func(void *args) { 127 | for (int i = 0; i < CHAR_NUM; i++) { 128 | sema_wait(&full_buffer_sema1); 129 | sema_wait(&mutex_sema1); 130 | char item = get_item(buffer1, &out1); 131 | sema_signal(&mutex_sema1); 132 | sema_signal(&empty_buffer_sema1); 133 | 134 | sema_wait(&empty_buffer_sema2); 135 | sema_wait(&mutex_sema2); 136 | put_item(buffer2, &in2, item - 32); 137 | sema_signal(&mutex_sema2); 138 | sema_signal(&full_buffer_sema2); 139 | } 140 | return NULL; 141 | } 142 | 143 | void *consumer_func(void *args) { 144 | for (int i = 0; i < CHAR_NUM; i++) { 145 | sema_wait(&full_buffer_sema2); 146 | sema_wait(&mutex_sema2); 147 | char item = get_item(buffer2, &out2); 148 | printf("%c ", item); 149 | sema_signal(&mutex_sema2); 150 | sema_signal(&empty_buffer_sema2); 151 | } 152 | return NULL; 153 | } 154 | -------------------------------------------------------------------------------- /3-multi-thread/6-ring/build.sh: -------------------------------------------------------------------------------- 1 | gcc ring.c -o ring.run -pthread 2 | -------------------------------------------------------------------------------- /3-multi-thread/6-ring/ring.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int send; 6 | 7 | typedef struct { 8 | pthread_t *pre, *start; 9 | int no; 10 | } thread_args, *thread_args_ptr; 11 | 12 | void *thread_func(void *); 13 | 14 | int main(int argc, char *argv[]) { 15 | // 参数判断 16 | if (argc < 2) { 17 | printf("too few arguments\nusage: ./ring.run n\n"); 18 | return 0; 19 | } 20 | 21 | // 输入参数 22 | int n; 23 | sscanf(argv[1], "%d", &n); 24 | if (n <= 1) { 25 | printf("the n is too small\n"); 26 | return 0; 27 | } 28 | 29 | // 创建线程 30 | pthread_t *thread_array = (pthread_t *) malloc(sizeof(pthread_t) * n); 31 | thread_args_ptr thread_args_array = (thread_args_ptr) malloc(sizeof(thread_args) * n); 32 | for (int i = 1; i < n; i++) { 33 | thread_args_array[i].pre = &thread_array[i - 1]; 34 | thread_args_array[i].start = &thread_array[0]; 35 | thread_args_array[i].no = i; 36 | } 37 | thread_args_array[0].pre = &thread_array[n - 1]; 38 | thread_args_array[0].start = &thread_array[0]; 39 | thread_args_array[0].no = 0; 40 | 41 | for (int i = 0; i < n; i++) 42 | pthread_create(&thread_array[i], NULL, &thread_func, (void *) &thread_args_array[i]); 43 | 44 | pthread_join(thread_array[n - 1], NULL); 45 | 46 | return 0; 47 | } 48 | 49 | void *thread_func(void *args) { 50 | thread_args_ptr temp = (thread_args_ptr) args; 51 | 52 | // 如果是第一个线程 53 | if (temp->no == 0) { 54 | send = 1; 55 | printf("thread %d send: %d\n", temp->no + 1, send); 56 | // 如果不是第一个线程 57 | } else { 58 | pthread_join(*temp->pre, NULL); 59 | printf("thread %d recv: %d\n", temp->no + 1, send); 60 | send += 1; 61 | printf("thread %d send: %d\n", temp->no + 1, send); 62 | } 63 | return NULL; 64 | } 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 John Kindem 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NUAA 2018 os-tasks 2 | 2018年NUAA操作系统实践作业,作者161520311,欢迎参考、fork、点星星ヾ(◍°∇°◍)ノ゙✨ 3 | 4 | # 使用说明 5 | **所有代码均在unix系统上运行,请勿在windows上玩弄,MacOS上亲测能够运行,Linux应该也没问题,Clang和Gcc环境下均编译通过** 6 | 7 | 根目录下有三个大文件夹,分别为三种类型的题目:文件读写、多进程、多线程,每个大文件夹下有很多小文件夹,一个小文件夹对应一道题目,每个题目的文件夹下有一个与文件夹同名的源码文件和一个编译脚本,你只需要进入具体题目的文件夹然后运行我写的编译脚本即可产生.run格式的的可执行文件,然后enjoy即可☺ 8 | 9 | 比如myecho: 10 | ``` 11 | // 从项目根目录开始 12 | cd 1-fileio 13 | cd 1-myecho 14 | ./build.sh 15 | ./myecho.run 16 | ``` 17 | 18 | 如果无法执行编译脚本,尝试给编译脚本加上执行权限: 19 | ``` 20 | chmod 777 buils.sh 21 | ``` 22 | 23 | # 题目详情 24 | 参照Linuxmooc给出的操作系统编程练习题列表: 25 | [Tasks - Linuxmooc](http://www.linuxmooc.com/task.html) 26 | --------------------------------------------------------------------------------