Skip to content
Snippets Groups Projects
Select Git revision
  • 99dac6d74b5fe743ff4ad7b41f6256cbb7bf0588
  • main default
2 results

questions.md

Blame
  • questions.md 5.63 KiB
    1. Can you think of why we use fork/execvp instead of just calling execvp directly? What value do you think the fork provides?

      Answer: start here We use fork() to create a new child process before calling execvp() so that the new process can replace its image with the desired executable. The value of fork() 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.

    2. 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 of fork() and printing an error message using perror("fork failed"). The function then returns ERR_EXEC_CMD to signal failure to the caller.

    3. 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 the PATH environment variable. It checks each directory listed in PATH and attempts to execute the command from there. If the command is not found in any of the PATH directories, execvp() fails and sets errno accordingly.

    4. 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 call wait(), the child process would complete execution but still exist in the process table until the parent reaps it, leading to resource leaks.

    5. 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 by waitpid(). It provides the return code of the executed command, allowing the shell to determine if the command succeeded (exit status 0) or failed (nonzero exit status). This is crucial for scripting and error handling.

    6. 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 an in_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).

    7. 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.

    8. 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 presses Ctrl+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. Unlike SIGINT, SIGSTOP cannot be caught, ignored, or blocked because it is intended for immediate process suspension. This makes it useful for debugging (e.g., using kill -STOP <pid> to pause a process).