浏览代码

Update master from bsys-ws17-template/hw1

Manuel Vögele 8 年前
父节点
当前提交
5705043367

+ 34
- 0
files/hw1.txt 查看文件

@@ -0,0 +1,34 @@
1
+./hw1/README.md
2
+./hw1/simu1/README-process-run.md
3
+./hw1/simu1/ANSWERS.md
4
+./hw1/simu1/QUESTIONS.md
5
+./hw1/simu1/process-run.py
6
+
7
+
8
+./hw1/simu2/QUESTIONS.md
9
+?./hw1/simu2/ANSWERS.md
10
+
11
+./hw1/task1/Cargo.toml
12
+./hw1/task1/src/lib.rs
13
+./hw1/task1/tests/task1.rs
14
+
15
+
16
+./hw1/task2/Cargo.toml
17
+./hw1/task2/src/lib.rs
18
+./hw1/task2/tests/task2.rs
19
+
20
+
21
+./hw1/task3/Cargo.toml
22
+./hw1/task3/src/lib.rs
23
+./hw1/task3/tests/task3.rs
24
+
25
+
26
+./hw1/task4/Cargo.toml
27
+./hw1/task4/src/lib.rs
28
+./hw1/task4/tests/task4.rs
29
+
30
+./hw1/task5/Cargo.toml
31
+./hw1/task5/Cargo.lock
32
+./hw1/task5/src/main.rs
33
+./hw1/task5/tests/output.bats
34
+

+ 47
- 0
hw1/README.md 查看文件

@@ -0,0 +1,47 @@
1
+# hw1
2
+
3
+## Tasks
4
+To fullfill **hw1** you have to solve:
5
+
6
+- task1
7
+- task2
8
+- task3
9
+- task4
10
+- simu1
11
+
12
+Optinal are (bonus +1P):
13
+
14
+- task5
15
+- simu2
16
+
17
+## Files
18
+You find already files for earch rust task.
19
+
20
+## ASIDE: SIMULATION HOMEWORKS
21
+
22
+Simulation homeworks (`simuN/`) come in the form of simulators you run to
23
+make sure you understand some piece of the material. The simulators are generally python programs that enable you both to generate different problems (using different random seeds) as well as to have the program solve the problem for you (with the `-c` flag) so that you can check your answers. Running any simulator with a `-h` or `--help`flag will provide with more information as to all the options the simulator gives you.
24
+
25
+The README provided with each simulator gives more detail as to how to run it. Each flag is described in some detail therein.
26
+
27
+You find all Files for your simulation homework in the `simuN/` directory.
28
+
29
+## Pull-Reuest
30
+
31
+If you are ready with the homework, all tests run, please create a pull request named **hw1**.
32
+
33
+## Gradings
34
+
35
+### hw1
36
+
37
+| Task | max. Credits | Comment |
38
+|---|---|---|
39
+| simu1 | 1 | |
40
+| task1 | 1 | |
41
+| task2 | 1 | |
42
+| task3 | 0,5 | |
43
+| task4 | 0,5 | |
44
+| simu2 | +0,5 | |
45
+| task5 | +0,5 | |
46
+| Deadline | +1 | |
47
+| = | 6 | |

+ 35
- 0
hw1/simu1/QUESTIONS.md 查看文件

@@ -0,0 +1,35 @@
1
+# Questions 4-Process-Run Simulation Part 1
2
+
3
+This program, `process-run.py`, allows you to see how process states change as programs run and either use the CPU (e.g., perform an add instruction) or do I/O (e.g., send a request to a disk and wait for it to complete). See the README for details.
4
+
5
+Please answer the questions, by giving the result and an explanation, why you got the result. Sometimes it could be helpful, if you compare your result with results of earlier questions. Write your answers in [markdown syntax][]  in the new file `ANSWERS.md.`
6
+
7
+1. Run the program with the following flags:
8
+
9
+ ```text
10
+./process-run.py -l 5:100,5:100.
11
+ ```
12
+
13
+ What should the CPU utilization be (e.g., the percent of time the CPU is in use?) Why do you know this? Use the `-c` and `-p` flags to see if you were right.
14
+
15
+2. Now run with these flags:
16
+
17
+ ```text
18
+./process-run.py -l 4:100,1:0.
19
+ ```
20
+
21
+ These flags specify one process with 4 instructions (all to use the CPU), and one that simply issues an I/O and waits for it to be done. How long does it take to complete both processes? Use `-c` and `-p` to find out if you were right.
22
+
23
+3. Now switch the order of the processes:
24
+
25
+ ```text
26
+./process-run.py -l 1:0,4:100.
27
+ ```
28
+
29
+ What happens now? Does switching the order matter? Why? (As always, use `-c` and `-p` to see if you were right)
30
+
31
+4. We’ll now explore some of the other flags. One important flag is `-S`, which determines how the system reacts when a process issues an I/O. With the flag set to `SWITCH_ON_END`, the system will NOT switch to another process while one is doing I/O, instead waiting until the process is completely finished. What happens when you run the following two processes, one doing I/O and the other doing CPU work? (`-l 1:0,4:100 -c -S SWITCH_ON_END`)
32
+
33
+5. Now, run the same processes, but with the switching behavior set to switch to another process whenever one is WAITING for I/O (`-l 1:0,4:100 -c -S SWITCH ON IO`). What happens now? Use `-c` and `-p` to confirm that you are right.
34
+
35
+[markdown syntax]: https://guides.github.com/features/mastering-markdown/

+ 236
- 0
hw1/simu1/README-process-run.md 查看文件

