Operating Systems 2014F: Assignment 2

From Soma-notes
Jump to navigation Jump to search

Please submit the answers to the following questions via CULearn by midnight on Wednesday, September 17, 2014. There 10 points in 6 questions.

Submit your answers as a single text file named "<username>-comp3000-assign2.txt" (where username is your MyCarletonOne username). The first four lines of this file should be "COMP 3000 Assignment 2", your name, student number, and the date of submission. You may wish to format your answers in Markdown to improve their appearance.

No other formats will be accepted. Submitting in another format will likely result in your assignment not being graded and you receiving no marks for this assignment. In particular do not submit an MS Word or OpenOffice file as your answers document!

Don't forget to include what outside resources you used to complete each of your answers, including other students, man pages, and web resources. You do not need to list help from the instructor, TA, or information found in the textbook.

Questions

  1. [1] What is the relationship between function calls and system calls?
  2. [1] How would you send a signal to a process to have it pause execution? Resume?
  3. [2] Where are environment variables stored? Specifically, if a process changes its environment variables, are the variables of any other processes changed? Be sure to consider currently running and processes created in the future.
  4. [2] Precisely describe the data structure used to store environment variables when they are passed to execve().
  5. [2] What happens when a program attempts to access memory location 0? Give a simple program that attempts to do this and explain what happens when it runs. Be sure to explain what program produces the output seen at the command line. (You may want to run the program using strace to get a better idea what is happening.)
  6. [2] Give the code for a limited "fork bomb" that creates the number of processes listed on the command line. Each process should print out which process it is, e.g. "I am bomb process 17!" (where the count is the count of the number of processes created, not the PID). After printing the count each should then sleep for 30 seconds (using sleep()) and then terminate.

Solutions

  1. System calls are how regular processes invoke code in the kernel while function calls are how code is invoked inside of a regular process. Functions and system calls both take arguments that are pushed onto the stack. Functions are invoked by pushing the current program counter address onto the stack and jumping to the address of the function's code (e.g., using a CALL x86 instruction). System calls make a trap/software interrupt (e.g., INT 0x80 or SYSCALL/SYSENTER on x86) that causes the CPU to switch modes to supervisor mode, run a dispatcher, make a function call within the kernel, then return back to userspace (running the same or another process, depending upon the scheduler). Note that regular programs don't make system calls directly; instead they call standard function which in turn make system calls using inline assembly or C extensions.
  2. From the command line use "kill -SIGSTOP <PID>" to stop and "kill -SIGCONT <PID>" to continue. From C, use kill() in a similar fashion.
  3. Environment variables are not global variables, they are process-specific and stored in the process's address space. Thus changes to a process's environment variables only affect it and its subsequent children (as produced by fork). Environment variables may or may not be passed on when a new program is run via execve (environment variables are one of the arguments to this system call).
  4. The argument declaration in C is "char *const envp[]". envp is an array of pointers to environment variables. The final element in this array must be NULL. Each of the other elements points to a null-terminated string in the form of "name=value".
  5. See zero.c below. When run on the command line this program outputs something like "segmentation fault (core dumped)". The printf() does not run because the access to address 0 happens as part of assembling its arguments (it is never called). This happens because the kernel generated a SIGSEGV signal because the process was accessing a part of its address space that wasn't allocated/valid.
  6. See limitedbomb.c below.

zero.c

#include <stdio.h>

int main(int argc, char *argv[])
{
        printf("The value of zero as a byte: %d\n", *((int *) 0));
        return 0;
}

limitedbomb.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
        int count, i, status;
        pid_t pid;

        if (argc < 2) {
                fprintf(stderr, "Usage: %s <num processes to create>\n",
                        argv[0]);
                return -1;
        }
	
        count = atoi(argv[1]);

        for (i = 1; i <= count; i++) {
                pid = fork();

		if (pid==0) {
			printf("I am bomb process %d!\n", i);
			sleep(30);
			return i;
		}                
        }

        for (i = 0; i < count; i++) {
                pid = wait(&status);

                printf("Child %d returned.\n",WEXITSTATUS(status));
        }
        
        return 0;
}