https://jyywiki.cn/OS/2024/labs/M4.md
今年在追番蒋炎岩老师的 NJU OS 2024spring。因为之前已经做过不少 os lab,所以这次不打算做 os lab,但是发现 jyy 的非 OS lab 设计得都非常有意思,所以决定做一下。
以前我从来没有思考过 crepl 要怎么实现,没想到利用 gcc 就可以如此容易的实现一个 crepl,以前没怎么接触过的 so 库的用法和其本质也逐渐熟悉起来了。
虽说出于学术诚信上的考量 jyy 并不希望我们公开 lab 代码,但是这个 lab 确实没什么难的地方,相信不会有南大学子上网搜代码抄的。并且我因为偷懒直接使用了 system
,直接抄我的也得老老实实改成 fork
& execve
实现:D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dlfcn.h>
int wrapper_count = 0;
int main(int argc, char *argv[]) { static char line[4096]; char cmd[4096]; char temp_so_path[] = "/tmp/crepl_so.XXXXXX"; char temp_src_path[] = "/tmp/crepl_src.XXXXXX";
int fd = mkstemp(temp_so_path); if (fd == -1) { perror("mkstemp failed"); return EXIT_FAILURE; } fd = mkstemp(temp_src_path); if (fd == -1) { perror("mkstemp failed"); return EXIT_FAILURE; }
sprintf(cmd, "gcc -Wno-implicit-function-declaration -xc " "-shared -o %s %s", temp_so_path, temp_src_path);
while (1) { printf("crepl> "); fflush(stdout);
if (!fgets(line, sizeof(line), stdin)) { break; }
int is_function = strncmp(line, "int ", strlen("int ")) == 0; char func_name[256]; char func[4096];
if (is_function) { strcpy(func, line); } else { sprintf(func_name, "__expr_wrapper_%d", wrapper_count++); sprintf(func, "int %s() { return %s; }", func_name, line); }
FILE* file = fopen(temp_src_path, "a"); if (file == NULL) { perror("Failed to open file"); return EXIT_FAILURE; } fprintf(file, "%s\n", func); fflush(file); fclose(file);
if (is_function) { printf("OK.\n"); continue; }
system(cmd);
void *handle; int (*function)(void); char *error; int eval_result;
handle = dlopen(temp_so_path, RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); return 1; }
dlerror(); *(void **) (&function) = dlsym(handle, func_name); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); dlclose(handle); return 1; }
eval_result = function();
dlclose(handle);
printf("= %d.\n", eval_result); } }
|