@@ -0,0 +1,236 @@
1
+# README Process Run
2
+
3
+
4
+This program, called `process-run.py`, allows you to see how the state of a
5
+process state changes as it runs on a CPU. As described in the chapter,
6
+processes can be in a few different states:
7
+
8
+```text
9
+  RUNNING - the process is using the CPU right now
10
+  READY   - the process could be using the CPU right now
11
+            but (alas) some other process is
12
+  WAITING - the process is waiting on I/O
13
+            (e.g., it issued a request to a disk)
14
+  DONE    - the process is finished executing
15
+```
16
+
17
+In this homework, we'll see how these process states change as a program
18
+runs, and thus learn a little bit better how these things work.
19
+
20
+To run the program and get its options, do this:
21
+
22
+```text
23
+prompt> ./process-run.py -h
24
+````
25
+
26
+If this doesn't work, type "python" before the command, like this:
27
+
28
+```text
29
+prompt> python process-run.py -h
30
+```
31
+
32
+What you should see is this:
33
+
34
+```text
35
+Usage: process-run.py [options]
36
+
37
+Options:
38
+  -h, --help            show this help message and exit
39
+  -s SEED, --seed=SEED  the random seed
40
+  -l PROCESS_LIST, --processlist=PROCESS_LIST
41
+                        a comma-separated list of processes to run, in the
42
+                        form X1:Y1,X2:Y2,... where X is the number of
43
+                        instructions that process should run, and Y the
44
+                        chances (from 0 to 100) that an instruction will use
45
+                        the CPU or issue an IO
46
+  -L IO_LENGTH, --iolength=IO_LENGTH
47
+                        how long an IO takes
48
+  -S PROCESS_SWITCH_BEHAVIOR, --switch=PROCESS_SWITCH_BEHAVIOR
49
+                        when to switch between processes: SWITCH_ON_IO,
50
+                        SWITCH_ON_END
51
+  -I IO_DONE_BEHAVIOR, --iodone=IO_DONE_BEHAVIOR
52
+                        type of behavior when IO ends: IO_RUN_LATER,
53
+                        IO_RUN_IMMEDIATE
54
+  -c                    compute answers for me
55
+  -p, --printstats      print statistics at end; only useful with -c flag
56
+                        (otherwise stats are not printed)
57
+```
58
+
59
+The most important option to understand is the **PROCESS_LIST** (as specified by
60
+the -l or --processlist flags) which specifies exactly what each running
61
+program (or "process") will do. A process consists of instructions, and each
62
+instruction can just do one of two things:
63
+
64
+- use the CPU
65
+- issue an IO (and wait for it to complete)
66
+
67
+When a process uses the CPU (and does no IO at all), it should simply
68
+alternate between RUNNING on the CPU or being READY to run. For example, here
69
+is a simple run that just has one program being run, and that program only
70
+uses the CPU (it does no IO).
71
+
72
+```text
73
+prompt> ./process-run.py -l 5:100
74
+Produce a trace of what would happen when you run these processes:
75
+Process 0
76
+  cpu
77
+  cpu
78
+  cpu
79
+  cpu
80
+  cpu
81
+
82
+Important behaviors:
83
+  System will switch when the current process is FINISHED or ISSUES AN IO
84
+  After IOs, the process issuing the IO will run LATER (when it is its turn)
85
+
86
+prompt>
87
+```
88
+
89
+Here, the process we specified is "5:100" which means it should consist of 5
90
+instructions, and the chances that each instruction is a CPU instruction are
91
+100%.
92
+
93
+You can see what happens to the process by using the -c flag, which computes the
94
+answers for you:
95
+
96
+```text
97
+prompt> ./process-run.py -l 5:100 -c
98
+Time     PID: 0        CPU        IOs
99
+  1     RUN:cpu          1
100
+  2     RUN:cpu          1
101
+  3     RUN:cpu          1
102
+  4     RUN:cpu          1
103
+  5     RUN:cpu          1
104
+````
105
+
106
+This result is not too interesting: the process is simple in the **RUN** state and then finishes, using the CPU the whole time and thus keeping the CPU busy the entire run, and not doing any I/Os.
107
+
108
+Let's make it slightly more complex by running two processes:
109
+
110
+```text
111
+prompt> ./process-run.py -l 5:100,5:100
112
+Produce a trace of what would happen when you run these processes:
113
+Process 0
114
+  cpu
115
+  cpu
116
+  cpu
117
+  cpu
118
+  cpu
119
+
120
+Process 1
121
+  cpu
122
+  cpu
123
+  cpu
124
+  cpu
125
+  cpu
126
+
127
+
128
+Important behaviors:
129
+  Scheduler will switch when the current process is FINISHED or ISSUES AN IO
130
+  After IOs, the process issuing the IO will run LATER (when it is its turn)
131
+```
132
+
133
+In this case, two different processes run, each again just using the CPU. What
134
+happens when the operating system runs them? Let's find out:
135
+
136
+```text
137
+prompt> ./process-run.py -l 5:100,5:100 -c
138
+Time     PID: 0     PID: 1        CPU        IOs
139
+  1     RUN:cpu      READY          1
140
+  2     RUN:cpu      READY          1
141
+  3     RUN:cpu      READY          1
142
+  4     RUN:cpu      READY          1
143
+  5     RUN:cpu      READY          1
144
+  6        DONE    RUN:cpu          1
145
+  7        DONE    RUN:cpu          1
146
+  8        DONE    RUN:cpu          1
147
+  9        DONE    RUN:cpu          1
148
+ 10        DONE    RUN:cpu          1
149
+```
150
+
151
+As you can see above, first the process with "process ID" (or "PID") 0 runs,
152
+while process 1 is READY to run but just waits until 0 is done. When 0 is
153
+finished, it moves to the DONE state, while 1 runs. When 1 finishes, the trace
154
+is done.
155
+
156
+Let's look at one more example before getting to some questions. In this
157
+example, the process just issues I/O requests. We specify here tht I/Os take 5
158
+time units to complete with the flag -L.
159
+
160
+```text
161
+prompt> ./process-run.py -l 3:0 -L 5
162
+Produce a trace of what would happen when you run these processes:
163
+Process 0
164
+  io-start
165
+  io-start
166
+  io-start
167
+
168
+Important behaviors:
169
+  System will switch when the current process is FINISHED or ISSUES AN IO
170
+  After IOs, the process issuing the IO will run LATER (when it is its turn)
171
+```
172
+
173
+What do you think the execution trace will look like? Let's find out:
174
+
175
+```text
176
+prompt> ./process-run.py -l 3:0 -L 5 -c
177
+Time     PID: 0        CPU        IOs
178
+  1  RUN:io-start          1
179
+  2     WAITING                     1
180
+  3     WAITING                     1
181
+  4     WAITING                     1
182
+  5     WAITING                     1
183
+  6* RUN:io-start          1
184
+  7     WAITING                     1
185
+  8     WAITING                     1
186
+  9     WAITING                     1
187
+ 10     WAITING                     1
188
+ 11* RUN:io-start          1
189
+ 12     WAITING                     1
190
+ 13     WAITING                     1
191
+ 14     WAITING                     1
192
+ 15     WAITING                     1
193
+ 16*       DONE
194
+```
195
+
196
+As you can see, the program just issues three I/Os. When each I/O is issued,
197
+the process moves to a WAITING state, and while the device is busy servicing
198
+the I/O, the CPU is idle.
199
+
200
+Let's print some stats (run the same command as above, but with the `-p flag)
201
+to see some overall behaviors:
202
+
203
+```text
204
+...
205
+Stats: Total Time 16
206
+Stats: CPU Busy 3 (18.75%)
207
+Stats: IO Busy  12 (75.00%)
208
+```
209
+
210
+As you can see, the trace took 16 clock ticks to run, but the CPU was only
211
+busy less than 20% of the time. The IO device, on the other hand, was quite
212
+busy. In general, we'd like to keep all the devices busy, as that is a better
213
+use of resources.
214
+
215
+There are a few other important flags:
216
+
217
+* `-s SEED, --seed=SEED`  the random seed
218
+
219
+ this gives you way to create a bunch of different jobs randomly
220
+
221
+* `-L IO_LENGTH, --iolength=IO_LENGTH`
222
+
223
+  this determines how long IOs take to complete (default is 5 ticks)
224
+
225
+* `-S PROCESS_SWITCH_BEHAVIOR, --switch=PROCESS_SWITCH_BEHAVIOR` when to switch between processes: `SWITCH_ON_IO, SWITCH_ON_END`
226
+
227
+  this determines when we switch to another process:
228
+    -  `SWITCH_ON_IO`, the system will switch when a process issues an IO
229
+    -  `SWITCH_ON_END`, the system will only switch when the current process is done
230
+
231
+* `-I IO_DONE_BEHAVIOR, --iodone=IO_DONE_BEHAVIOR` type of behavior when IO ends: `IO_RUN_LATER`, `IO_RUN_IMMEDIATE`
232
+
233
+  this determines when a process runs after it issues an IO:
234
+    -  `IO_RUN_IMMEDIATE`: switch to this process right now
235
+    -  `IO_RUN_LATER`: switch to this process when it is natural to
236
+      (e.g., depending on process-switching behavior)

