______ In-class notes for 09/11/2019 (CS 273 (OS), Fall 2019)
Home
>>     < >




In-class notes for 09/11/2019

CS 273 (OS), Fall 2019

  • HW2, due today "midnight"

    • Questions?

  • Note: First quiz will be one week from today.

Reading questions?

  • Chapter 1

  • Chapter 10

Submitted questions on assignments and technology

  • Use this form to submit questions for a future class meeting

Reading questions

Expanded notes on topics from last time

Selected Linux system calls

  • More file-related system calls

    dup(), pipe(), etc.

    • Each process has a kernel file descriptor array, with file descriptor as index and pointer to open-file data structures as values.

  • System calls for file systems, i.e., OS components that contain files and directories

    mount(), umount(), etc.

Other components of an OS besides file system

  • Devices

    • ioctl(), for setting parameters for an I/O (input-output) device (will return for code illustration)

    • Berkeley socket calls, for network I/O (will return later)

    • Specialized device calls, e.g., time-related calls for interacting with clock device (will return)

  • Memory management

    • brk(), sbrk(), for adjusting how much main memory is allocated to a process.

  • Process management system calls

    • fork(), execve(), exit(), wait(), waitpid()

    • Example code: ~rab/os/egs/forkeg.c

      (fork(), execve(), and wait() implement the key ideas in the Linux strategy for starting new programs.)

    • zombie process -- process called exit(), but its parent hasn't called wait() for it to collect its exit status, so that exited process continues to take up OS resources.

Lab 2

(Start in-class; due later as part of HW3)


The environment

  • As part of process management in Linux, every process possesses an array of strings known as the environment for that process. Each string in the environment has the form

        NAME=value
    
    for example,
        PRINTER=dept-rns202
    
    These strings are treated as "environment variables", in which a variable NAME is thought of as having the value value.

  • When a process is started using a (running) shell program, that process automatically inherits that shell's environment. This enables that shell to pass information to the new process. For example, you might execute the program lpr in a shell; the new lpr process is programmed to check for an environment variable PRINTER, and will use the value of PRINTER as the default destination printer if that environment variable exists.

    In general, whenever any given process (not necessarily a shell) starts up another new process in Linux, that new process inherits that given process's environment.

  • A shell command

        % printenv
    
    typically prints all the environment strings for that shell process.

    In the csh and tcsh shells, the command

        % setenv X val
    
    sets the environment variable named X to have the value val.

    Environment variables are assigned differently in the bash, sh, and ksh shells:

        $ export X
        $ set X=val 
    
    (note that these shells typically use $ for a prompt character). The export command only needs to be entered once per shell, and declares that set commands involving X should change the environment.

  • In a C or C++ program, the optional third argument of main() becomes automatically filled with the address of the environment array when that third argument is included. See reverse.c in Lab 1 for an example of including that third argument for main(). The third argument has type char **, since it holds an array of pointers to (null-terminated arrays of) characters. That array of pointers can have one or more elements; the final element holds a null-pointer, namely the value (char *) 0, which enables a program to detect the end of its environment.

    Shell command:
        % reverse a b c
    
    Header for main() in code reverse.c:
        int main(int argc, char **argv, char **envp)
    
    Memory diagram:

Programming with system calls (mopen.c)

  • The program ~cs273/egs/mopen.c uses system calls open(), read(), write(), and exit() in order to manipulate a given file interactively and quit the program. mopen.c is also a model for how to use system calls in a C program.

  • Demo of egs/mopen
    Example: ~cs273/egs/mopen try.txt -r -w -r

  • Before using a system call in your code, consult the manual page (perhaps by googling man syscall, e.g., man write) in order to find out what arguments are required, what that system call does, how to interpret the return value (if any), and what header files are needed to make that call. For example, the write manual page indicates that the write() system call requires three arguments: a file descriptor for an open file, a "buffer" array of bytes to be written, and a count of how many bytes to attempt to write. That call, returns an integer number of bytes successfully written, and it requires the standard header file unistd.h .

  • The call of write() in mopen.c illustrates a standard way to program with system calls.

          if ((ret_val = write(fd, getlinebuff, nchars-1))) < 0)
    	printf("Error code %d returned\n", ret_val);
          else 
    	printf("%d bytes written\n", ret_val);
    
    • The write() system call appears in boldface in this code segment, including its three arguments.

    • The return value from that call of write() is stored in a variable (ret_val in this example). If that value is negative, an error message is printed; otherwise a report of that number of bytes is printed.

    Be sure to check return values from system calls as we show for the write() system call above, so your code can correctly handle all possible outcomes from a system call.

  • The code above represents a common convention for many system calls, in which negative return values indicate errors. But the particulars can vary from one system call to another. Check carefully with the online documentation to insure that your program interprets system-call return value correctly.

    In particular, the search man exit shows that the exit() library function (which makes an _exit() system call) returns no value. This makes sense, because that system call terminates the calling process -- there can be no return! Thus, attempting to store that nonexistent return value (as we did with write()) would cause a compiler error.

  • getline library function, for reading a line of input (including newline, with nullbyte appended). This is safer than gets() or fgets(), in case input includes a nullbyte within a line.

      char *getlinebuff = NULL;
      size_t getlinelen = 0;
      ...
          int nchars = getline(&getlinebuff, &getlinelen, stdin);
          if ((ret_val = write(fd, getlinebuff, nchars-1)) < 0)
            ...
      free(getlinebuff);
    

    • Dynamic memory allocation; buffer management within getline()

    • Passing addresses of memory locations (having no reference types)

    • Standard input stream stdin, of type FILE*

    Don't mix I/O system calls (e.g., open(), read(), write()) and stdio.h library calls (e.g., printf(), scanf(), getline()), fopen()) on the same input source.

    • Unbuffered I/O vs buffered I/O internal in those calls (don't confuse with programmer's buff and getlinebuff).

    • Here, we are using buffered I/O on standard input and unbuffered I/O on a file.

  • Overview of the structure of ~cs273/egs/mopen.c.

    • #includes of header files

    • Definition of try_open() helper function

    • main()

      • Processing of command-line arguments in argv

      • Print instructions for entering mopen commands

      • Loop for reading and acting on mopen commands

        • Print mopen command prompt

        • Nested if - else cases for recognizing each mopen command, retrieving/checking its arguments, and performing/checking its system call

      • exit() call for terminating the program

  • To add a new system call option to mopen.c, be sure to modify all the appropriate parts of the code (do you need more header files? add to instruction output; add a new if - else case with proper error checking)




< >