Skip to content
Snippets Groups Projects
Select Git revision
  • 98e407c4aaf77549e868093951fb2bfb9245cc38
  • master default
2 results

questions.md

Blame
  • user avatar
    Ansh authored
    98e407c4
    History
    questions.md 5.73 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: We use fork/execvp instead of calling execvp directly because fork will make a new process that is a copy of the parent process, so when we put in a command, that child process will start doing it while the parent process is still running unaffected by anything. If we didn't do this, our parent process would just be replaced by the thing we are calling execvp on, so our shell would terminate.

    2. What happens if the fork() system call fails? How does your implementation handle this scenario?

      Answer: If the fork() call fails, then that means that the OS wasn't able to create a new process for some reason. My code checks if the fork fails, and if it does, it writes a perror "Fork failed" and returns -1.

    3. How does execvp() find the command to execute? What system environment variable plays a role in this process?

      Answer: execvp finds the command to execute by using the system's PATH environment variable.

    4. What is the purpose of calling wait() in the parent process after forking? What would happen if we didn’t call it?

      Answer: The purpose of calling wait() is so that the parent process is able to synchronize with the child process and wait for it to exit before continuing its execution. If we did not call wait(), then we run into the risk of the parent continuint execution without knowing whether the child has finished its own process or not.

    5. In the referenced demo code we used WEXITSTATUS(). What information does this provide, and why is it important?

      Answer: WEXITSTATUS() gives us the exit code of the child process. It is important because it lets the shell check if something executed successfully or has failed.

    6. Describe how your implementation of build_cmd_buff() handles quoted arguments. Why is this necessary?

      Answer: My implementation parses through each character individually. Once it hits a ", it will then check whether the inside_quotes flag is set to 0 or 1. If it is set to 0, it will change the flag to 1, to indicate we are now inside of quotes, then iterate our i variable ++ to change to the next letter on the next runthrough, change start to i to indicate that we are at the start of the quote, and continue the loop. It will keep going, and eventually it will hit another ", in which it will then null terminate the current token and store it into the array, then toggle inside_quotes back to 0. Eventually, it will finishing going through all the letters, and then it will double check to make sure there's no more remaining tokens. Then it will set argc to the argument count and set the last entry in the array to NULL. This was necessary to make sure that no spaces inside of the quotes would get trimmed, and everything passes through as a proper element in the array. Like we don't want the input inside the quotes to be split up, so this will make sure that it won't.

    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: The biggest difference is that we have to parse through our input character by character instead of splitting the inputs based on where the pipes were. For some reason, I just couldn't get the parsing implementation to work. It kept making echo " Hello world " as [echo, ", hello, world] and would trim the spaces even though it was in double quotes. You'll probably see by my upload time, but I was up researching and figuring out how to fix it for 3 - 4 ish hours.

    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: The purpose of signals is to inform a process about certain events or to control the behavior in a specific way. They differ from other IPC's because they are primarily meant to be an asynchronous notification that is used to alert a process about something rather than doing something large like transferring data or have synchronous communication.

    • Find and describe three commonly used signals (e.g., SIGKILL, SIGTERM, SIGINT). What are their typical use cases?

      Answer: SIGKILL terminates a process immediately, and it can't be caught or ignored. This is usually used when a process is unresponsive or not terminating through normal means. SIGTERM is a request for the termination of a process, it can be blocked, handled, and ignored. It is sort of like a more polite way of asking the program to terminate. It is commonly used when you want a program to terminate gracefully. SIGINT is generated when someone types CTRL+C in the terminal, and it is used to interrupt a running process. It is commonly used for when you may have a long script that is printing a lot of statements and you want it to stop, instead of closing out of the terminal, you can just press CTRL + C and it will stop.

    • What happens when a process receives SIGSTOP? Can it be caught or ignored like SIGINT? Why or why not?

      Answer: When a program receives SIGSTOP, it will be paused by the OS. It cannot be caught or ignored like SIGINT because it's meant for when you want to stop a program forcefully, but you don't want to outright kill it like SIGKILL, you just want it to pause for a bit before you resume it later.