+ 325
- 0
hw1/simu1/process-run.py 查看文件

@@ -0,0 +1,325 @@
1
+#! /usr/bin/env python
2
+
3
+import sys
4
+from optparse import OptionParser
5
+import random
6
+
7
+# process switch behavior
8
+SCHED_SWITCH_ON_IO = 'SWITCH_ON_IO'
9
+SCHED_SWITCH_ON_END = 'SWITCH_ON_END'
10
+
11
+# io finished behavior
12
+IO_RUN_LATER = 'IO_RUN_LATER'
13
+IO_RUN_IMMEDIATE = 'IO_RUN_IMMEDIATE'
14
+
15
+# process states
16
+STATE_RUNNING = 'RUNNING'
17
+STATE_READY = 'READY'
18
+STATE_DONE = 'DONE'
19
+STATE_WAIT = 'WAITING'
20
+
21
+# members of process structure
22
+PROC_CODE = 'code_'
23
+PROC_PC = 'pc_'
24
+PROC_ID = 'pid_'
25
+PROC_STATE = 'proc_state_'
26
+
27
+# things a process can do
28
+DO_COMPUTE = 'cpu'
29
+DO_IO = 'io'
30
+
31
+
32
+class scheduler:
33
+    def __init__(self, process_switch_behavior, io_done_behavior, io_length):
34
+        # keep set of instructions for each of the processes
35
+        self.proc_info = {}
36
+        self.process_switch_behavior = process_switch_behavior
37
+        self.io_done_behavior = io_done_behavior
38
+        self.io_length = io_length
39
+        return
40
+
41
+    def new_process(self):
42
+        proc_id = len(self.proc_info)
43
+        self.proc_info[proc_id] = {}
44
+        self.proc_info[proc_id][PROC_PC] = 0
45
+        self.proc_info[proc_id][PROC_ID] = proc_id
46
+        self.proc_info[proc_id][PROC_CODE] = []
47
+        self.proc_info[proc_id][PROC_STATE] = STATE_READY
48
+        return proc_id
49
+
50
+    def load_file(self, progfile):
51
+        fd = open(progfile)
52
+        proc_id = self.new_process()
53
+        
54
+        for line in fd:
55
+            tmp = line.split()
56
+            if len(tmp) == 0:
57
+                continue
58
+            opcode = tmp[0]
59
+            if opcode == 'compute':
60
+                assert(len(tmp) == 2)
61
+                for i in range(int(tmp[1])):
62
+                    self.proc_info[proc_id][PROC_CODE].append(DO_COMPUTE)
63
+            elif opcode == 'io':
64
+                assert(len(tmp) == 1)
65
+                self.proc_info[proc_id][PROC_CODE].append(DO_IO)
66
+        fd.close()
67
+        return
68
+
69
+    def load(self, program_description):
70
+        proc_id = self.new_process()
71
+        tmp = program_description.split(':')
72
+        if len(tmp) != 2:
73
+            print 'Bad description (%s): Must be number <x:y>' % program_description
74
+            print '  where X is the number of instructions'
75
+            print '  and Y is the percent change that an instruction is CPU not IO'
76
+            exit(1)
77
+
78
+        num_instructions, chance_cpu = int(tmp[0]), float(tmp[1])/100.0
79
+        for i in range(num_instructions):
80
+            if random.random() < chance_cpu:
81
+                self.proc_info[proc_id][PROC_CODE].append(DO_COMPUTE)
82
+            else:
83
+                self.proc_info[proc_id][PROC_CODE].append(DO_IO)
84
+        return
85
+
86
+    def move_to_ready(self, expected, pid=-1):
87
+        if pid == -1:
88
+            pid = self.curr_proc
89
+        assert(self.proc_info[pid][PROC_STATE] == expected)
90
+        self.proc_info[pid][PROC_STATE] = STATE_READY
91
+        return
92
+
93
+    def move_to_wait(self, expected):
94
+        assert(self.proc_info[self.curr_proc][PROC_STATE] == expected)
95
+        self.proc_info[self.curr_proc][PROC_STATE] = STATE_WAIT
96
+        return
97
+
98
+    def move_to_running(self, expected):
99
+        assert(self.proc_info[self.curr_proc][PROC_STATE] == expected)
100
+        self.proc_info[self.curr_proc][PROC_STATE] = STATE_RUNNING
101
+        return
102
+
103
+    def move_to_done(self, expected):
104
+        assert(self.proc_info[self.curr_proc][PROC_STATE] == expected)
105
+        self.proc_info[self.curr_proc][PROC_STATE] = STATE_DONE
106
+        return
107
+
108
+    def next_proc(self, pid=-1):
109
+        if pid != -1:
110
+            self.curr_proc = pid
111
+            self.move_to_running(STATE_READY)
112
+            return
113
+        for pid in range(self.curr_proc + 1, len(self.proc_info)):
114
+            if self.proc_info[pid][PROC_STATE] == STATE_READY:
115
+                self.curr_proc = pid
116
+                self.move_to_running(STATE_READY)
117
+                return
118
+        for pid in range(0, self.curr_proc + 1):
119
+            if self.proc_info[pid][PROC_STATE] == STATE_READY:
120
+                self.curr_proc = pid
121
+                self.move_to_running(STATE_READY)
122
+                return
123
+        return
124
+
125
+    def get_num_processes(self):
126
+        return len(self.proc_info)
127
+
128
+    def get_num_instructions(self, pid):
129
+        return len(self.proc_info[pid][PROC_CODE])
130
+
131
+    def get_instruction(self, pid, index):
132
+        return self.proc_info[pid][PROC_CODE][index]
133
+
134
+    def get_num_active(self):
135
+        num_active = 0
136
+        for pid in range(len(self.proc_info)):
137
+            if self.proc_info[pid][PROC_STATE] != STATE_DONE:
138
+                num_active += 1
139
+        return num_active
140
+
141
+    def get_num_runnable(self):
142
+        num_active = 0
143
+        for pid in range(len(self.proc_info)):
144
+            if self.proc_info[pid][PROC_STATE] == STATE_READY or \
145
+                   self.proc_info[pid][PROC_STATE] == STATE_RUNNING:
146
+                num_active += 1
147
+        return num_active
148
+
149
+    def get_ios_in_flight(self, current_time):
150
+        num_in_flight = 0
151
+        for pid in range(len(self.proc_info)):
152
+            for t in self.io_finish_times[pid]:
153
+                if t > current_time:
154
+                    num_in_flight += 1
155
+        return num_in_flight
156
+
157
+    def check_for_switch(self):
158
+        return
159
+
160
+    def space(self, num_columns):
161
+        for i in range(num_columns):
162
+            print '%10s' % ' ',
163
+
164
+    def check_if_done(self):
165
+        if len(self.proc_info[self.curr_proc][PROC_CODE]) == 0:
166
+            if self.proc_info[self.curr_proc][PROC_STATE] == STATE_RUNNING:
167
+                self.move_to_done(STATE_RUNNING)
168
+                self.next_proc()
169
+        return
170
+
171
+    def run(self):
172
+        clock_tick = 0
173
+
174
+        if len(self.proc_info) == 0:
175
+            return
176
+
177
+        # track outstanding IOs, per process
178
+        self.io_finish_times = {}
179
+        for pid in range(len(self.proc_info)):
180
+            self.io_finish_times[pid] = []
181
+
182
+        # make first one active
183
+        self.curr_proc = 0
184
+        self.move_to_running(STATE_READY)
185
+
186
+        # OUTPUT: headers for each column
187
+        print '%s' % 'Time', 
188
+        for pid in range(len(self.proc_info)):
189
+            print '%10s' % ('PID:%2d' % (pid)),
190
+        print '%10s' % 'CPU',
191
+        print '%10s' % 'IOs',
192
+        print ''
193
+
194
+        # init statistics
195
+        io_busy = 0
196
+        cpu_busy = 0
197
+
198
+        while self.get_num_active() > 0:
199
+            clock_tick += 1
200
+
201
+            # check for io finish
202
+            io_done = False
203
+            for pid in range(len(self.proc_info)):
204
+                if clock_tick in self.io_finish_times[pid]:
205
+                    io_done = True
206
+                    self.move_to_ready(STATE_WAIT, pid)
207
+                    if self.io_done_behavior == IO_RUN_IMMEDIATE:
208
+                        # IO_RUN_IMMEDIATE
209
+                        if self.curr_proc != pid:
210
+                            if self.proc_info[self.curr_proc][PROC_STATE] == STATE_RUNNING:
211
+                                self.move_to_ready(STATE_RUNNING)
212
+                        self.next_proc(pid)
213
+                    else:
214
+                        # IO_RUN_LATER
215
+                        if self.process_switch_behavior == SCHED_SWITCH_ON_END and self.get_num_runnable() > 1:
216
+                            # this means the process that issued the io should be run
217
+                            self.next_proc(pid)
218
+                        if self.get_num_runnable() == 1:
219
+                            # this is the only thing to run: so run it
220
+                            self.next_proc(pid)
221
+                    self.check_if_done()
222
+            
223
+            # if current proc is RUNNING and has an instruction, execute it
224
+            instruction_to_execute = ''
225
+            if self.proc_info[self.curr_proc][PROC_STATE] == STATE_RUNNING and \
226
+                   len(self.proc_info[self.curr_proc][PROC_CODE]) > 0:
227
+                instruction_to_execute = self.proc_info[self.curr_proc][PROC_CODE].pop(0)
228
+                cpu_busy += 1
229
+
230
+            # OUTPUT: print what everyone is up to
231
+            if io_done:
232
+                print '%3d*' % clock_tick,
233
+            else:
234
+                print '%3d ' % clock_tick,
235
+            for pid in range(len(self.proc_info)):
236
+                if pid == self.curr_proc and instruction_to_execute != '':
237
+                    print '%10s' % ('RUN:'+instruction_to_execute),
238
+                else:
239
+                    print '%10s' % (self.proc_info[pid][PROC_STATE]),
240
+            if instruction_to_execute == '':
241
+                print '%10s' % ' ',
242
+            else:
243
+                print '%10s' % 1,
244
+            num_outstanding = self.get_ios_in_flight(clock_tick)
245
+            if num_outstanding > 0:
246
+                print '%10s' % str(num_outstanding),
247
+                io_busy += 1
248
+            else:
249
+                print '%10s' % ' ',
250
+            print ''
251
+
252
+            # if this is an IO instruction, switch to waiting state
253
+            # and add an io completion in the future
254
+            if instruction_to_execute == DO_IO:
255
+                self.move_to_wait(STATE_RUNNING)
256
+                self.io_finish_times[self.curr_proc].append(clock_tick + self.io_length)
257
+                if self.process_switch_behavior == SCHED_SWITCH_ON_IO:
258
+                    self.next_proc()
259
+
260
+            # ENDCASE: check if currently running thing is out of instructions
261
+            self.check_if_done()
262
+        return (cpu_busy, io_busy, clock_tick)
263
+        
264
+#
265
+# PARSE ARGUMENTS
266
+#
267
+
268
+parser = OptionParser()
269
+parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed')
270
+parser.add_option('-l', '--processlist', default='',
271
+                  help='a comma-separated list of processes to run, in the form X1:Y1,X2:Y2,... where X is the number of instructions that process should run, and Y the chances (from 0 to 100) that an instruction will use the CPU or issue an IO',
272
+                  action='store', type='string', dest='process_list')
273
+parser.add_option('-L', '--iolength', default=5, help='how long an IO takes', action='store', type='int', dest='io_length')
274
+parser.add_option('-S', '--switch', default='SWITCH_ON_IO',
275
+                  help='when to switch between processes: SWITCH_ON_IO, SWITCH_ON_END',
276
+                  action='store', type='string', dest='process_switch_behavior')
277
+parser.add_option('-I', '--iodone', default='IO_RUN_LATER',
278
+                  help='type of behavior when IO ends: IO_RUN_LATER, IO_RUN_IMMEDIATE',
279
+                  action='store', type='string', dest='io_done_behavior')
280
+parser.add_option('-c', help='compute answers for me', action='store_true', default=False, dest='solve')
281
+parser.add_option('-p', '--printstats', help='print statistics at end; only useful with -c flag (otherwise stats are not printed)', action='store_true', default=False, dest='print_stats')
282
+(options, args) = parser.parse_args()
283
+
284
+random.seed(options.seed)
285
+
286
+assert(options.process_switch_behavior == SCHED_SWITCH_ON_IO or \
287
+       options.process_switch_behavior == SCHED_SWITCH_ON_END)
288
+assert(options.io_done_behavior == IO_RUN_IMMEDIATE or \
289
+       options.io_done_behavior == IO_RUN_LATER)
290
+
291
+s = scheduler(options.process_switch_behavior, options.io_done_behavior, options.io_length)
292
+
293
+# example process description (10:100,10:100)
294
+for p in options.process_list.split(','):
295
+    s.load(p)
296
+
297
+if options.solve == False:
298
+    print 'Produce a trace of what would happen when you run these processes:'
299
+    for pid in range(s.get_num_processes()):
300
+        print 'Process %d' % pid
301
+        for inst in range(s.get_num_instructions(pid)):
302
+            print '  %s' % s.get_instruction(pid, inst)
303
+        print ''
304
+    print 'Important behaviors:'
305
+    print '  System will switch when',
306
+    if options.process_switch_behavior == SCHED_SWITCH_ON_IO:
307
+        print 'the current process is FINISHED or ISSUES AN IO'
308
+    else:
309
+        print 'the current process is FINISHED'
310
+    print '  After IOs, the process issuing the IO will',
311
+    if options.io_done_behavior == IO_RUN_IMMEDIATE:
312
+        print 'run IMMEDIATELY'
313
+    else:
314
+        print 'run LATER (when it is its turn)'
315
+    print ''
316
+    exit(0)
317
+
318
+(cpu_busy, io_busy, clock_tick) = s.run()
319
+
320
+if options.print_stats:
321
+    print ''
322
+    print 'Stats: Total Time %d' % clock_tick
323
+    print 'Stats: CPU Busy %d (%.2f%%)' % (cpu_busy, 100.0 * float(cpu_busy)/clock_tick)
324
+    print 'Stats: IO Busy  %d (%.2f%%)' % (io_busy, 100.0 * float(io_busy)/clock_tick)
325
+    print ''

