From e6f77b7ea3e38c9853bee60b275f3f89d252a5b3 Mon Sep 17 00:00:00 2001 From: We-unite <3205135446@qq.com> Date: Thu, 23 Jan 2025 10:41:10 +0800 Subject: Initial commit, makee it usable on newest linux --- files/memtest | Bin 0 -> 13628 bytes files/process.c | 58 ++++++++ files/stat_log.py | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ files/testlab2.c | 195 +++++++++++++++++++++++++++ files/testlab2.sh | 49 +++++++ 5 files changed, 696 insertions(+) create mode 100644 files/memtest create mode 100644 files/process.c create mode 100755 files/stat_log.py create mode 100644 files/testlab2.c create mode 100755 files/testlab2.sh (limited to 'files') diff --git a/files/memtest b/files/memtest new file mode 100644 index 0000000..8c56b25 Binary files /dev/null and b/files/memtest differ diff --git a/files/process.c b/files/process.c new file mode 100644 index 0000000..46eb0b0 --- /dev/null +++ b/files/process.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +#define HZ 100 + +void cpuio_bound(int last, int cpu_time, int io_time); + +int main(int argc, char * argv[]) +{ + return 0; +} + +/* + * 此函数按照参数占用CPU和I/O时间 + * last: 函数实际占用CPU和I/O的总时间,不含在就绪队列中的时间,>=0是必须的 + * cpu_time: 一次连续占用CPU的时间,>=0是必须的 + * io_time: 一次I/O消耗的时间,>=0是必须的 + * 如果last > cpu_time + io_time,则往复多次占用CPU和I/O + * 所有时间的单位为秒 + */ +void cpuio_bound(int last, int cpu_time, int io_time) +{ + struct tms start_time, current_time; + clock_t utime, stime; + int sleep_time; + + while (last > 0) + { + /* CPU Burst */ + times(&start_time); + /* 其实只有t.tms_utime才是真正的CPU时间。但我们是在模拟一个 + * 只在用户状态运行的CPU大户,就像“for(;;);”。所以把t.tms_stime + * 加上很合理。*/ + do + { + times(¤t_time); + utime = current_time.tms_utime - start_time.tms_utime; + stime = current_time.tms_stime - start_time.tms_stime; + } while ( ( (utime + stime) / HZ ) < cpu_time ); + last -= cpu_time; + + if (last <= 0 ) + break; + + /* IO Burst */ + /* 用sleep(1)模拟1秒钟的I/O操作 */ + sleep_time=0; + while (sleep_time < io_time) + { + sleep(1); + sleep_time++; + } + last -= sleep_time; + } +} + diff --git a/files/stat_log.py b/files/stat_log.py new file mode 100755 index 0000000..2dbe3ee --- /dev/null +++ b/files/stat_log.py @@ -0,0 +1,394 @@ +#!/usr/bin/python +import sys +import copy + +P_NULL = 0 +P_NEW = 1 +P_READY = 2 +P_RUNNING = 4 +P_WAITING = 8 +P_EXIT = 16 + +S_STATE = 0 +S_TIME = 1 + +HZ = 100 + +graph_title = r""" +-----===< COOL GRAPHIC OF SCHEDULER >===----- + + [Symbol] [Meaning] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + number PID or tick + "-" New or Exit + "#" Running + "|" Ready + ":" Waiting + / Running with + "+" -| Ready + \and/or Waiting + +-----===< !!!!!!!!!!!!!!!!!!!!!!!!! >===----- +""" + +usage = """ +Usage: +%s /path/to/process.log [PID1] [PID2] ... [-x PID1 [PID2] ... ] [-m] [-g] + +Example: +# Include process 6, 7, 8 and 9 in statistics only. (Unit: tick) +%s /path/to/process.log 6 7 8 9 + +# Exclude process 0 and 1 from statistics. (Unit: tick) +%s /path/to/process.log -x 0 1 + +# Include process 6 and 7 only and print a COOL "graphic"! (Unit: millisecond) +%s /path/to/process.log 6 7 -m -g + +# Include all processes and print a COOL "graphic"! (Unit: tick) +%s /path/to/process.log -g +""" + +class MyError(Exception): + pass + +class DuplicateNew(MyError): + def __init__(self, pid): + args = "More than one 'N' for process %d." % pid + MyError.__init__(self, args) + +class UnknownState(MyError): + def __init__(self, state): + args = "Unknown state '%s' found." % state + MyError.__init__(self, args) + +class BadTime(MyError): + def __init__(self, time): + args = "The time '%d' is bad. It should >= previous line's time." % time + MyError.__init__(self, args) + +class TaskHasExited(MyError): + def __init__(self, state): + args = "The process has exited. Why it enter '%s' state again?" % state + MyError.__init__(self, args) + +class BadFormat(MyError): + def __init__(self): + args = "Bad log format" + MyError.__init__(self, args) + +class RepeatState(MyError): + def __init__(self, pid): + args = "Previous state of process %d is identical with this line." % (pid) + MyError.__init__(self, args) + +class SameLine(MyError): + def __init__(self): + args = "It is a clone of previous line." + MyError.__init__(self, args) + +class NoNew(MyError): + def __init__(self, pid, state): + args = "The first state of process %d is '%s'. Why not 'N'?" % (pid, state) + MyError.__init__(self, args) + +class statistics: + def __init__(self, pool, include, exclude): + if include: + self.pool = process_pool() + for process in pool: + if process.getpid() in include: + self.pool.add(process) + else: + self.pool = copy.copy(pool) + + if exclude: + for pid in exclude: + if self.pool.get_process(pid): + self.pool.remove(pid) + + def list_pid(self): + l = [] + for process in self.pool: + l.append(process.getpid()) + return l + + def average_turnaround(self): + if len(self.pool) == 0: + return 0 + sum = 0 + for process in self.pool: + sum += process.turnaround_time() + return float(sum) / len(self.pool) + + def average_waiting(self): + if len(self.pool) == 0: + return 0 + sum = 0 + for process in self.pool: + sum += process.waiting_time() + return float(sum) / len(self.pool) + + def begin_time(self): + begin = 0xEFFFFF + for p in self.pool: + if p.begin_time() < begin: + begin = p.begin_time() + return begin + + def end_time(self): + end = 0 + for p in self.pool: + if p.end_time() > end: + end = p.end_time() + return end + + def throughput(self): + return len(self.pool) * HZ / float(self.end_time() - self.begin_time()) + + def print_graphic(self): + begin = self.begin_time() + end = self.end_time() + + print graph_title + + for i in range(begin, end+1): + line = "%5d " % i + for p in self.pool: + state = p.get_state(i) + if state & P_NEW: + line += "-" + elif state == P_READY or state == P_READY | P_WAITING: + line += "|" + elif state == P_RUNNING: + line += "#" + elif state == P_WAITING: + line += ":" + elif state & P_EXIT: + line += "-" + elif state == P_NULL: + line += " " + elif state & P_RUNNING: + line += "+" + else: + assert False + if p.get_state(i-1) != state and state != P_NULL: + line += "%-3d" % p.getpid() + else: + line += " " + print line + +class process_pool: + def __init__(self): + self.list = [] + + def get_process(self, pid): + for process in self.list: + if process.getpid() == pid: + return process + return None + + def remove(self, pid): + for process in self.list: + if process.getpid() == pid: + self.list.remove(process) + + def new(self, pid, time): + p = self.get_process(pid) + if p: + if pid != 0: + raise DuplicateNew(pid) + else: + p.states=[(P_NEW, time)] + else: + p = process(pid, time) + self.list.append(p) + return p + + def add(self, p): + self.list.append(p) + + def __len__(self): + return len(self.list) + + def __iter__(self): + return iter(self.list) + +class process: + def __init__(self, pid, time): + self.pid = pid + self.states = [(P_NEW, time)] + + def getpid(self): + return self.pid + + def change_state(self, state, time): + last_state, last_time = self.states[-1] + if state == P_NEW: + raise DuplicateNew(pid) + if time < last_time: + raise BadTime(time) + if last_state == P_EXIT: + raise TaskHasExited(state) + if last_state == state and self.pid != 0: # task 0 can have duplicate state + raise RepeatState(self.pid) + + self.states.append((state, time)) + + def get_state(self, time): + rval = P_NULL + combo = P_NULL + if self.begin_time() <= time <= self.end_time(): + for state, s_time in self.states: + if s_time < time: + rval = state + elif s_time == time: + combo |= state + else: + break + if combo: + rval = combo + return rval + + def turnaround_time(self): + return self.states[-1][S_TIME] - self.states[0][S_TIME] + + def waiting_time(self): + return self.state_last_time(P_READY) + + def cpu_time(self): + return self.state_last_time(P_RUNNING) + + def io_time(self): + return self.state_last_time(P_WAITING) + + def state_last_time(self, state): + time = 0 + state_begin = 0 + for s,t in self.states: + if s == state: + state_begin = t + elif state_begin != 0: + assert state_begin <= t + time += t - state_begin + state_begin = 0 + return time + + + def begin_time(self): + return self.states[0][S_TIME] + + def end_time(self): + return self.states[-1][S_TIME] + +# Enter point +if len(sys.argv) < 2: + print usage.replace("%s", sys.argv[0]) + sys.exit(0) + +# parse arguments +include = [] +exclude = [] +unit_ms = False +graphic = False +ex_mark = False + +try: + for arg in sys.argv[2:]: + if arg == '-m': + unit_ms = True + continue + if arg == '-g': + graphic = True + continue + if not ex_mark: + if arg == '-x': + ex_mark = True + else: + include.append(int(arg)) + else: + exclude.append(int(arg)) +except ValueError: + print "Bad argument '%s'" % arg + sys.exit(-1) + +# parse log file and construct processes +processes = process_pool() + +f = open(sys.argv[1], "r") + +# Patch process 0's New & Run state +processes.new(0, 40).change_state(P_RUNNING, 40) + +try: + prev_time = 0 + prev_line = "" + for lineno, line in enumerate(f): + + if line == prev_line: + raise SameLine + prev_line = line + + fields = line.split("\t") + if len(fields) != 3: + raise BadFormat + + pid = int(fields[0]) + s = fields[1].upper() + + time = int(fields[2]) + if time < prev_time: + raise BadTime(time) + prev_time = time + + p = processes.get_process(pid) + + state = P_NULL + if s == 'N': + processes.new(pid, time) + elif s == 'J': + state = P_READY + elif s == 'R': + state = P_RUNNING + elif s == 'W': + state = P_WAITING + elif s == 'E': + state = P_EXIT + else: + raise UnknownState(s) + if state != P_NULL: + if not p: + raise NoNew(pid, s) + p.change_state(state, time) +except MyError, err: + print "Error at line %d: %s" % (lineno+1, err) + sys.exit(0) + +# Stats +stats = statistics(processes, include, exclude) +att = stats.average_turnaround() +awt = stats.average_waiting() +if unit_ms: + unit = "ms" + att *= 1000/HZ + awt *= 1000/HZ +else: + unit = "tick" +print "(Unit: %s)" % unit +print "Process Turnaround Waiting CPU Burst I/O Burst" +for pid in stats.list_pid(): + p = processes.get_process(pid) + tt = p.turnaround_time() + wt = p.waiting_time() + cpu = p.cpu_time() + io = p.io_time() + + if unit_ms: + print "%7d %10d %7d %9d %9d" % (pid, tt*1000/HZ, wt*1000/HZ, cpu*1000/HZ, io*1000/HZ) + else: + print "%7d %10d %7d %9d %9d" % (pid, tt, wt, cpu, io) +print "Average: %10.2f %7.2f" % (att, awt) +print "Throughout: %.2f/s" % (stats.throughput()) + +if graphic: + stats.print_graphic() diff --git a/files/testlab2.c b/files/testlab2.c new file mode 100644 index 0000000..bd97b76 --- /dev/null +++ b/files/testlab2.c @@ -0,0 +1,195 @@ +/* + * Compile: "gcc testlab2.c" + * Run: "./a.out" + */ + +#include +#include +#include +#include +#include +#define __LIBRARY__ +#include + +_syscall2(int, whoami,char*,name,unsigned int,size); +_syscall1(int, iam, const char*, name); + +#define MAX_NAME_LEN 23 +#define NAMEBUF_SIZE (MAX_NAME_LEN + 1) +/* truncate a long name to SHORT_NAME_LEN for display */ +#define SHORT_NAME_LEN (MAX_NAME_LEN + 2) + +/* name score */ +#define TEST_CASE { \ + {"x", 10, 1, NAMEBUF_SIZE, 1},\ + {"sunner", 10, 6, NAMEBUF_SIZE, 6},\ + {"Twenty-three characters", 5, 23, NAMEBUF_SIZE, 23},\ + {"123456789009876543211234", 5, -1, 0, -1},\ + {"abcdefghijklmnopqrstuvwxyz", 5, -1, 0, -1},\ + {"Linus Torvalds", 5, 14, NAMEBUF_SIZE, 14},\ + {"", 5, 0, NAMEBUF_SIZE, 0},\ + {"whoami(0xbalabala, 10)", 5, 22, 10, -1},\ + {NULL, 0, 0, 0, 0} /* End of cases */ \ +} +/*改动一:增加size,和rval2*/ + +int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2); +void print_message(const char* msgfmt, const char* name); + +struct test_case +{ + char *name; + int score; + int rval1; /* return value of iam() */ + /*改动2:增加size,和rval2定义*/ + int size; /*Patch for whoami,2009.11.2*/ + int rval2; /* return value of whoami() */ +}; + +int main(void) +{ + struct test_case cases[] = TEST_CASE; + + int total_score=0, i=0; + + while (cases[i].score != 0) + { + int score; + + printf("Test case %d:", i+1); + + /*改动3:增加size,和rval2的参数阿*/ + score = test( cases[i].name, + cases[i].score, + cases[i].rval1, + cases[i].size, + cases[i].rval2 ); + + total_score += score; + i++; + } + + printf("Final result: %d%%\n", total_score); + return 0; + +} + /*改动4:增加size,和rval2的声明*/ +int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2) +{ + int rval; + int len; + char * gotname; + int score=-1; + + assert(name != NULL); + + print_message("name = \"%s\", length = %d...", name); + + /*Test iam()*/ + len = strlen(name); + rval = iam(name); + /* printf("Return value = %d\n", rval);*/ + +/*改动5:增加的expected_rval1*/ + if (rval == expected_rval1) + { + if (rval == -1 && errno == EINVAL) /*The system call can detect bad name*/ + { + /* print_message("Long name, %s(%d), detected.\n", name);*/ + printf("PASS\n"); + score = max_score; + } + else if (rval == -1 && errno != EINVAL) + { + printf("\nERROR iam(): Bad errno %d. It should be %d(EINVAL).\n", errno, EINVAL); + score = 0; + } + /* iam() is good. Test whoami() next. */ + } + else + { + printf("\nERROR iam(): Return value is %d. It should be %d.\n", rval, expected_rval1); + score = 0; + } + + if (score != -1) + return score; + + /*Test whoami()*/ + gotname = (char*)malloc(len+1); + if (gotname == NULL) + exit(-1); + + memset(gotname, 0, len+1); + + /* printf("Get: buffer length = %d.\n", len+1); */ + + rval = whoami(gotname, size); + /* printf("Return value = %d\n", rval); */ + +/*改动6:增加的expected_rval2*/ +/*改动++:比较多 ,但还是顺序的改改*/ + + if(rval == expected_rval2) + { + if(rval == -1) + { + printf("PASS\n"); + score = max_score; + } + else + { + if (strcmp(gotname, name) == 0) + { + /* print_message("Great! We got %s(%d) finally!\n", gotname); */ + printf("PASS\n"); + score = max_score; + } + else + { + print_message("\nERROR whoami(): we got %s(%d). ", gotname); + print_message("It should be %s(%d).\n", name); + score = 0; + } + } + } + else if (rval == -1) + { + printf("\nERROR whoami(): Return value is -1 and errno is %d. Why?\n", errno); + score = 0; + } + else + { + printf("\nERROR whoami(): Return value should be %d, not %d.\n", expected_rval2, rval); + score = 0; + } + + free(gotname); + assert(score != -1); + + return score; +} + +void print_message(const char* msgfmt, const char* name) +{ + char short_name[SHORT_NAME_LEN + 4] = {0}; + int len; + + len = strlen(name); + + if (len == 0) + { + strcpy(short_name, "NULL"); + } + else if (len <= SHORT_NAME_LEN) + { + strcpy(short_name, name); + } + else + { + memset(short_name, '.', SHORT_NAME_LEN+3); + memcpy(short_name, name, SHORT_NAME_LEN); + } + + printf(msgfmt, short_name, len); +} diff --git a/files/testlab2.sh b/files/testlab2.sh new file mode 100755 index 0000000..7f79876 --- /dev/null +++ b/files/testlab2.sh @@ -0,0 +1,49 @@ +#/bin/sh + +string1="Sunner" +string2="Richard Stallman" +string3="This is a very very long string!" + +score1=10 +score2=10 +score3=10 + +expected1="Sunner" +expected2="Richard Stallman" +expected3="Richard Stallman" + +echo Testing string:$string1 +./iam "$string1" +result=`./whoami` +if [ "$result" = "$expected1" ]; then + echo PASS. +else + score1=0 + echo FAILED. +fi +score=$score1 + +echo Testing string:$string2 +./iam "$string2" +result=`./whoami` +if [ "$result" = "$expected2" ]; then + echo PASS. +else + score2=0 + echo FAILED. +fi +score=$score+$score2 + +echo Testing string:$string3 +./iam "$string3" +result=`./whoami` +if [ "$result" = "$expected3" ]; then + echo PASS. +else + score3=0 + echo FAILED. +fi +score=$score+$score3 + +let "totalscore=$score" +echo Score: $score = $totalscore% -- cgit v1.2.3-70-g09d2