diff --git a/WEEK-7/questions.md b/WEEK-7/questions.md new file mode 100644 index 0000000000000000000000000000000000000000..bcd0449acff15b840857cb24e21a4366b1f53340 --- /dev/null +++ b/WEEK-7/questions.md @@ -0,0 +1,36 @@ +1. Your shell forks multiple child processes when executing piped commands. How does your implementation ensure that all child processes complete before the shell continues accepting user input? What would happen if you forgot to call waitpid() on all child processes? + +---> By invoking waitpid() on each child process, our shell makes sure that every child process is finished before moving on. +The parent process uses waitpid() in a loop to wait for each child process to finish once a process is forked, keeping track of all child process IDs (pids[]). + +If we fail to invoke waitpid() for every child process: + +Process IDs (PIDs) of the child processes will stay in the process table as "zombies" even after they have completed their execution because the parent shell has not gathered their exit status. +Resource Leak: System resources may run out if an excessive number of zombie processes build up. +Shell Accepting Input Too Early: Unexpected behavior may result if the shell begins reading the subsequent command while child processes are still active. + +2. The dup2() function is used to redirect input and output file descriptors. Explain why it is necessary to close unused pipe ends after calling dup2(). What could go wrong if you leave pipes open? + +---> By duplicating a file descriptor, the dup2() function essentially reroutes standard input or output to a pipe. To avoid problems, it is essential to shut the original pipe ends after completing the redirection. + +The operating system limits the amount of open file descriptors, and leaving superfluous ones open will eventually exhaust system resources. This is why leaving unused pipe ends open can result in file descriptor exhaustion. + + Deadlocks can also occur when pipes are not closed; if a process keeps reading from a pipe but the writing end is left open, it might never get an EOF signal, which would leave it hanging endlessly while it awaits input. + +Additionally, by disrupting the normal flow of inter-process communication, open pipes can damage data and provide unexpected or inconsistent outcomes. Deadlocks are avoided, dependable communication between processes is maintained, and effective resource management is ensured by appropriately closing unused pipe ends. + +3. Your shell recognizes built-in commands (cd, exit, dragon). Unlike external commands, built-in commands do not require execvp(). Why is cd implemented as a built-in rather than an external command? What challenges would arise if cd were implemented as an external process? + +---> The shell's current working directory can be changed with the cd (change directory) command. Running cd as an external command in a child process would not accomplish the desired result because every process keeps its own working directory. + +Only the working directory of that process would change if cd were run in a different process; the directory of the parent shell would stay the same. Furthermore, any directory changes performed by the child process would be erased at its termination, rendering CD useless for shell session navigation. + +Efficiency is another significant issue; changing the working directory just requires starting a new process, which is pointless and inefficient when the change may be implemented directly within the shell process. + +4. Currently, your shell supports a fixed number of piped commands (CMD_MAX). How would you modify your implementation to allow an arbitrary number of piped commands while still handling memory allocation efficiently? What trade-offs would you need to consider? + +---> The shell currently limits the flexibility of executing complicated command pipelines by imposing a preset limit on the number of piped commands. We might utilize dynamically growing arrays (`realloc()`) or linked lists in place of fixed-size arrays to enable dynamic allocation of instructions. We may eliminate arbitrary restrictions and increase the shell's versatility by dynamically allocating memory for each command and growing the command buffer as more commands are entered. Every strategy, though, has disadvantages. + +A fixed array restricts the amount of commands and may result in wasteful memory utilization, even if it is easier to build and offers predictable memory usage. Although dynamic memory allocation using `realloc()` eliminates the command restriction and offers flexibility, it necessitates cautious memory management to avoid leaks. + +Although a linked list provides full dynamic allocation without set restrictions, non-contiguous memory allocation and pointer dereferencing may result in a small performance overhead. Selecting the optimum strategy requires striking a balance between memory utilization, efficiency, and simplicity for the greatest shell performance. \ No newline at end of file