+ 18
- 0
hw1/simu2/QUESTIONS.md 查看文件

@@ -0,0 +1,18 @@
1
+# Questions 4-Process-Run Simulation Part 2
2
+
3
+This program, `process-run.py`, allows you to see how process states change as programs run and either use the CPU (e.g., perform an add instruction) or do I/O (e.g., send a request to a disk and wait for it to complete). See the README for details.
4
+
5
+Please answer the questions, by giving the result and an explanation, why you got the result. Sometimes it could be helpful, if you compare your result with results of earlier questions. Write your answers in markdown syntax in the new file `ANSWERS.md.`
6
+
7
+
8
+1. One  important behavior is what to do when an I/O completes. With `-I IO_RUN_LATER`, when an I/O completes, the process that issued it is not necessarily run right away; rather, whatever was running at the time keeps running. What happens when you run this combination of processes?
9
+
10
+ ```text
11
+./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH ON IO -I IO RUN LATER -c -p
12
+ ```
13
+
14
+ Are system resources being effectively utilized?
15
+
16
+2. Now run the same processes, but with `-I IO_RUN_IMMEDIATE` set, which immediately runs the process that issued the I/O. How does this behavior differ? Why might running a process that just completed an I/O again be a good idea?
17
+
18
+3. Now run with some randomly generated processes, e.g., `-s 1 -l 3:50,3:50, -s 2 -l 3:50,3:50, -s 3 -l 3:50,3:50`. See if you can predict how the trace will turn out. What happens when you use `-I IO_RUN_IMMEDIATE` vs. `-I IO_RUN_LATER`? What happens when you use `-S SWITCH_ON_IO` vs. `-S SWITCH_ON_END`?

