浏览代码

Merge remote-tracking branch 'origin/hw7' into hw7

Lorenz 7 年前
父节点
当前提交
31528a103f
共有 7 个文件被更改,包括 79 次插入51 次删除
  1. 22
    2
      hw7/simu1/ANSWERS.md
  2. 2
    1
      hw7/task1/src/hash256.rs
  3. 2
    0
      hw7/task1/src/main.rs
  4. 7
    0
      hw7/task2/src/errortype.rs
  5. 42
    46
      hw7/task2/src/lib.rs
  6. 4
    0
      hw7/task2/src/main.rs
  7. 0
    2
      hw7/task2/src/shellerror.rs

+ 22
- 2
hw7/simu1/ANSWERS.md 查看文件

@@ -17,6 +17,26 @@
17 17
 
18 18
 Hier wird der Lock durch das Vertauschen des Wertes in `mutex` mit dem Register `ax` gesetzt. Aufgehoben wird der Lock, in dem eine `0` in die Mutex-Variable (`mutex`) geschrieben wird.
19 19
 
20
-1. Das Programm liefert nun immer den erwarteten Wert. Sowohl mit `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -i 1 -a ax=40:bx=40,ax=40:bx=40` als auch mit nur `-i 1000` steht am Ende der Wert `80` in `count`.
20
+1. Das Programm liefert nun immer den erwarteten Wert. Sowohl mit `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -i 1 -a bx=40,bx=40` als auch mit nur `-i 1000` steht am Ende der Wert `80` in `count`.
21 21
 
22
-2. Die mit der Flag `-P` ausgeführten Tests laufen fehlerfrei. Beispielsweise liefern `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5 -P 0011` und `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5 -P 001000000000001` beide das erwartete Ergebnis (`10`).
22
+### `peterson.s`
23
+
24
+1. Trotz unterschiedlicher Interruptfrequenzen (`-i 1`, `-i 5`, `-i 10`, `-i 20`...) funktioniert der Code fehlerfrei.
25
+
26
+2. Mit beispielsweise `./x86.py -p peterson.s -M count,flag,turn -R ax,bx,cx,fx -a ax=5:bx=0,ax=5:bx=1 -P 11111111000000001000111111111111111` lassen sich mögliche Race Conditions ausschließen, da zwischen dem Testen auf einen Wert und dem zugehörigen Sprung jeweils ein Interrupt stattfindet. Das Endergebnis bleibt davon jedoch unbeeinflusst, was auf fehlerfreien Code schließen lässt.
27
+
28
+### `ticket.s`
29
+
30
+1. Die Wartezeit der Threads ist abhängig von der Interrupt-Häufigkeit. Wenn nur selten ein Interrupt stattfindet, beispielsweise mit `-i 10000`, hängen die einzelnen Threads sehr lange in der `.aquire`-Schleife fest.
31
+
32
+2. Eine größere Threadzahl macht im Gegensatz zur Interrupthäufigkeit keinen Unterschied. Die einzelnen Threads warten zwar dennoch länger, das liegt jedoch daran, dass mehr Tickets vergeben wurden und somit die Wartezeit auch höher ist.
33
+
34
+### `yield.s`
35
+
36
+1. Beim Aufruf von `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5` bzw. `./x86.py -p yield.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5` ist der Unterschied deutlich zu merken. Der zweite Thread hängt in `test-and-set.s` in einer Schleife beim holen des Locks, und loopt bis zum nächsten Interrupt. `yield.s` tut hier was es soll, und spart somit ca. 50 Zyklen (bzw. etwas weniger als die Interruptrate). Die Einsparung von Zyklen tritt immer dann auf, wenn Thread 1 den Lock hat, dann ein Interrupt kommt und Thread 2 auf den Lock warten muss. Mit `test-and-set.s` wird in diesem Fall ewig geloopt, mit `yield.s` wird die CPU direkt wieder für den ersten Thread freigegeben.
37
+
38
+### `test-and-test-and-set.s`
39
+
40
+1. Dieser Lock tut dasselbe wie in `test-and-set.s`, nur wird beim holen des Locks ein zweiter Test durchgeführt.
41
+
42
+2. Im Vergleich mit `test-and-set.s` muss mit dieser Konfiguration kein atomarer Tausch der Werte in `%ax` und `mutex` ausgeführt werden, wenn der mutex nicht sowieso frei ist. Nur wenn der mutex auch verfügbar ist, wird dieser Tausch durchgeführt.

+ 2
- 1
hw7/task1/src/hash256.rs 查看文件

@@ -1,12 +1,13 @@
1 1
 use hasher_sha256::{Hasher, HashResult};
2 2
 use hasher_sha256::Sha256;
3 3
 
