Joshua Rutschmann 8 anni fa
parent
commit
890f3e4e4f

+ 4
- 1
.gitignore Vedi File

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

+ 12
- 0
hw6/simu1/ANSWERS.md Vedi File

@@ -0,0 +1,12 @@
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 Vedi File

@@ -4,12 +4,13 @@ use std::process;
4 4
 extern crate nix;
5 5
 
6 6
 use nix::unistd::{fork, pipe, read, write};
7
-use nix::sys::wait::wait;
7
+use nix::sys::wait::{wait, WaitStatus};
8 8
 use std::str;
9
-use nix::sys::wait::WaitStatus;
10 9
 use nix::unistd::ForkResult::{Child, Parent};
11 10
 use std::os::unix::io::RawFd;
12 11
 
12
+mod unit_test_pipe;
13
+
13 14
 const BUFFER_SIZE: usize = 256;
14 15
 
15 16
 
@@ -33,16 +34,23 @@ fn main() {
33 34
                                 Ok(Child) => {
34 35
                                     match sum_strings(vec) {
35 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 43
                                 Ok(Parent { .. }) => {
40 44
                                     if let Ok(ws) = wait() {
41
-                                        if let WaitStatus::Exited(_, _) = ws {
45
+                                        if let WaitStatus::Exited(_, exit_code) = ws {
42 46
                                             match mul_strings(vec) {
43 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,13 +67,16 @@ fn main() {
59 67
                     for s in numbers {
60 68
                         args = concatenate_strings(&args, &concatenate_strings(&s, " "));
61 69
                     }
62
-                    println!("sending to children: {}", args);
70
+                    println!("sending to childs: {}", args);
71
+
63 72
                     if let Err(_) = write(writer, args.as_bytes()) {
64 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,12 +117,12 @@ fn split_into_strings<'a>(s1: &'a str) -> Vec<String> {
106 117
 }
107 118
 
108 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 122
     for x in v {
112
-        match x.parse::<i32>() {
123
+        match x.parse::<i64>() {
113 124
             Ok(val) => {
114
-                match i32::checked_add(sum, val) {
125
+                match i64::checked_add(sum, val) {
115 126
                     Some(y) => {
116 127
                         sum = y;
117 128
                     }
@@ -125,12 +136,12 @@ fn sum_strings(v: Vec<String>) -> Result<i32, String> {
125 136
 }
126 137
 
127 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 141
     for x in v {
131
-        match x.parse::<i32>() {
142
+        match x.parse::<i64>() {
132 143
             Ok(val) => {
133
-                match i32::checked_mul(prod, val) {
144
+                match i64::checked_mul(prod, val) {
134 145
                     Some(y) => {
135 146
                         prod = y;
136 147
                     }

+ 24
- 0
hw6/task1/src/unit_test_pipe.rs Vedi File

@@ -0,0 +1,24 @@
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 Vedi File

@@ -2,12 +2,14 @@ use std::ffi::OsString;
2 2
 use std::str::FromStr;
3 3
 use std::env;
4 4
 
5
+#[derive(PartialEq, Debug)]
5 6
 pub enum Command {
6 7
     Empty,
7 8
     Exit,
8 9
     Cd(Option<OsString>),
9 10
 }
10 11
 
12
+#[derive(PartialEq, Debug)]
11 13
 pub struct CommandNotFoundError;
12 14
 
13 15
 impl FromStr for Command {
@@ -31,7 +33,8 @@ impl FromStr for Command {
31 33
 
32 34
 
33 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 38
     pub fn parse_cd(cmd: Option<&str>) -> Self {
36 39
         match cmd {
37 40
             None => Command::Cd(None),
@@ -39,6 +42,7 @@ impl Command {
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 46
     pub fn exec_cd(&self) {
43 47
         if let Command::Cd(None) = *self {
44 48
             let possible_home = env::home_dir();

+ 4
- 5
hw6/task2/src/main.rs Vedi File

@@ -1,19 +1,18 @@
1 1
 use std::process;
2
-use shell::{Shell, R, W};
2
+use shell::Shell;
3 3
 use std::io;
4 4
 
5
+mod unit_tests_shell;
5 6
 mod command;
6 7
 mod shell;
7 8
 
8 9
 
10
+
9 11
 fn main() {
10 12
     let stdin = io::stdin();
11
-    let input = R(stdin.lock());
12
-
13 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 16
     match s.start() {
18 17
         Ok(_) => process::exit(0),
19 18
         Err(_) => process::exit(1),

+ 8
- 46
hw6/task2/src/shell.rs Vedi File

@@ -1,24 +1,18 @@
1
-use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
2
-use std::io;
3
-
1
+use std::io::{BufRead, Write};
4 2
 use command::*;
5 3
 use std::str::FromStr;
6 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 7
     pub reader: R,
14 8
     pub writer: W,
15 9
     pub should_exit: bool,
16 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 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 16
         Shell {
23 17
             reader: input,
24 18
             writer: output,
@@ -37,7 +31,7 @@ impl<'a> Shell<R<'a>, W<'a>> {
37 31
     /// If the Command-creation succeeds, run the command.
38 32
     fn shell_loop(&mut self) -> Result<(), &str> {
39 33
         while !self.should_exit {
40
-            if let Ok(line) = self.prompt() {
34
+            if let Ok(Some(line)) = self.prompt() {
41 35
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
42 36
             }
43 37
         }
@@ -46,7 +40,7 @@ impl<'a> Shell<R<'a>, W<'a>> {
46 40
 
47 41
     /// Prints the shell prompt.
48 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 44
         match env::current_dir() {
51 45
             Ok(pwd) => {
52 46
                 let _ = self.writer.write(
@@ -58,8 +52,8 @@ impl<'a> Shell<R<'a>, W<'a>> {
58 52
                 let mut line: String = String::new();
59 53
                 let read_result = self.reader.read_line(&mut line);
60 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 59
             Err(_) => return Err("Path Error"),
@@ -80,35 +74,3 @@ impl<'a> Shell<R<'a>, W<'a>> {
80 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 Vedi File

@@ -1,6 +1,46 @@
1 1
 #[cfg(test)]
2 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 45
     #[test]
6 46
     fn test_prompt_in_memory_with_string() {

Loading…
Annulla
Salva