+ 31
- 0
hw1/task1/README.md 查看文件

@@ -0,0 +1,31 @@
1
+# Homework hw1 task 1
2
+
3
+## Vorbereitungen
4
+
5
+Rufen Sie im `task1/` Verzeichnis: `cargo init` auf. Dadurch wird ein Rust Library Projekt in `task1/` angelegt. Mit `cargo build` wird die Library erstellt, der Aufruf `cargo test` ruft die CI Tests im `tests/` Verzeichnis auf und testet Ihre Library.
6
+
7
+## task
8
+
9
+Schreiben Sie die Funktion
10
+
11
+```rust
12
+pub fn is_leap_year(year: i32) -> bool
13
+```
14
+
15
+die überprüft, ob das übergebene Jahr ein Schaltjahr ist.
16
+
17
+Das trickreiche an der Überprüfung ist, dass folgende Bedingungen für das Jahr gelten müssen:
18
+
19
+```plain
20
+on every year that is evenly divisible by 4
21
+  except every year that is evenly divisible by 100
22
+    unless the year is also evenly divisible by 400
23
+```
24
+
25
+Zum Beispiel ist 1997 kein Schaltjahr, aber 1996. 1900 ist kein Schaltjahr aber 2000.
26
+
27
+Verwenden Sie keine Funktionen aus Bibliotheken dafür, sondern implementieren Sie die Funktion selbst.
28
+
29
+## Test
30
+
31
+Testen können Sie Ihre Library durch den Aufruf von `cargo test`. Dann werden alle Tests aus der Datei `tests/task1.rs` ausgeführt.

