questions.md
-
Ziheng Chen authoredZiheng Chen authored
-
Can you think of why we use
fork/execvp
instead of just callingexecvp
directly? What value do you think thefork
provides?Answer: start here We use
fork()
to create a new child process before callingexecvp()
so that the new process can replace its image with the desired executable. The value offork()
is that it allows the parent process (the shell) to remain running while the child process executes the command. This enables process control, such as waiting for the child to complete, handling multiple commands, and supporting job control features like background execution. -
What happens if the fork() system call fails? How does your implementation handle this scenario?
Answer: start here If
fork()
fails, it returns-1
, indicating that no child process was created. This typically happens when system resources (like process table slots) are exhausted. My implementation handles this by checking the return value offork()
and printing an error message usingperror("fork failed")
. The function then returnsERR_EXEC_CMD
to signal failure to the caller. -
How does execvp() find the command to execute? What system environment variable plays a role in this process?
Answer: start here
execvp()
searches for the command in the directories specified by thePATH
environment variable. It checks each directory listed inPATH
and attempts to execute the command from there. If the command is not found in any of thePATH
directories,execvp()
fails and setserrno
accordingly. -
What is the purpose of calling wait() in the parent process after forking? What would happen if we didn’t call it?
Answer: start here The
wait()
system call allows the parent process to pause execution until the child process terminates. This prevents zombie processes (defunct processes that remain in the process table). If we didn’t callwait()
, the child process would complete execution but still exist in the process table until the parent reaps it, leading to resource leaks. -
In the referenced demo code we used WEXITSTATUS(). What information does this provide, and why is it important?
Answer: start here
WEXITSTATUS(status)
extracts the exit status of a terminated child process from the status code returned bywaitpid()
. It provides the return code of the executed command, allowing the shell to determine if the command succeeded (exit status0
) or failed (nonzero exit status). This is crucial for scripting and error handling. -
Describe how your implementation of build_cmd_buff() handles quoted arguments. Why is this necessary?
Answer: start here My
build_cmd_buff()
function correctly detects quoted arguments by toggling anin_quotes
flag whenever it encounters a double quote ("
). It ensures that spaces within quotes are treated as part of the argument rather than as separators. This is necessary because many shell commands require passing multi-word strings as single arguments (e.g.,echo "Hello World"
should be treated as one argument). -
What changes did you make to your parsing logic compared to the previous assignment? Were there any unexpected challenges in refactoring your old code?
Answer: start here In this assignment, I improved handling of argument splitting by properly managing spaces inside quotes. Additionally, I added checks for argument limits (
CMD_ARGV_MAX
) and included error handling for too many arguments. The main challenge was ensuring that special characters (like"
and spaces) were handled correctly while maintaining robust error reporting. -
For this quesiton, you need to do some research on Linux signals. You can use this google search to get started.
-
What is the purpose of signals in a Linux system, and how do they differ from other forms of interprocess communication (IPC)?
Answer: start here Signals provide a way for processes to receive asynchronous notifications about events, such as termination requests (
SIGTERM
) or user interrupts (SIGINT
). Unlike other IPC mechanisms (pipes, message queues, shared memory), signals do not carry data—they simply notify a process of an event. Signals are often used for handling process control (e.g., stopping or restarting services). -
Find and describe three commonly used signals (e.g., SIGKILL, SIGTERM, SIGINT). What are their typical use cases?
Answer: start here
-
SIGKILL (9)
: Immediately terminates a process and cannot be caught or ignored. Used when a process needs to be forcefully stopped (e.g.,kill -9 <pid>
). -
SIGINT (2)
: Sent when the user pressesCtrl+C
. It allows a process to handle interruption gracefully, such as stopping an interactive program. -
SIGTERM (15)
: Politely asks a process to terminate, allowing it to clean up resources. This is the preferred way to stop processes (e.g.,kill <pid>
).
-
-
What happens when a process receives SIGSTOP? Can it be caught or ignored like SIGINT? Why or why not?
Answer: start here When a process receives
SIGSTOP
, it is immediately paused (suspended) by the kernel. UnlikeSIGINT
,SIGSTOP
cannot be caught, ignored, or blocked because it is intended for immediate process suspension. This makes it useful for debugging (e.g., usingkill -STOP <pid>
to pause a process).