4
-
4
+/// Dieser Datentyp beschreibt die Lösung des Hashverfahrens.
5 5
 pub struct Solution {
6 6
     pub number: usize,
7 7
     pub hash: String,
8 8
 }
9 9
 
10
+/// `verify_product` dient der Verifikation eines gefundenen Hashes.
10 11
 pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option<Solution> {
11 12
     let sol = base * number;
12 13
     let input = sol.to_string();

+ 2
- 0
hw7/task1/src/main.rs 查看文件

@@ -7,6 +7,7 @@ use std::process;
7 7
 mod hasher_sha256;
8 8
 mod hash256;
9 9
 
10
+/// Hauptfunktion zum Starten des Hashers.
10 11
 pub fn main() {
11 12
     let matches = create_app().get_matches();
12 13
     let base = matches.value_of("base").unwrap_or("1");
@@ -54,6 +55,7 @@ pub fn main() {
54 55
     };
55 56
 }
56 57
 
58
+/// Diese Funktion dient der Konfiguration der App mit dem Paket **Clap**.
57 59
 fn create_app<'a, 'b>() -> App<'a, 'b> {
58 60
     App::new("Hash256")
59 61
         .version("1.0")

+ 7
- 0
hw7/task2/src/errortype.rs 查看文件

@@ -0,0 +1,7 @@
1
+/// Dieser Datentyp beschreibt die in der Shell auftretenden Fehler.
2
+#[derive(Debug, PartialEq)]
3
+pub enum ErrorType {
4
+    PathError,
5
+    BrokenPipeError,
6
+    ForkError,
7
+}

+ 42
- 46
hw7/task2/src/lib.rs 查看文件

@@ -3,18 +3,14 @@ extern crate nix;
3 3
 use std::io::{BufRead, Write};
4 4
 use std::str::FromStr;
5 5
 use std::env;
6
-use std::str::Split;
7
-use std::os::unix::io::RawFd;
8 6
 use std::ffi::{OsString, CString};
9 7
 use nix::unistd::ForkResult::{Child, Parent};
10
-use nix::sys::wait::{wait, WaitStatus};
11
-use nix::unistd::dup2;
12
-use nix::unistd::close;
13
-use nix::unistd::{execvp, fork, pipe, read, write};
8
+use nix::sys::wait::wait;
9
+use nix::unistd::{dup2, close, execvp, fork, pipe};
14 10
 
15
-mod shellerror;
11
+mod errortype;
16 12
 
17
-use shellerror::ShellError;
13
+use errortype::ErrorType;
18 14
 
19 15
 #[derive(PartialEq, Debug)]
20 16
 pub enum Command {
@@ -25,7 +21,7 @@ pub enum Command {
25 21
 }
26 22
 
27 23
 impl FromStr for Command {
28
-    type Err = ShellError;
24
+    type Err = ErrorType;
29 25
     fn from_str(s: &str) -> Result<Self, Self::Err> {
30 26
 
31 27
         let mut parts = s.split_whitespace();
@@ -93,14 +89,14 @@ impl<R: BufRead, W: Write> Shell<R, W> {
93 89
     }
94 90
     /// Initializes the Shell Loop.
95 91
     /// Starts the shell.
96
-    pub fn start(&mut self) -> Result<(), &str> {
92
+    pub fn start(&mut self) -> Result<(), ErrorType> {
97 93
         self.shell_loop()
98 94
     }
99 95
 
100 96
     /// Loops while exit hasn't been called.
101 97
     /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
102 98
     /// If the Command-creation succeeds, run the command.
103
-    fn shell_loop(&mut self) -> Result<(), &str> {
99
+    fn shell_loop(&mut self) -> Result<(), ErrorType> {
104 100
         while !self.should_exit {
105 101
             if let Ok(Some(line)) = self.prompt() {
106 102
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
@@ -111,7 +107,7 @@ impl<R: BufRead, W: Write> Shell<R, W> {
111 107
 
112 108
     /// Prints the shell prompt.
113 109
     /// Waits for user input and returns the read line.
114
-    pub fn prompt(&mut self) -> Result<Option<String>, &str> {
110
+    pub fn prompt(&mut self) -> Result<Option<String>, ErrorType> {
115 111
         match env::current_dir() {
116 112
             Ok(pwd) => {
117 113
                 let _ = self.writer.write(
@@ -127,61 +123,61 @@ impl<R: BufRead, W: Write> Shell<R, W> {
127 123
                     Err(_) => Ok(None),
128 124
                 }
129 125
             }
130
-            Err(_) => return Err("Path Error"),
126
+            Err(_) => return Err(ErrorType::PathError),
131 127
         }
132 128
     }
133 129
 
134 130
     /// Runs a command.
135 131
     /// Currently only `cd` and `exit` are working.
136
-    fn run(&mut self, command: Command) -> Result<(), ShellError> {
132
+    fn run(&mut self, command: Command) -> Result<(), ErrorType> {
137 133
 
138 134
         match command {
139 135
             Command::Empty => {},
140 136
             Command::Program(cmd) => {
141 137
 
142
-                let mut commands = cmd.split('|');
138
+                let commands = cmd.split('|');
143 139
                 let commands_vec: Vec<&str> = commands.collect();
144
-                
140
+
145 141
                 let needs_pipe = commands_vec.len() == 2;
146 142
 
147
-                if let Ok((reader, writer)) = pipe() {
148 143
 
149 144
                     let fi = fork();
150 145
                     match fi {
151
-                        Ok(Parent { .. }) => {
152
-                            wait();
153
-                        }
154
-                        Ok(Child) => {
155
-                            if let Some(first) = commands_vec.get(0) {
156
-                                if needs_pipe {
157
-                                    close(reader).unwrap();
158
-                                    dup2(writer, 1).unwrap();
159
-                                }
160
-                                self.execute(first);
161
-                            }
162
-                        }
163
-                        Err(_) => println!("Fatal error: Fork failed"),
164
-                    }
165
-
146
+                        Ok(Parent { child: _child }) => {
147
+                            let _ = wait();
166 148
 
167
-                    let sec = fork();
168
-                    match sec {
169
-                        Ok(Parent { .. }) => {
170
-                            wait();
171 149
                         }
172 150
                         Ok(Child) => {
173
-                            if let Some(second) = commands_vec.get(1) {
174
-                                close(1).unwrap();
175
-                                close(writer).unwrap();
176
-                                dup2(reader, 0).unwrap();
177
-                                self.execute(second);
151
+                            if let Ok((reader, writer)) = pipe() {
152
+                                let sec = fork();
153
+                                match sec {
154
+                                    Ok(Parent { child: _child }) => {
155
+                                        let _ = wait();
156
+                                        if let Some(second) = commands_vec.get(1) {
157
+                                            match close(writer) {
158
+                                                Ok(_) => {},
159
+                                                Err(_) => return Err(ErrorType::BrokenPipeError),
160
+                                            }
161
+                                            dup2(reader, 0).unwrap();
162
+                                            self.execute(second);
163
+                                        }
164
+                                    }
165
+                                    Ok(Child) => {
166
+                                        if let Some(first) = commands_vec.get(0) {
167
+                                            if needs_pipe {
168
+                                                close(reader).unwrap();
169
+                                                dup2(writer, 1).unwrap();
170
+                                            }
171
+                                            self.execute(first);
172
+                                        }
173
+                                    }
174
+                                    Err(_) => return Err(ErrorType::ForkError),
175
+                                }
178 176
                             }
179 177
                         }
180
-                        Err(_) => println!("Fatal error: Fork failed"),
178
+                        Err(_) => return Err(ErrorType::ForkError),
181 179
                     }
182 180
 
183
-                }
184
-
185 181
             },
186 182
             Command::Exit => self.should_exit = true,
187 183
             Command::Cd(_) => {
@@ -192,11 +188,11 @@ impl<R: BufRead, W: Write> Shell<R, W> {
192 188
     }
193 189
 
194 190
     fn execute(&self, cmd: &str){
195
-        let mut parts:Vec<&str> = cmd.split_whitespace().collect();
191
+        let parts:Vec<&str> = cmd.split_whitespace().collect();
196 192
         let args:Vec<CString> = parts.iter().map(|f| CString::new(*f).unwrap()).collect();
197 193
         let t = args.into_boxed_slice();
198 194
 
199
-        execvp(&t[0], &t);
195
+        execvp(&t[0], &t).unwrap();
200 196
     }
201 197
 }
202 198
 

+ 4
- 0
hw7/task2/src/main.rs 查看文件

@@ -4,11 +4,15 @@ use std::process;
4 4
 use std::io;
5 5
 use task2::Shell;
6 6
 
7
+
8
+/// Diese Funktion startet die Shell durch Aufruf
9
+/// von `Shell::new()`.
7 10
 fn main() {
8 11
     let stdin = io::stdin();
9 12
     let stdout = io::stdout();
10 13
 
11 14
     let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
15
+    // Kontrolliertes bzw. unkontrolliertes Beenden der Shell
12 16
     match s.start() {
13 17
         Ok(_) => process::exit(0),
14 18
         Err(_) => process::exit(1),

+ 0
- 2
hw7/task2/src/shellerror.rs 查看文件

@@ -1,2 +0,0 @@
1
-#[derive(PartialEq, Debug)]
2
-pub struct ShellError;

正在加载...
取消
保存