+ 3
- 0
hw1/task1/src/lib.rs 查看文件

@@ -0,0 +1,3 @@
1
+pub fn is_leap_year(year: i32) -> bool {
2
+    unimplemented!();
3
+}

+ 25
- 0
hw1/task1/tests/task1.rs 查看文件

@@ -0,0 +1,25 @@
1
+extern crate task1;
2
+
3
+#[test]
4
+fn test_vanilla_leap_year() {
5
+    assert_eq!(task1::is_leap_year(1996), true);
6
+}
7
+
8
+#[test]
9
+fn test_any_old_year() {
10
+    assert_eq!(task1::is_leap_year(1995), false);
11
+    assert_eq!(task1::is_leap_year(1997), false);
12
+    assert_eq!(task1::is_leap_year(1998), false);
13
+    assert_eq!(task1::is_leap_year(1999), false);
14
+}
15
+
16
+#[test]
17
+fn test_century() {
18
+    assert_eq!(task1::is_leap_year(1900), false);
19
+}
20
+
21
+#[test]
22
+fn test_exceptional_centuries() {
23
+    assert_eq!(task1::is_leap_year(2000), true);
24
+    assert_eq!(task1::is_leap_year(2400), true);
25
+}

+ 24
- 0
hw1/task2/README.md 查看文件

