From 51dbee6ad83729354e7684c5eea2973025c02959 Mon Sep 17 00:00:00 2001 From: Karim Date: Sun, 9 Nov 2025 23:56:17 +0300 Subject: [PATCH 1/2] fix .gitignore --- lab/vtsh/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lab/vtsh/.gitignore b/lab/vtsh/.gitignore index fb90d94..8f5d964 100644 --- a/lab/vtsh/.gitignore +++ b/lab/vtsh/.gitignore @@ -6,3 +6,7 @@ build/ # Python __pycache__/ + +.idea/* + +some.bin \ No newline at end of file From 1ada46f5071efeae9c34267e9c95745c02ef4b7e Mon Sep 17 00:00:00 2001 From: Karim Date: Sun, 9 Nov 2025 23:34:18 +0300 Subject: [PATCH 2/2] Implement all --- lab/vtsh/.idea/.gitignore | 8 + lab/vtsh/.idea/codeStyles/Project.xml | 105 ++++++ lab/vtsh/.idea/codeStyles/codeStyleConfig.xml | 5 + lab/vtsh/.idea/editor.xml | 344 ++++++++++++++++++ lab/vtsh/.idea/misc.xml | 7 + lab/vtsh/.idea/modules.xml | 8 + lab/vtsh/.idea/vcs.xml | 6 + lab/vtsh/.idea/vtsh.iml | 2 + lab/vtsh/bin/CMakeLists.txt | 11 + lab/vtsh/bin/cpu_linreg | Bin 0 -> 33784 bytes lab/vtsh/bin/cpu_linreg.c | 74 ++++ lab/vtsh/bin/ema_join.h | 20 + lab/vtsh/bin/ema_join_algo.c | 49 +++ lab/vtsh/bin/ema_join_io.c | 62 ++++ lab/vtsh/bin/ema_join_nl.c | 84 +++++ lab/vtsh/bin/io_load.c | 16 + lab/vtsh/bin/io_load.h | 32 ++ lab/vtsh/bin/io_load_args.c | 125 +++++++ lab/vtsh/bin/io_load_runner.c | 176 +++++++++ lab/vtsh/bin/main | Bin 0 -> 34296 bytes lab/vtsh/bin/main.c | 115 +++++- lab/vtsh/joined.tbl | 4 + lab/vtsh/left.tbl | 4 + lab/vtsh/out.bin | Bin 0 -> 524288 bytes lab/vtsh/right.tbl | 5 + lab/vtsh/test/shell | 1 + lab/vtsh/test/test_redirection.py | 2 +- 27 files changed, 1261 insertions(+), 4 deletions(-) create mode 100644 lab/vtsh/.idea/.gitignore create mode 100644 lab/vtsh/.idea/codeStyles/Project.xml create mode 100644 lab/vtsh/.idea/codeStyles/codeStyleConfig.xml create mode 100644 lab/vtsh/.idea/editor.xml create mode 100644 lab/vtsh/.idea/misc.xml create mode 100644 lab/vtsh/.idea/modules.xml create mode 100644 lab/vtsh/.idea/vcs.xml create mode 100644 lab/vtsh/.idea/vtsh.iml create mode 100755 lab/vtsh/bin/cpu_linreg create mode 100644 lab/vtsh/bin/cpu_linreg.c create mode 100644 lab/vtsh/bin/ema_join.h create mode 100644 lab/vtsh/bin/ema_join_algo.c create mode 100644 lab/vtsh/bin/ema_join_io.c create mode 100644 lab/vtsh/bin/ema_join_nl.c create mode 100644 lab/vtsh/bin/io_load.c create mode 100644 lab/vtsh/bin/io_load.h create mode 100644 lab/vtsh/bin/io_load_args.c create mode 100644 lab/vtsh/bin/io_load_runner.c create mode 100755 lab/vtsh/bin/main create mode 100644 lab/vtsh/joined.tbl create mode 100644 lab/vtsh/left.tbl create mode 100644 lab/vtsh/out.bin create mode 100644 lab/vtsh/right.tbl create mode 120000 lab/vtsh/test/shell diff --git a/lab/vtsh/.idea/.gitignore b/lab/vtsh/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/lab/vtsh/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/lab/vtsh/.idea/codeStyles/Project.xml b/lab/vtsh/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..81469bd --- /dev/null +++ b/lab/vtsh/.idea/codeStyles/Project.xml @@ -0,0 +1,105 @@ + + + + + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/codeStyles/codeStyleConfig.xml b/lab/vtsh/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/lab/vtsh/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/editor.xml b/lab/vtsh/.idea/editor.xml new file mode 100644 index 0000000..0093ef6 --- /dev/null +++ b/lab/vtsh/.idea/editor.xml @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/misc.xml b/lab/vtsh/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/lab/vtsh/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/modules.xml b/lab/vtsh/.idea/modules.xml new file mode 100644 index 0000000..af61fa6 --- /dev/null +++ b/lab/vtsh/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/vcs.xml b/lab/vtsh/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/lab/vtsh/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lab/vtsh/.idea/vtsh.iml b/lab/vtsh/.idea/vtsh.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/lab/vtsh/.idea/vtsh.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/lab/vtsh/bin/CMakeLists.txt b/lab/vtsh/bin/CMakeLists.txt index 7ef16bd..823b2f2 100644 --- a/lab/vtsh/bin/CMakeLists.txt +++ b/lab/vtsh/bin/CMakeLists.txt @@ -14,3 +14,14 @@ target_link_libraries( PRIVATE libvtsh ) + +add_executable( + cpu_linreg + cpu_linreg.c +) + +target_include_directories( + cpu_linreg + PUBLIC + . +) diff --git a/lab/vtsh/bin/cpu_linreg b/lab/vtsh/bin/cpu_linreg new file mode 100755 index 0000000000000000000000000000000000000000..50aa45f576d970cc27caaab0c47d114a96901be9 GIT binary patch literal 33784 zcmeI5e{5S<701u>YdfdO8h5FdLQ~sGSDH<2)3FwXp=u6E*t(6j+Cqt@HaB+Sq$Y_S z9EYu>0yAq6KpHiw)csXC{bO@bk=g;0`^S__ktQZ2y7rGjhr}Gz36~##P(X6KJi_24 z?s&ZWx$b8Uv2}IPlUJMmL1RDD7^qZFcW=+?ZaqJ=+D4AP7G@TNq>ECi=nE-FK~?Rq z9|PInb<-ZhIvf#4UhTu_(iP|76^K$@9X%bY z^U%R(?WKjBO@LaLs+w`KFk2r)so{hx4Ik;R9bNYEhL?kE7-`_qz+W z4zal7boX=n0_Jb1HbQ4x5W@SSZE_;nHX4hx4W1YsgwACPgyT5#%|HC;=&n7}ukJhf z-ebuxPkj=$AjE(W)noJ5>$YC*+V8D-2v)s5-A~kt^|7B219cU?FSF-9dp|sm$H=%7 z3*ve9#6&7Ow)?ZY5mzi?PyPfd_FqmDVJp#tj?TQeY=v-t|BKj1c93lT$YM>+%~~d9 zO@mGoMf|1VFTGy+OzEa!44-RT%St9<$9c0azN0&Ulu%E{+?g&}b8uk~rk(D=(mAz{zo5wwK z7&Bw4C2B`sfUM%SkTsL(v-K^|1JKQ5OU=Iw_Ze7Ij>p0e$6wr1)yMO=59_k$9bGzy z@y&?soQXaiv)#9d`<%mg-IqCL_klxY{W?DIcw>3FF^9P`8TdgA%(d7^Rt|Gk*%}aQ zL&#ce#5#FQJ!${NdX5n>Pj>{0wPYv67pskWZ?yDA;G7pza{%J(P?Yyz%25W z)p=VmkhgWSR>sKAEd&b4U17!yl)dkK|EjkkcQc>ymyc8WnS7_e(8{&xFX;Hqz5?=B zK>kL4caNRFys65w=Gg+Bh;fcjHD74SPT_vo!22q5u;z`Gc~2Vdd3}Wkxexy7TCCiM zd0<@L#(SmO?>jBo=zrGgsM-btG{e)k%f z!yNKf1e3=wb{_TO0%h^O((_6Iy2Rs4fzYMd&OXg)r?cK%rmwsgd%DukOnCfX;ZOU? zP_`LuJ?+{xkeH08P$#3~(Qt~s5Fd#ro{t9;$}QqT77vc&K8r=Nb3|0RxAh8#rXw zcogy^qYRHIk{uj;rVk(SgZSR2`3o2ct=< z84JhabZ?THFt@e9|8c#UMa@#__-E3zGULK$Hfek%ON~ z-T`&A#Hp=U*#)@z0^54?n!P;r6ND{_yMPU++!4bz^9L z%`dK88SxzIUAuhp$0xt~(tB@w_la-seC=-g8{R%~ABr@>f-v( zzpOU?>SwX3x*b1x^KSkByZQAa7x!Pj&~mZH{OO+(wLKq1F1>xEv+3vUM@-LKnfC2t F^mk*a{mK9U literal 0 HcmV?d00001 diff --git a/lab/vtsh/bin/cpu_linreg.c b/lab/vtsh/bin/cpu_linreg.c new file mode 100644 index 0000000..2689839 --- /dev/null +++ b/lab/vtsh/bin/cpu_linreg.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +#define XMIN 0.0 +#define XMAX 100.0 +#define A_TRUE 2.0 +#define B_TRUE 3.0 +#define NOISE_SIGMA 0.5 + +double rand01() { + return (double)rand() / (double)RAND_MAX; +} + +void run_linreg(long long n) { + double mean_x = 0.0, mean_y = 0.0; + double m2x = 0.0, cxy = 0.0; + long long k = 0; + + for (long long i = 0; i < n; i++) { + double x = XMIN + rand01() * (XMAX - XMIN); + double noise = (rand01() - 0.5) * 2 * NOISE_SIGMA; + double y = A_TRUE * x + B_TRUE + noise; + + k++; + double dx = x - mean_x; + double dy = y - mean_y; + mean_x += dx / k; + mean_y += dy / k; + m2x += dx * (x - mean_x); + cxy += dx * (y - mean_y); + } + + double var_x = m2x / n; + double cov_xy = cxy / n; + + double a = cov_xy / var_x; + double b = mean_y - a * mean_x; + + printf("a = %.4f, b = %.4f\n", a, b); +} + +int main(int argc, char *argv[]) { + long long count = 10000000; + int repeat = 3; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--count") == 0 && i + 1 < argc) { + count = atoll(argv[++i]); + } else if (strcmp(argv[i], "--repeat") == 0 && i + 1 < argc) { + repeat = atoi(argv[++i]); + } else { + printf("Unknown option: %s\n", argv[i]); + return 1; + } + } + + srand(7); + + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + + for (int r = 1; r <= repeat; r++) { + run_linreg(count); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + double total_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; + printf("Total time = %.3f s\n", total_time); + + return 0; +} diff --git a/lab/vtsh/bin/ema_join.h b/lab/vtsh/bin/ema_join.h new file mode 100644 index 0000000..eba0eb7 --- /dev/null +++ b/lab/vtsh/bin/ema_join.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +typedef struct { + long long id; + char value[9]; +} Row; + +typedef struct { + long long id; + char left[9]; + char right[9]; +} JoinedRow; + +Row* load_table(const char* path, size_t* out_count); +int save_result(const char* path, const JoinedRow* rows, size_t count); +JoinedRow* nested_loop_join(const Row* left,size_t left_count,const Row* right,size_t right_count,size_t* out_count); +double seconds_between(const struct timespec* start,const struct timespec* end); diff --git a/lab/vtsh/bin/ema_join_algo.c b/lab/vtsh/bin/ema_join_algo.c new file mode 100644 index 0000000..6aaa03f --- /dev/null +++ b/lab/vtsh/bin/ema_join_algo.c @@ -0,0 +1,49 @@ +#include "ema_join.h" + +#include +#include +#include + +JoinedRow* nested_loop_join(const Row* left,size_t left_count,const Row* right,size_t right_count,size_t* out_count) { + JoinedRow* result = NULL; + size_t capacity = 0; + size_t size = 0; + + for (size_t i = 0; i < left_count; ++i) { + for (size_t j = 0; j < right_count; ++j) { + if (left[i].id == right[j].id) { + if (size == capacity) { + size_t new_capacity = (capacity == 0) ? 16 : (capacity * 2); + JoinedRow* tmp = realloc(result, new_capacity * sizeof(JoinedRow)); + if (tmp == NULL) { + fprintf(stderr, "Не хватает памяти для результата\n"); + free(result); + return NULL; + } + result = tmp; + capacity = new_capacity; + } + + result[size].id = left[i].id; + strncpy(result[size].left, left[i].value, sizeof(result[size].left) - 1); + result[size].left[sizeof(result[size].left) - 1] = '\0'; + strncpy(result[size].right, right[j].value, sizeof(result[size].right) - 1); + result[size].right[sizeof(result[size].right) - 1] = '\0'; + size++; + } + } + } + + *out_count = size; + return result; +} + +double seconds_between(const struct timespec* start, const struct timespec* end) { + time_t sec = end->tv_sec - start->tv_sec; + long nsec = end->tv_nsec - start->tv_nsec; + if (nsec < 0) { + sec -= 1; + nsec += 1000000000L; + } + return (double)sec + (double)nsec / 1e9; +} diff --git a/lab/vtsh/bin/ema_join_io.c b/lab/vtsh/bin/ema_join_io.c new file mode 100644 index 0000000..a6279d8 --- /dev/null +++ b/lab/vtsh/bin/ema_join_io.c @@ -0,0 +1,62 @@ +#include "ema_join.h" + +#include +#include +#include +#include + +Row* load_table(const char* path, size_t* out_count) { + FILE* file = fopen(path, "r"); + if (file == NULL) { + fprintf(stderr, "Не удалось открыть %s: %s\n", path, strerror(errno)); + return NULL; + } + + unsigned long long rows = 0; + if (fscanf(file, "%llu", &rows) != 1) { + fprintf(stderr, "Не удалось прочитать количество строк в %s\n", path); + fclose(file); + return NULL; + } + + Row* data = calloc(rows, sizeof(Row)); + if (data == NULL) { + fprintf(stderr, "Не хватает памяти для чтения %s\n", path); + fclose(file); + return NULL; + } + + for (unsigned long long i = 0; i < rows; ++i) { + long long id = 0; + char word[16] = {0}; + if (fscanf(file, "%lld %15s", &id, word) != 2) { + fprintf(stderr, "Строка %llu в %s некорректна\n", i + 1, path); + free(data); + fclose(file); + return NULL; + } + data[i].id = id; + strncpy(data[i].value, word, sizeof(data[i].value) - 1); + data[i].value[sizeof(data[i].value) - 1] = '\0'; + } + + fclose(file); + *out_count = (size_t)rows; + return data; +} + +int save_result(const char* path, const JoinedRow* rows, size_t count) { + FILE* file = fopen(path, "w"); + if (file == NULL) { + fprintf(stderr, "Не удалось открыть %s для записи: %s\n", path, strerror(errno)); + return -1; + } + + fprintf(file, "%zu\n", count); + for (size_t i = 0; i < count; ++i) { + fprintf(file, "%lld %s %s\n", rows[i].id, rows[i].left, rows[i].right); + } + + fclose(file); + return 0; +} diff --git a/lab/vtsh/bin/ema_join_nl.c b/lab/vtsh/bin/ema_join_nl.c new file mode 100644 index 0000000..0ac9c9b --- /dev/null +++ b/lab/vtsh/bin/ema_join_nl.c @@ -0,0 +1,84 @@ +#include "ema_join.h" + +#include +#include +#include + +static void usage(const char* prog) { + fprintf(stderr,"Использование: %s --left <файл> --right <файл> --out <файл> [--repeat N]\n",prog); +} + +int main(int argc, char* argv[]) { + const char* left_path = NULL; + const char* right_path = NULL; + const char* out_path = NULL; + int repeat = 1; + + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--left") == 0 && i + 1 < argc) { + left_path = argv[++i]; + } else if (strcmp(argv[i], "--right") == 0 && i + 1 < argc) { + right_path = argv[++i]; + } else if (strcmp(argv[i], "--out") == 0 && i + 1 < argc) { + out_path = argv[++i]; + } else if (strcmp(argv[i], "--repeat") == 0 && i + 1 < argc) { + repeat = atoi(argv[++i]); + if (repeat <= 0) { + fprintf(stderr, "--repeat должен быть больше нуля\n"); + return 1; + } + } else { + usage(argv[0]); + return 1; + } + } + + if (left_path == NULL || right_path == NULL || out_path == NULL) { + usage(argv[0]); + return 1; + } + + size_t left_count = 0; + size_t right_count = 0; + Row* left = load_table(left_path, &left_count); + if (left == NULL) + return 1; + Row* right = load_table(right_path, &right_count); + if (right == NULL) { + free(left); + return 1; + } + + JoinedRow* result = NULL; + size_t result_count = 0; + + for (int i = 1; i <= repeat; ++i) { + free(result); + result = NULL; + result_count = 0; + + struct timespec start = {0}, end = {0}; + clock_gettime(CLOCK_MONOTONIC, &start); + result = nested_loop_join(left, left_count, right, right_count, &result_count); + clock_gettime(CLOCK_MONOTONIC, &end); + + if (result == NULL) { + free(left); + free(right); + return 1; + } + + printf("Итерация %d: совпадений=%zu время=%.6f с\n",i,result_count,seconds_between(&start, &end)); + } + + int rc = save_result(out_path, result, result_count); + free(result); + free(left); + free(right); + + if (rc != 0) + return 1; + + printf("Результат записан в %s\n", out_path); + return 0; +} diff --git a/lab/vtsh/bin/io_load.c b/lab/vtsh/bin/io_load.c new file mode 100644 index 0000000..637807e --- /dev/null +++ b/lab/vtsh/bin/io_load.c @@ -0,0 +1,16 @@ +#include "io_load.h" + +#include + +int main(int argc, char* argv[]) { + options_t opts; + if (parse_args(argc, argv, &opts) != 0) { + print_usage(argv[0]); + return 1; + } + + if (run_io_workload(&opts) != 0) + return 1; + + return 0; +} diff --git a/lab/vtsh/bin/io_load.h b/lab/vtsh/bin/io_load.h new file mode 100644 index 0000000..537690a --- /dev/null +++ b/lab/vtsh/bin/io_load.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +typedef enum { + MODE_READ, + MODE_WRITE +} io_mode_t; + +typedef enum { + ORDER_SEQUENCE, + ORDER_RANDOM +} io_order_t; + +typedef struct { + io_mode_t mode; + size_t block_size; + size_t block_count; + const char* path; + int repeat; + bool use_direct; + io_order_t order; + bool range_set; + off_t range_start; + off_t range_end; +} options_t; + +void print_usage(const char* prog); +int parse_args(int argc, char* argv[], options_t* opts); +int run_io_workload(const options_t* opts); diff --git a/lab/vtsh/bin/io_load_args.c b/lab/vtsh/bin/io_load_args.c new file mode 100644 index 0000000..17ce494 --- /dev/null +++ b/lab/vtsh/bin/io_load_args.c @@ -0,0 +1,125 @@ +#include "io_load.h" + +#include +#include +#include +#include + +static bool parse_range(const char* text, off_t* start, off_t* end, bool* range_set) { + const char* dash = strchr(text, '-'); + if (dash == NULL) + return false; + + char left[32]; + char right[32]; + size_t left_len = (size_t)(dash - text); + size_t right_len = strlen(dash + 1); + if (left_len == 0 || right_len == 0 || + left_len >= sizeof(left) || right_len >= sizeof(right)) + return false; + + memcpy(left, text, left_len); + left[left_len] = '\0'; + memcpy(right, dash + 1, right_len + 1); + + errno = 0; + long long start_val = strtoll(left, NULL, 10); + long long end_val = strtoll(right, NULL, 10); + if (errno != 0 || start_val < 0 || end_val < 0) + return false; + + *start = (off_t)start_val; + *end = (off_t)end_val; + *range_set = !(start_val == 0 && end_val == 0); + return true; +} + +void print_usage(const char* prog) { + fprintf(stderr, + "Usage: %s --rw --block_size --block_count \n" + " --file [--range start-end] [--direct on|off]\n" + " [--type sequence|random] [--repeat N]\n", + prog); +} + +int parse_args(int argc, char* argv[], options_t* opts) { + opts->mode = MODE_READ; + opts->block_size = 4096; + opts->block_count = 1024; + opts->path = NULL; + opts->repeat = 1; + opts->use_direct = false; + opts->order = ORDER_SEQUENCE; + opts->range_set = false; + opts->range_start = 0; + opts->range_end = 0; + + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--rw") == 0 && i + 1 < argc) { + const char* mode = argv[++i]; + if (strcmp(mode, "read") == 0) { + opts->mode = MODE_READ; + } else if (strcmp(mode, "write") == 0) { + opts->mode = MODE_WRITE; + } else { + fprintf(stderr, "Unknown --rw value: %s\n", mode); + return -1; + } + } else if (strcmp(argv[i], "--block_size") == 0 && i + 1 < argc) { + opts->block_size = (size_t)strtoull(argv[++i], NULL, 10); + if (opts->block_size == 0) { + fprintf(stderr, "block_size must be > 0\n"); + return -1; + } + } else if (strcmp(argv[i], "--block_count") == 0 && i + 1 < argc) { + opts->block_count = (size_t)strtoull(argv[++i], NULL, 10); + if (opts->block_count == 0) { + fprintf(stderr, "block_count must be > 0\n"); + return -1; + } + } else if (strcmp(argv[i], "--file") == 0 && i + 1 < argc) { + opts->path = argv[++i]; + } else if (strcmp(argv[i], "--repeat") == 0 && i + 1 < argc) { + opts->repeat = atoi(argv[++i]); + if (opts->repeat <= 0) { + fprintf(stderr, "repeat must be > 0\n"); + return -1; + } + } else if (strcmp(argv[i], "--direct") == 0 && i + 1 < argc) { + const char* val = argv[++i]; + if (strcmp(val, "on") == 0) { + opts->use_direct = true; + } else if (strcmp(val, "off") == 0) { + opts->use_direct = false; + } else { + fprintf(stderr, "--direct accepts on/off\n"); + return -1; + } + } else if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) { + const char* val = argv[++i]; + if (strcmp(val, "sequence") == 0) { + opts->order = ORDER_SEQUENCE; + } else if (strcmp(val, "random") == 0) { + opts->order = ORDER_RANDOM; + } else { + fprintf(stderr, "--type accepts sequence/random\n"); + return -1; + } + } else if (strcmp(argv[i], "--range") == 0 && i + 1 < argc) { + if (!parse_range(argv[++i], &opts->range_start, &opts->range_end, &opts->range_set)) { + fprintf(stderr, "Invalid range format\n"); + return -1; + } + } else { + fprintf(stderr, "Unknown argument: %s\n", argv[i]); + return -1; + } + } + + if (opts->path == NULL) { + fprintf(stderr, "--file is required\n"); + return -1; + } + + return 0; +} diff --git a/lab/vtsh/bin/io_load_runner.c b/lab/vtsh/bin/io_load_runner.c new file mode 100644 index 0000000..9d2a07a --- /dev/null +++ b/lab/vtsh/bin/io_load_runner.c @@ -0,0 +1,176 @@ +#include "io_load.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void* allocate_buffer(size_t size) { + void* buffer = malloc(size); + if (buffer == NULL) + fprintf(stderr, "malloc failed\n"); + return buffer; +} + +static double seconds_between(const struct timespec* start, + const struct timespec* end) { + time_t sec = end->tv_sec - start->tv_sec; + long nsec = end->tv_nsec - start->tv_nsec; + if (nsec < 0) { + sec -= 1; + nsec += 1000000000L; + } + return (double)sec + (double)nsec / 1e9; +} + +static int check_range(const options_t* opts, const struct stat* st) { + off_t range_start = opts->range_start; + off_t range_end = opts->range_end; + + if (!opts->range_set) { + range_start = 0; + if (opts->mode == MODE_READ) { + range_end = st->st_size; + } else { + range_end = range_start + (off_t)(opts->block_size * opts->block_count); + } + } + + if (opts->mode == MODE_READ && range_end > st->st_size) { + fprintf(stderr, "Range exceeds file size for read mode\n"); + return -1; + } + + if (range_end <= range_start) { + fprintf(stderr, "Invalid range\n"); + return -1; + } + + off_t span = range_end - range_start; + if (opts->order == ORDER_SEQUENCE && + span < (off_t)(opts->block_size * opts->block_count)) { + fprintf(stderr, "Range is too small for sequential access\n"); + return -1; + } + + return 0; +} + +static off_t pick_offset(const options_t* opts, off_t range_start, size_t index) { + if (opts->order == ORDER_RANDOM) { + off_t range_bytes = opts->range_end - opts->range_start; + if (range_bytes < (off_t)opts->block_size) + return opts->range_start; + + off_t slots = range_bytes / (off_t)opts->block_size; + if (slots <= 0) + slots = 1; + off_t slot = (off_t)(rand() % (int)slots); + return opts->range_start + slot * (off_t)opts->block_size; + } + + return range_start + (off_t)(index * opts->block_size); +} + +int run_io_workload(const options_t* opts) { + int flags = (opts->mode == MODE_READ) ? O_RDONLY : (O_WRONLY | O_CREAT); + int fd = open(opts->path, flags, 0666); + if (fd < 0) { + fprintf(stderr, "Failed to open %s: %s\n", opts->path, strerror(errno)); + return 1; + } + +#if defined(F_NOCACHE) + if (opts->use_direct && fcntl(fd, F_NOCACHE, 1) != 0) + fprintf(stderr, "fcntl failed: %s\n", strerror(errno)); +#else + if (opts->use_direct) + fprintf(stderr, "Warning: F_NOCACHE not supported on this platform\n"); +#endif + + struct stat st; + if (fstat(fd, &st) != 0) { + fprintf(stderr, "fstat failed: %s\n", strerror(errno)); + close(fd); + return 1; + } + + options_t local_opts = *opts; + if (!local_opts.range_set) { + local_opts.range_start = 0; + if (local_opts.mode == MODE_READ) + local_opts.range_end = st.st_size; + else + local_opts.range_end = local_opts.range_start + (off_t)(local_opts.block_size * local_opts.block_count); + } + + if (check_range(&local_opts, &st) != 0) { + close(fd); + return 1; + } + + void* buffer = allocate_buffer(local_opts.block_size); + if (buffer == NULL) { + close(fd); + return 1; + } + + if (local_opts.mode == MODE_WRITE) { + for (size_t i = 0; i < local_opts.block_size; ++i) + ((unsigned char*)buffer)[i] = (unsigned char)('A' + (i % 26)); + } + + srand(0); + + struct timespec total_start = {0}, total_end = {0}; + clock_gettime(CLOCK_MONOTONIC, &total_start); + + for (int r = 0; r < local_opts.repeat; ++r) { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + + for (size_t i = 0; i < local_opts.block_count; ++i) { + off_t offset = pick_offset(&local_opts, local_opts.range_start, i); + ssize_t done; + if (local_opts.mode == MODE_READ) { + done = pread(fd, buffer, local_opts.block_size, offset); + } else { + done = pwrite(fd, buffer, local_opts.block_size, offset); + } + if (done < 0) { + fprintf(stderr, "I/O error at block %zu: %s\n", i, strerror(errno)); + free(buffer); + close(fd); + return 1; + } + if ((size_t)done != local_opts.block_size) { + fprintf(stderr, "Short transfer at block %zu\n", i); + free(buffer); + close(fd); + return 1; + } + } + + clock_gettime(CLOCK_MONOTONIC, &end); + time_t sec = end.tv_sec - start.tv_sec; + long nsec = end.tv_nsec - start.tv_nsec; + if (nsec < 0) { + sec -= 1; + nsec += 1000000000L; + } + double elapsed = (double)sec + (double)nsec / 1e9; + printf("Iteration %d: blocks=%zu size=%zu bytes time=%.6f s\n", r + 1, local_opts.block_count, local_opts.block_size, elapsed); + } + + clock_gettime(CLOCK_MONOTONIC, &total_end); + printf("Total time: %.6f s\n", seconds_between(&total_start, &total_end)); + + free(buffer); + close(fd); + return 0; +} diff --git a/lab/vtsh/bin/main b/lab/vtsh/bin/main new file mode 100755 index 0000000000000000000000000000000000000000..8ccf6447e03a6d054852bcecdb7ce89ec43b3de9 GIT binary patch literal 34296 zcmeI5e{2-T702J+;rMI=cmB~hfdXeEj1NUXAf-U#YQa#TCEz+p&{oa*d_J42?K^X~ z23!*LC`2Vnl=v#D&?;#|8VQ4l)JC-B`XhA`wdD`0V)`qoqUfxu>bWHmq>vTp5XVcORC=dh$A)fEdQ6 z4ZAiNtvh$zZ>@%I2LW=GT)7uU7G@iO7)DRRu?)BDZy0q|(yjKkMz^8hpH`6Hh_mh6 zc6?^@rft@!h*zs5KA>}&wAYt?%CD?M_n-xjkK1j9W3{bsJxrv-%xvy}3`4&i`N1PZ zdE`})HV7x~kA>%p@Sz&WtM=b}AcOTlGzY-c*1zQlp?^lG%{4-;rvL|LOgH_E>`H7k_Kknz=a@$~M{NA+? z_F3_;1;n%)W5IatA4-|g{^c8&V_dOLt6>u|?*G_fA|LXQturr93n1+8IEpy32Fd1I zruPyro}N0Sot|o?OtH0c4C5X4mFWearWZzzES$`(rb2NyWpk_b0=gS+SQ*N6YIHoe zlvuCJFVzbbly0B!Qx@xVPT6+rS>F`x%b)trygcm6=GU`%jn+)J`P=SvcEVeECR9e% z6X<_pu_x0!v}_W%E~Acm58^|;=dZO81D^b zR-$d%_M^}CAoTG+V~&e3pT&@R$b2e{!dD9)*UuT4gTehys&NM4tAL$t%^vGr;}`?K zhwb1$?E7peL)vJ|_$yi_wyQZISzDno0?M6@fGQT(HPq)8I+`pb3k7yYWeD$zD zW51^vdLDDwj5+Xl#=lFMw@^P{uNNj3@mf^;Jzq= zYpNdX75XzI<(>Rdx@7vM!m)#N@CkveN$`~KTcWI=NxOU8e(fB_gb4Pkq(TrnPQxDd)5hkwFLXL99w0qoB38Z6Ri-RF3mh&x_apEkN~ug#9* zySUW;PT*7DQ#oaQn*BZ5^`Y;}m*bm)Pq8W2vlni&zNsAQz&6})DU>`n~EyDG_y^+#KlEML=INtM*pM5&>;89o?{CXf~Qhwe~&GoE(@qzRlTjzbzY`6A)2h!Mk zrF1@b04c4W@(=<-KnMr{As_^VfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF# z2nYcoAOwVf5D)@FKnMr{As_^VfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF# z2nYco@P9}kh&i`GPC)psbL%Vs6p*a_|5lmr5}!`0tm8BQecEER({O-*hD*e??T}6g zF3#4DLY{@Z0C^E|5%LD)Dun;lKpG*dAUdQSBQOjjWricYMr3cV(Tyu$OD#Qv;bfO( z>cTCu19mYM=aRaG)`;{a(7Y#V^5wGxV>GfKUd!1Hdy0(ifn+Rhc9W5cn)^EkxnL$E z{iw!yY9Ou(D68B|^pdf^JCQ_oARIFXVi>}KWXz0WA_mnn3e2Cp^wYU`3S|rx_ z&U!xzeBV3kd0fi{kGu3I zUHUUFeZ-}I-=$|=`b#eTf=eHB=^W2|W(A*D!Dm(QITd_H1)opBXH)RG6il1Xqu_6$ z7E%Yn9n|Vu;Bzqe3=BU1;y>*NO(}>ly*V-r6&Z#zGXBTD10&TN8!%D>;Yc*a^Su7X z>`_Em21SISN_DUythI;8gVpe;5dR`Pdu%_J=4eOIqn5=seNa}m*7j-&-q^{L+1jIb zQ+9mE72_YDe(uCy8joI@cj@a(9$OWici&yVdj2bCU)YoQF*lPj -#include +#include +#include +#include +#include +#include +#include + +#define MAX_INPUT 1024 +#define MAX_ARGS 64 + +static char* skip_spaces(char* s) { + while (*s == ' ' || *s == '\t') + s++; + return s; +} + +int run_command(char *cmd) { + char *args[MAX_ARGS]; + pid_t pid; + int status; + + int argc = 0; + char *token = strtok(cmd, " \t"); + while (token != NULL && argc < MAX_ARGS - 1) { + args[argc++] = token; + token = strtok(NULL, " \t"); + } + args[argc] = NULL; + + if (argc == 0) + return 0; + + if (strcmp(args[0], "exit") == 0) + exit(0); + + struct timespec start = {0}, end = {0}; + clock_gettime(CLOCK_MONOTONIC, &start); + + pid = vfork(); + if (pid < 0) + _exit(1); + + if (pid == 0) { + execvp(args[0], args); + const char msg[] = "Command not found\n"; + write(STDOUT_FILENO, msg, sizeof(msg) - 1); + _exit(127); + } + + if (waitpid(pid, &status, 0) < 0) + return 1; + + clock_gettime(CLOCK_MONOTONIC, &end); + time_t sec = end.tv_sec - start.tv_sec; + long nsec = end.tv_nsec - start.tv_nsec; + if (nsec < 0) { + sec -= 1; + nsec += 1000000000L; + } + double time_spent = (double)sec + (double)nsec / 1e9; + fprintf(stderr, "time=%.6f\n", time_spent); + + if (WIFEXITED(status)) + return WEXITSTATUS(status); + if (WIFSIGNALED(status)) + return 128 + WTERMSIG(status); + return 1; +} int main() { - printf("%s", vtsh_prompt()); - printf("Hello, world!\n"); + char input[MAX_INPUT]; + setvbuf(stdin, NULL, _IONBF, 0); + + while (1) { + if (fgets(input, sizeof(input), stdin) == NULL) + break; + + input[strcspn(input, "\n")] = '\0'; + char *cmd = skip_spaces(input); + if (*cmd == '\0') + continue; + + int code = 0; + + while (cmd != NULL && *cmd != '\0') { + char *and_ptr = strstr(cmd, "&&"); + + if (and_ptr != NULL) { + *and_ptr = '\0'; + } + + char *segment = skip_spaces(cmd); + if (*segment == '\0') { + fprintf(stderr, "syntax error: empty command\n"); + break; + } + + code = run_command(segment); + + if (code != 0) + break; + + if (and_ptr == NULL) + break; + + cmd = skip_spaces(and_ptr + 2); + if (*cmd == '\0') { + fprintf(stderr, "syntax error: trailing &&\n"); + break; + } + } + } + + return 0; } diff --git a/lab/vtsh/joined.tbl b/lab/vtsh/joined.tbl new file mode 100644 index 0000000..d94eddb --- /dev/null +++ b/lab/vtsh/joined.tbl @@ -0,0 +1,4 @@ +3 +1 alpha___ one_____ +2 bravo___ two_____ +3 charlie_ three___ diff --git a/lab/vtsh/left.tbl b/lab/vtsh/left.tbl new file mode 100644 index 0000000..27644cf --- /dev/null +++ b/lab/vtsh/left.tbl @@ -0,0 +1,4 @@ +3 +1 alpha___ +2 bravo___ +3 charlie_ diff --git a/lab/vtsh/out.bin b/lab/vtsh/out.bin new file mode 100644 index 0000000000000000000000000000000000000000..fecb0927bfbecddcdbd217599f4993dd757650ed GIT binary patch literal 524288 zcmeI*hri8r90%ZY&pr2^d+t4VoO{;YNJeWB-qy`O7KBdvAjZbTGdebwSoq5*T=QMB8^4wOf+njg) z1s7h__Toz}ZP&g-$ICi(?$Y)0ZdY{gab?e5S6zKg?>>F|^&fEUz(IqD48899VZ(2@ z@um?s-*W41x8HH+T_Z=09y4~__`4@eoHTjL)M?Xa%)IB`S@+GJGk4zn`xiX0aM6Pg zEnf2Q(nlU$w*0XbkFR{<$)}!P^~~xuYuBycuyNC~&prRb<}F)a-1gGTuWaA3bJwf8 zUwi$HH}~v)>+N^meeeB!`#(7F;YS~T^66)vAN=CWufG1~+wZ>r;m4nT{^i%-e*fdo zLx=zR`=5W09IX!c{Jwv`fB%2aKhJ;fKkt9%ALl>kU*~`KANN1^U-y6Y5A`4QFZDn5 zPxW8*Z}oru5B(qgFa1CLPyJv0Z~cGs59UA2znK3q|78Bl{G0hd^N;2~&A*!eHUDh> z+x)xvfBO&iKkUEQ|FQpM|I7ZH{XhGU_CM{v+W)oxZ2#N-yZwLp2l5}}U&#NEetF8^Kr zz5IXv0sn!2!T;c&@L%{h{2%@i|A~La|KgwV-}ra@KmH;Ak$=hmk z&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu z@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj z|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc z`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf3FT?1T#bYcm6y7 zo&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR z-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4 z|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2> z^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZE zJO7>k&VT2>^WXXJ{CEC4|DFHNf9Jnv1T#Zf+5C6@JO7>k&VT2>^WXXJ{CEC4|DFHN zf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ z{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k z&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu z@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj z|IUBszh{QBvcoz2cm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2> z^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZE zJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBs zzw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9 z{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JnvWruSjx%_wjJO7>k z&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu z@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj z|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc z`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7 zo&U~%=fCsc`S1L9{yYDj|IUBszlU=oxp`6kJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR z-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2>^WXXJ{CEC4 z|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZEJO7>k&VT2> z^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBszw_Vu@BDZE zJO7>k&VT2>^WXXJ{CEC4|DFHNf9JpR-}&$Scm6y7o&U~%=fCsc`S1L9{yYDj|IUBs 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 literal 0 HcmV?d00001 diff --git a/lab/vtsh/right.tbl b/lab/vtsh/right.tbl new file mode 100644 index 0000000..d2895e2 --- /dev/null +++ b/lab/vtsh/right.tbl @@ -0,0 +1,5 @@ +4 +1 one_____ +3 three___ +4 four____ +2 two_____ diff --git a/lab/vtsh/test/shell b/lab/vtsh/test/shell new file mode 120000 index 0000000..86ff261 --- /dev/null +++ b/lab/vtsh/test/shell @@ -0,0 +1 @@ +../build/bin/vtsh \ No newline at end of file diff --git a/lab/vtsh/test/test_redirection.py b/lab/vtsh/test/test_redirection.py index cb14495..1759e4b 100644 --- a/lab/vtsh/test/test_redirection.py +++ b/lab/vtsh/test/test_redirection.py @@ -4,7 +4,7 @@ REQUIRED_REDIRECTION_FUNCTIONALITY = False -@unittest.skipIf(not REQUIRED_REDIRECTION_FUNCTIONALITY, +@unittest.skipIf(not REQUIRED_REDIRECTION_FUNCTIONALITY, ("Redirection functionality is not required in the task. " "This functionality is for an additional task.")) class TestShellRedirection(BaseShellTest):