Joshua Rutschmann 8年前
コミット
890f3e4e4f

+ 4
- 1
.gitignore ファイルの表示

1
 # Generated by Cargo
1
 # Generated by Cargo
2
 # will have compiled files and executables
2
 # will have compiled files and executables
3
-/target/
3
+*/*/target/
4
 
4
 
5
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
5
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6
 # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
6
 # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
10
 **/*.rs.bk
10
 **/*.rs.bk
11
 
11
 
12
 *.swp
12
 *.swp
13
+
14
+# Files generated by IntelliJ IDEA
15
+*.idea

+ 12
- 0
hw6/simu1/ANSWERS.md ファイルの表示

1
+# hw6 - Simulation 1 - Antworten
2
+
3
+1.
4
+    * Da Job 1 so viel mehr Tickets hat, ist es bei der Ausführung durch den Lottery Scheduler viel wahrscheinlicher, dass dieser Job ausgeführt wird.
5
+    * Job 0 wird (zumindest mit `-s 0`) nie ausgeführt, bevor Job 1 fertig ist. Theoretisch könnte es vorkommen, ist jedoch sehr unwahrscheinlich (1/101-tel pro Tick).
6
+    * Eine solch unfaire Ticketverteilung führt zu einem Verhalten des Schedulers, das nicht der Idee der "Lottery" entspricht. Es führt dazu, das ein Job zunächst vollständig ausgeführt wird und anschließend der andere, bzw. zu einer Priorisierung des Jobs mit vielen Tickets. Das Verhalten wird dadurch ähnlich zu Schedulern wie z.B. FIFO.
7
+
8
+2. Der Scheduler ist sehr fair bei einer Joblänge von 100. Mit `-s 1` ist die Fairness `196/200 = 0,98`, mit `-s 2` liegt sie bei `190/200 = 0,95`, mit `-s 3` bei `196/200 = 0,98`, mit `-s 4` bei `199/200 = 0,995` und mit `-s 5` bei `181/200 = 0,905`. Im Durchschnitt (unter Verwendung dieser 5 Seeds) ist das eine Fairness von `0,962`, was sehr nahe an der angestrebten Fairness von `1,0` liegt.
9
+
10
+3. Mit `-q 10` und den Seeds 1-5 ergeben sich folgende Fairness-Werte: `-s 1` und `-s 5`: `160/200 = 0,8`, `-s 2`, `-s 3` und `-s 4`: `190/200 = `0,95`. Die durchschnittliche Fairness liegt damit bei `0,92`, was deutlich schlechter als mit kürzerer Quantumzeit ist. Je größer die Quantumzeit dabei wird, desto schlechter ist auch die Fairness. Beispielsweise ergibt sich mit den selben Seeds, jedoch mit `-q 100` nur noch eine durchschnittliche Fairness von `0,5`.
11
+
12
+4. Mit einem Stride Scheduler wäre die Fairness immer 100%, da beide Jobs die selbe Länge haben und somit immer abwechselnd ausgeführt würden. Der Graph wäre somit konstant auf 1.0.

+ 27
- 16
hw6/task1/src/main.rs ファイルの表示

4
 extern crate nix;
4
 extern crate nix;
5
 
5
 
6
 use nix::unistd::{fork, pipe, read, write};
6
 use nix::unistd::{fork, pipe, read, write};
7
-use nix::sys::wait::wait;
7
+use nix::sys::wait::{wait, WaitStatus};
8
 use std::str;
8
 use std::str;
9
-use nix::sys::wait::WaitStatus;
10
 use nix::unistd::ForkResult::{Child, Parent};
9
 use nix::unistd::ForkResult::{Child, Parent};
11
 use std::os::unix::io::RawFd;
10
 use std::os::unix::io::RawFd;
12
 
11
 
12
+mod unit_test_pipe;
13
+
13
 const BUFFER_SIZE: usize = 256;
14
 const BUFFER_SIZE: usize = 256;
14
 
15
 
15
 
16
 
33
                                 Ok(Child) => {
34
                                 Ok(Child) => {
34
                                     match sum_strings(vec) {
35
                                     match sum_strings(vec) {
35
                                         Ok(res) => println!("Sum = {}", res),
36
                                         Ok(res) => println!("Sum = {}", res),
36
-                                        Err(e) => println!("{}", e),
37
+                                        Err(e) => {
38
+                                            println!("{}", e);
39
+                                            process::exit(1);
40
+                                        }
37
                                     }
41
                                     }
38
                                 }
42
                                 }
39
                                 Ok(Parent { .. }) => {
43
                                 Ok(Parent { .. }) => {
40
                                     if let Ok(ws) = wait() {
44
                                     if let Ok(ws) = wait() {
41
-                                        if let WaitStatus::Exited(_, _) = ws {
45
+                                        if let WaitStatus::Exited(_, exit_code) = ws {
42
                                             match mul_strings(vec) {
46
                                             match mul_strings(vec) {
43
                                                 Ok(res) => println!("Mul = {}", res),
47
                                                 Ok(res) => println!("Mul = {}", res),
44
-                                                Err(e) => println!("{}", e),
48
+                                                Err(e) => {
49
+                                                    println!("{}", e);
50
+                                                    process::exit(1);
51
+                                                }
45
                                             }
52
                                             }
53
+                                            process::exit(exit_code as i32);
46
                                         }
54
                                         }
47
                                     }
55
                                     }
48
                                 }
56
                                 }
59
                     for s in numbers {
67
                     for s in numbers {
60
                         args = concatenate_strings(&args, &concatenate_strings(&s, " "));
68
                         args = concatenate_strings(&args, &concatenate_strings(&s, " "));
61
                     }
69
                     }
62
-                    println!("sending to children: {}", args);
70
+                    println!("sending to childs: {}", args);
71
+
63
                     if let Err(_) = write(writer, args.as_bytes()) {
72
                     if let Err(_) = write(writer, args.as_bytes()) {
64
                         println!("Broken pipe")
73
                         println!("Broken pipe")
65
                     }
74
                     }
66
 
75
 
67
-                    if let Err(_) = wait() {
68
-                        println!("Waiting on children failed")
76
+                    if let Ok(ws) = wait() {
77
+                        if let WaitStatus::Exited(_, exit_code) = ws {
78
+                            process::exit(exit_code as i32);
79
+                        }
69
                     }
80
                     }
70
                 }
81
                 }
71
 
82
 
106
 }
117
 }
107
 
118
 
108
 /// Calculates the sum of the given Strings and returns them as a Result.
119
 /// Calculates the sum of the given Strings and returns them as a Result.
109
-fn sum_strings(v: Vec<String>) -> Result<i32, String> {
110
-    let mut sum = 0;
120
+fn sum_strings(v: Vec<String>) -> Result<i64, String> {
121
+    let mut sum: i64 = 0;
111
     for x in v {
122
     for x in v {
112
-        match x.parse::<i32>() {
123
+        match x.parse::<i64>() {
113
             Ok(val) => {
124
             Ok(val) => {
114
-                match i32::checked_add(sum, val) {
125
+                match i64::checked_add(sum, val) {
115
                     Some(y) => {
126
                     Some(y) => {
116
                         sum = y;
127
                         sum = y;
117
                     }
128
                     }
125
 }
136
 }
126
 
137
 
127
 /// Calculates the product of the given Strings and returns them as a Result.
138
 /// Calculates the product of the given Strings and returns them as a Result.
128
-fn mul_strings(v: Vec<String>) -> Result<i32, String> {
129
-    let mut prod = 1;
139
+fn mul_strings(v: Vec<String>) -> Result<i64, String> {
140
+    let mut prod: i64 = 1;
130
     for x in v {
141
     for x in v {
131
-        match x.parse::<i32>() {
142
+        match x.parse::<i64>() {
132
             Ok(val) => {
143
             Ok(val) => {
133
-                match i32::checked_mul(prod, val) {
144
+                match i64::checked_mul(prod, val) {
134
                     Some(y) => {
145
                     Some(y) => {
135
                         prod = y;
146
                         prod = y;
136
                     }
147
                     }

+ 24
- 0
hw6/task1/src/unit_test_pipe.rs ファイルの表示

1
+#[cfg(test)]
2
+mod test {
3
+    use read_from_pipe;
4
+    use nix::unistd::{pipe, write};
5
+
6
+    #[test]
7
+    fn test_pipe() {
8
+        match pipe() {
9
+            Ok((reader, writer)) => {
10
+                let input = b"teststring";
11
+
12
+                if let Err(_) = write(writer, input) {
13
+                    // Broken pipe
14
+                }
15
+                assert_eq!(read_from_pipe(reader).unwrap(), "teststring".to_string());
16
+            }
17
+            Err(_) => {}
18
+        }
19
+
20
+    }
21
+
22
+    #[test]
23
+    fn test_kill_last_child() {}
24
+}

+ 5
- 1
hw6/task2/src/command.rs ファイルの表示

2
 use std::str::FromStr;
2
 use std::str::FromStr;
3
 use std::env;
3
 use std::env;
4
 
4
 
5
+#[derive(PartialEq, Debug)]
5
 pub enum Command {
6
 pub enum Command {
6
     Empty,
7
     Empty,
7
     Exit,
8
     Exit,
8
     Cd(Option<OsString>),
9
     Cd(Option<OsString>),
9
 }
10
 }
10
 
11
 
12
+#[derive(PartialEq, Debug)]
11
 pub struct CommandNotFoundError;
13
 pub struct CommandNotFoundError;
12
 
14
 
13
 impl FromStr for Command {
15
 impl FromStr for Command {
31
 
33
 
32
 
34
 
33
 impl Command {
35
 impl Command {
34
-    /// If the passed String exists, set the path of the Cd in the enum
36
+    /// If the passed String exists, set the path of the Cd in the enum (as OsString)
37
+    /// Returns **Command**
35
     pub fn parse_cd(cmd: Option<&str>) -> Self {
38
     pub fn parse_cd(cmd: Option<&str>) -> Self {
36
         match cmd {
39
         match cmd {
37
             None => Command::Cd(None),
40
             None => Command::Cd(None),
39
         }
42
         }
40
     }
43
     }
41
 
44
 
45
+    /// If this instance is of Kind **Command::Cd** either go to HOME or navigate to the given path
42
     pub fn exec_cd(&self) {
46
     pub fn exec_cd(&self) {
43
         if let Command::Cd(None) = *self {
47
         if let Command::Cd(None) = *self {
44
             let possible_home = env::home_dir();
48
             let possible_home = env::home_dir();

+ 4
- 5
hw6/task2/src/main.rs ファイルの表示

1
 use std::process;
1
 use std::process;
2
-use shell::{Shell, R, W};
2
+use shell::Shell;
3
 use std::io;
3
 use std::io;
4
 
4
 
5
+mod unit_tests_shell;
5
 mod command;
6
 mod command;
6
 mod shell;
7
 mod shell;
7
 
8
 
8
 
9
 
10
+
9
 fn main() {
11
 fn main() {
10
     let stdin = io::stdin();
12
     let stdin = io::stdin();
11
-    let input = R(stdin.lock());
12
-
13
     let stdout = io::stdout();
13
     let stdout = io::stdout();
14
-    let output = W(stdout.lock());
15
 
14
 
16
-    let mut s = Shell::new(input, output, "schell".to_string());
15
+    let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
17
     match s.start() {
16
     match s.start() {
18
         Ok(_) => process::exit(0),
17
         Ok(_) => process::exit(0),
19
         Err(_) => process::exit(1),
18
         Err(_) => process::exit(1),

+ 8
- 46
hw6/task2/src/shell.rs ファイルの表示

1
-use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
2
-use std::io;
3
-
1
+use std::io::{BufRead, Write};
4
 use command::*;
2
 use command::*;
5
 use std::str::FromStr;
3
 use std::str::FromStr;
6
 use std::env;
4
 use std::env;
7
 
5
 
8
-///Tuple-Structs which hold Std-in and -out locks.
9
-pub struct R<'a>(pub StdinLock<'a>);
10
-pub struct W<'a>(pub StdoutLock<'a>);
11
-
12
-pub struct Shell<R, W> {
6
+pub struct Shell<R: BufRead, W: Write> {
13
     pub reader: R,
7
     pub reader: R,
14
     pub writer: W,
8
     pub writer: W,
15
     pub should_exit: bool,
9
     pub should_exit: bool,
16
     pub name: String,
10
     pub name: String,
17
 }
11
 }
18
 
12
 
19
-impl<'a> Shell<R<'a>, W<'a>> {
13
+impl<R: BufRead, W: Write> Shell<R, W> {
20
     /// Creates a new Shell with a name, input and output.
14
     /// Creates a new Shell with a name, input and output.
21
-    pub fn new(input: R<'a>, output: W<'a>, name: String) -> Self {
15
+    pub fn new(input: R, output: W, name: String) -> Self {
22
         Shell {
16
         Shell {
23
             reader: input,
17
             reader: input,
24
             writer: output,
18
             writer: output,
37
     /// If the Command-creation succeeds, run the command.
31
     /// If the Command-creation succeeds, run the command.
38
     fn shell_loop(&mut self) -> Result<(), &str> {
32
     fn shell_loop(&mut self) -> Result<(), &str> {
39
         while !self.should_exit {
33
         while !self.should_exit {
40
-            if let Ok(line) = self.prompt() {
34
+            if let Ok(Some(line)) = self.prompt() {
41
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
35
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
42
             }
36
             }
43
         }
37
         }
46
 
40
 
47
     /// Prints the shell prompt.
41
     /// Prints the shell prompt.
48
     /// Waits for user input and returns the read line.
42
     /// Waits for user input and returns the read line.
49
-    fn prompt(&mut self) -> Result<String, &str> {
43
+    pub fn prompt(&mut self) -> Result<Option<String>, &str> {
50
         match env::current_dir() {
44
         match env::current_dir() {
51
             Ok(pwd) => {
45
             Ok(pwd) => {
52
                 let _ = self.writer.write(
46
                 let _ = self.writer.write(
58
                 let mut line: String = String::new();
52
                 let mut line: String = String::new();
59
                 let read_result = self.reader.read_line(&mut line);
53
                 let read_result = self.reader.read_line(&mut line);
60
                 match read_result {
54
                 match read_result {
61
-                    Ok(_) => Ok(line),
62
-                    Err(_) => Err("Error reading."),
55
+                    Ok(_) => Ok(Some(line)),
56
+                    Err(_) => Ok(None),
63
                 }
57
                 }
64
             }
58
             }
65
             Err(_) => return Err("Path Error"),
59
             Err(_) => return Err("Path Error"),
80
         Ok(())
74
         Ok(())
81
     }
75
     }
82
 }
76
 }
83
-
84
-/// Implement Read-Trait for Tuple-Struct R
85
-/// Simply calls `read` of StdinLock
86
-impl<'a> Read for R<'a> {
87
-    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
88
-        self.0.read(buf)
89
-    }
90
-}
91
-
92
-/// Implement BufRead-Trait for Tuple-Struct R
93
-/// Simply calls `fill_buff` and `consume` from StdinLock
94
-impl<'a> BufRead for R<'a> {
95
-    fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
96
-        self.0.fill_buf()
97
-    }
98
-
99
-    fn consume(&mut self, amt: usize) {
100
-        self.0.consume(amt)
101
-    }
102
-}
103
-
104
-/// Implement Write-Trait for Tuple-Struct W
105
-/// Simply calls `write` and `flush` from StdoutLock
106
-impl<'a> Write for W<'a> {
107
-    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
108
-        self.0.write(buf)
109
-    }
110
-
111
-    fn flush(&mut self) -> Result<(), io::Error> {
112
-        self.0.flush()
113
-    }
114
-}

+ 41
- 1
hw6/task2/src/unit_tests_shell.rs ファイルの表示

1
 #[cfg(test)]
1
 #[cfg(test)]
2
 mod test {
2
 mod test {
3
-    use shell::Shell;
3
+    pub use shell::Shell;
4
+    use command::Command;
5
+    use command::CommandNotFoundError;
6
+    use std::str::FromStr;
7
+    use std::ffi::OsString;
8
+
9
+    #[test]
10
+    fn test_command_empty_whitespace() {
11
+        assert_eq!(Command::from_str("       ").unwrap(), Command::Empty);
12
+    }
13
+
14
+    #[test]
15
+    fn test_command_empty_tab() {
16
+        assert_eq!(Command::from_str("\t").unwrap(), Command::Empty);
17
+    }
18
+
19
+    #[test]
20
+    fn test_command_cd() {
21
+        assert_eq!(
22
+            Command::from_str("cd /home/peter/").unwrap(),
23
+            Command::Cd(Some(OsString::from("/home/peter/")))
24
+        );
25
+    }
26
+
27
+    #[test]
28
+    fn test_command_home() {
29
+        assert_eq!(Command::from_str("cd").unwrap(), Command::Cd(None));
30
+    }
31
+
32
+    #[test]
33
+    fn test_command_exit() {
34
+        assert_eq!(Command::from_str("exit").unwrap(), Command::Exit);
35
+    }
36
+
37
+    #[test]
38
+    fn test_command_not_found() {
39
+        assert_eq!(
40
+            Command::from_str("awdeiu33we").unwrap_err(),
41
+            CommandNotFoundError
42
+        );
43
+    }
4
 
44
 
5
     #[test]
45
     #[test]
6
     fn test_prompt_in_memory_with_string() {
46
     fn test_prompt_in_memory_with_string() {

読み込み中…
キャンセル
保存