@@ -0,0 +1,24 @@
1
+# Homework hw1 task 2
2
+
3
+## prepare your task
4
+
5
+Run `cargo init` in your `task2/` directory.
6
+
7
+## task
8
+
9
+Calculate the number of grains of wheat on a chessboard given that the number on each square doubles.
10
+
11
+There once was a wise servant who saved the life of a prince. The king
12
+promised to pay whatever the servant could dream up. Knowing that the
13
+king loved chess, the servant told the king he would like to have grains
14
+of wheat. One grain on the first square of a chess board. Two grains on
15
+the next. Four on the third, and so on.
16
+
17
+There are 64 squares on a chessboard.
18
+
19
+Write code that shows:
20
+
21
+- how many grains were on each square (`fn square(n: u32) -> u64`), and
22
+- the total number of grains (`fn total() -> u64`)
23
+
24
+Use the given file `lib.rs` for your solution.

+ 8
- 0
hw1/task2/src/lib.rs 查看文件

@@ -0,0 +1,8 @@
1
+pub fn square(n: u32) -> u64 {
2
+    unimplemented!()
3
+}
4
+
5
+
6
+pub fn total() -> u64 {
7
+    unimplemented!();
8
+}

+ 41
- 0
hw1/task2/tests/task2.rs 查看文件

@@ -0,0 +1,41 @@
1
+extern crate task2;
2
+
3
+#[test]
4
+fn square_one() {
5
+    assert_eq!(task2::square(1), 1);
6
+}
7
+
8
+#[test]
9
+fn square_two() {
10
+    assert_eq!(task2::square(2), 2);
11
+}
12
+
13
+#[test]
14
+fn square_three() {
15
+    assert_eq!(task2::square(3), 4);
16
+}
17
+
18
+#[test]
19
+fn square_four() {
20
+    assert_eq!(task2::square(4), 8);
21
+}
22
+
23
+#[test]
24
+fn square_sixteen() {
25
+    assert_eq!(task2::square(16), 32_768);
26
+}
27
+
28
+#[test]
29
+fn square_thirty_two() {
30
+    assert_eq!(task2::square(32), 2_147_483_648);
31
+}
32
+
33
+#[test]
34
+fn square_sixty_four() {
35
+    assert_eq!(task2::square(64), 9_223_372_036_854_775_808);
36
+}
37
+
38
+#[test]
39
+fn total_sums_all_squares() {
40
+    assert_eq!(task2::total(), 18_446_744_073_709_551_615);
41
+}

+ 8
- 0
hw1/task3/README.md 查看文件

@@ -0,0 +1,8 @@
1
+# Homework hw1 task 3
2
+
3
+## prepare your task
4
+
5
+Run `cargo init` in your `task3/` directory.
6
+
7
+## task
8
+Schreiben Sie eine Funktion `count(line: &str, c: char) -> u64)` welche zählt, wie oft ein gegebenes Zeichen (c) in einem gegebenen String (line) vorkommt und diese Anzahl zurück gibt. Z.B. soll der Aufruf `count("peter", 'e')` `2` zurückgeben.

+ 3
- 0
hw1/task3/src/lib.rs 查看文件

@@ -0,0 +1,3 @@
1
+pub fn count(line: &str, c: char) -> u64 {
2
+    unimplemented!();
3
+}

+ 45
- 0
hw1/task3/tests/task3.rs 查看文件

@@ -0,0 +1,45 @@
1
+extern crate task3;
2
+
3
+#[test]
4
+fn test_one_char() {
5
+    assert_eq!(
6
+        task3::count("♥ The quick brown fox jumps over the lazy dog. ♥", 'T'),
7
+        1
8
+    );
9
+}
10
+
11
+#[test]
12
+fn test_two_char() {
13
+    assert_eq!(
14
+        task3::count(
15
+            "♥ The quick brown fox jumps over the lazy dog. ♥",
16
+            '♥',
17
+        ),
18
+        2
19
+    );
20
+}
21
+
22
+#[test]
23
+#[should_panic]
24
+fn test_wrong() {
25
+    assert_eq!(
26
+        task3::count("♥ The quick brown fox jumps over the lazy dog. ♥", 'c'),
27
+        2
28
+    );
29
+}
30
+
31
+#[test]
32
+fn test_four_char() {
33
+    assert_eq!(
34
+        task3::count("♥ The quick brown fox jumps over the lazy dog. ♥", 'o'),
35
+        4
36
+    );
37
+}
38
+
39
+#[test]
40
+fn test_no_char() {
41
+    assert_eq!(
42
+        task3::count("♥ The quick brown fox jumps over the lazy dog. ♥", '!'),
43
+        0
44
+    );
45
+}

+ 22
- 0
hw1/task4/README.md 查看文件

@@ -0,0 +1,22 @@
1
+# Homework hw1 task 4
2
+
3
+## prepare your task
4
+
5
+Run `cargo init` in your `task4/` directory.
6
+
7
+## task
8
+
9
+Find the difference between the sum of the squares and the square of the sum of the first N natural numbers.
10
+
11
+The square of the sum of the first ten natural numbers is,
12
+
13
+    (1 + 2 + ... + 10)**2 = 55**2 = 3025
14
+
15
+The sum of the squares of the first ten natural numbers is,
16
+
17
+    1**2 + 2**2 + ... + 10**2 = 385
18
+
19
+Hence the difference between the square of the sum of the first
20
+ten natural numbers and the sum of the squares is 2640:
21
+
22
+    3025 - 385 = 2640

+ 11
- 0
hw1/task4/src/lib.rs 查看文件

@@ -0,0 +1,11 @@
1
+pub fn square_of_sum(n: i32) -> i32 {
2
+    unimplemented!();
3
+}
4
+
5
+pub fn sum_of_squares(n: i32) -> i32 {
6
+    unimplemented!();
7
+}
8
+
9
+pub fn difference(n: i32) -> i32 {
10
+    unimplemented!();
11
+}

+ 31
- 0
hw1/task4/tests/task4.rs 查看文件

@@ -0,0 +1,31 @@
1
+extern crate task4;
2
+
3
+#[test]
4
+fn test_square_of_sum_5() {
5
+    assert_eq!(225, task4::square_of_sum(5));
6
+}
7
+
8
+#[test]
9
+fn test_sum_of_squares_5() {
10
+    assert_eq!(55, task4::sum_of_squares(5));
11
+}
12
+
13
+#[test]
14
+fn test_difference_5() {
15
+    assert_eq!(170, task4::difference(5));
16
+}
17
+
18
+#[test]
19
+fn test_square_of_sum_100() {
20
+    assert_eq!(25502500, task4::square_of_sum(100));
21
+}
22
+
23
+#[test]
24
+fn test_sum_of_squares_100() {
25
+    assert_eq!(338350, task4::sum_of_squares(100));
26
+}
27
+
28
+#[test]
29
+fn test_difference_100() {
30
+    assert_eq!(25164150, task4::difference(100));
31
+}

+ 32
- 0
hw1/task5/README.md 查看文件

@@ -0,0 +1,32 @@
1
+# Homework hw1 task 5
2
+
3
+## Vorbereitungen
4
+
5
+Rufen Sie im `task5/` Verzeichnis: `cargo init --bin` auf. Dadurch wird ein Rust Binary Projekt in `task5/` angelegt. Mit `cargo build` wird die Library erstellt, der Aufruf `cargo run` startet das Programm. Der Aufruf von `cargo test` ruft die UNIT-Tests im `src/main.rs` auf.
6
+
7
+Ausserdem können die korrekten Outputs Ihres Programms auf der Console mit dem Aufruf von `bats tests/output.bats` getestet werden.
8
+
9
+## task
10
+
11
+Schreiben Sie ein Programm, in welchem eine von Ihnen selbst geschriebene Funktion
12
+
13
+```rust
14
+fn is_prime(n: u64) -> bool
15
+```
16
+
17
+genutzt wird, die überprüft, ob eine gegebene Zahl eine Primzahl ist. Die Funktion muss nicht auf Laufzeit optimiert werden.
18
+
19
+Die *main()* Funktion gibt in einer Schleife die Zahlen von 1 bis 30 aus. Die Zahlen, die eine Primzahlt sind werden in der Ausgabe mit einem `*`` Zeichen markiert.
20
+
21
+```
22
+1
23
+2*
24
+3*
25
+4
26
+5*
27
+...
28
+```
29
+
30
+Nutzen Sie die schon vorgegebene Datei `main.rs`!
31
+
32
+Verwenden Sie keine Funktionen aus Bibliotheken dafür, sondern implementieren Sie die Funktion selbst.

+ 40
- 0
hw1/task5/src/main.rs 查看文件

@@ -0,0 +1,40 @@
1
+//! hw01t5: Primzahltest
2
+fn is_prime(n: u64) -> bool {
3
+    unimplemented!();
4
+}
5
+
6
+
7
+fn main() {
8
+    unimplemented!();
9
+}
10
+
11
+#[test]
12
+fn small_primes() {
13
+    assert!(is_prime(2));
14
+    assert!(is_prime(3));
15
+    assert!(is_prime(5));
16
+    assert!(is_prime(7));
17
+}
18
+
19
+#[test]
20
+fn small_composites() {
21
+    assert!(!is_prime(1));
22
+    assert!(!is_prime(4));
23
+    assert!(!is_prime(6));
24
+    assert!(!is_prime(8));
25
+    assert!(!is_prime(9));
26
+}
27
+
28
+#[test]
29
+fn large_primes() {
30
+    assert!(is_prime(1_300_769));
31
+    assert!(is_prime(1_300_297));
32
+    assert!(is_prime(7_367_287));
33
+}
34
+
35
+#[test]
36
+fn large_composites() {
37
+    assert!(!is_prime(908_209));
38
+    assert!(!is_prime(3_073_009));
39
+    assert!(!is_prime(4_897_369));
40
+}

+ 27
- 0
hw1/task5/tests/output.bats 查看文件

@@ -0,0 +1,27 @@
1
+#!/usr/bin/env bats
2
+
3
+
4
+@test "Check that we have a debug output" {
5
+    run stat "$BATS_TEST_DIRNAME/../target/debug/task5"
6
+    [ "$status" -eq 0 ]
7
+}
8
+
9
+@test "Output must be from 1..30 and correct formated" {
10
+    run "$BATS_TEST_DIRNAME/../target/debug/task5"
11
+    [[ "${lines[0]}" =~ "1" ]]
12
+    [[ "${lines[1]}" =~ "2*" ]]
13
+    [[ "${lines[2]}" =~ "3*" ]]
14
+    [[ "${lines[3]}" =~ "4" ]]
15
+    [[ "${lines[4]}" =~ "5" ]]
16
+    [[ "${lines[25]}" =~ "26" ]]
17
+    [[ "${lines[26]}" =~ "27" ]]
18
+    [[ "${lines[27]}" =~ "28" ]]
19
+    [[ "${lines[28]}" =~ "29*" ]]
20
+    [[ "${lines[29]}" =~ "30" ]]
21
+}
22
+
23
+# wc output with white spaces is trimmed by xargs
24
+@test "Output must be exact 30 lines long" {
25
+    run bash -c "'$BATS_TEST_DIRNAME/../target/debug/task5' | wc -l | xargs"
26
+    [ "$output" = "30" ]
27
+}

正在加载...
取消
保存