CS 321 Spring 2013  >  Lecture Notes for Monday, January 23, 2013

CS 321 Spring 2013
Lecture Notes for Monday, January 23, 2013

Operating System Concepts [1.5]

Concurrency means logically (as opposed to physically) doing multiple operations at the same time. Modern OSs support concurrency far in excess of the number of processors in the machine. They do this by rapidly switching a single processor between multiple tasks. This is called multitasking (an older term, time sharing, means essentially the same thing). Such switching may be done with or without the explicit permission of the programs being executed concurrently. In the latter case, the OS is doing preemptive multitasking.

A process is a program in execution. This is an abstraction of the processor. A typical modern computer runs hundreds of processes concurrently.

We also use the term “process” to refer to the operating facility that supports a running program. Modern OSs generally allow this facility to support multiple concurrent executions, all of which have access to the same memory. These are called (kernel) threads.

Each process has an address space: its abstraction of the memory. This looks like a simple sequence of bytes, accessed via the usual assembly-language instructions. In practice, parts of the address space may correspond to physical memory, while other parts are actually on disk. When the latter are accessed, they are loaded into memory (this is virtual memory). If memory is full, then portions may need to be swapped out to storage.

A file is another abstraction that looks like a sequence of bytes, but it is accessed via a very different interface: open, read, write, close, etc., which is optimized for slow connections. Conceptually, a file is an abstraction of storage; however, as we have seen, essentially anything can be behind the file interface.

Input/output, or I/O, means communication with anything other than the processor and the memory.

All modern OSs provide various kinds of protection: ensuring that all access (to memory, files, etc.) is authorized.

A shell is a low-ish level interface to operating-system functionality. Traditionally, a shell uses a command-line interface.

System Calls [1.6]


Some things an OS does without being directly told to do so: switch between processes, swap a portion of memory out to disk, etc. Other OS operations are done when requested: output something, start a new process, wait a while, grab some memory, etc. These requests are done via system calls.

System calls happen a lot: essentially everything a program does, aside from mucking about with its own variables, will involve system calls.

Nonetheless, in a typical program we rarely deal directly with actual system calls. Typically we use higher-level library routines that make system calls. For example, in C++, “cout << ...” is (in part) a wrapper around the sys_write system call.

Calls & Thin Wrappers

In C/C++, system calls are usually made through thin wrapper functions. These are bare-bones interfaces to the assembly-language system calls. The main reason for a wrapper is calling conventions: C/C++ functions are not called the same way that system calls are made.

We looked at the following Unix system call wrappers. All are usually declared in <unistd.h> (not an ANSI standard header).

Wrapper around sys_write. Write to a (virtual?) file. Takes file descriptor, pointer to character buffer, number of characters to write. Returns number of characters actually written. A file descriptor is a nonnegative integer that identifies an open file. File descriptors are returned by the sys_open system call. Standard file descriptors that are opened for us are 0 (standard input), 1 (standard output), 2 (standard error output).
Wrapper around sys_exit. (The underscore avoids name conflict with a Standard Library function.) End current process. Takes integer parameter, which is used as status of process. By convention, a status of zero means no error, while nonzero signals an error. Does not return.
Implementation varies. Originally wrapper about sys_sleep; may be wrapper around sys_nanosleep, which allows for more fine-grained timing. Put process to sleep for given number of seconds. Takes integer parameter: number of seconds to sleep. Returns number of seconds the process actually slept.
Wrapper around sys_fork. Clone the current process. No parameters. Return value is integer of type pid_t. For child process, returns zero. For parent process, returns non-zero. If return value is positive: process ID (PID) of child. If negative: fork failed.

See syscall1.cpp (NetRun link) & syscall2.cpp (NetRun link) for C++ code that makes system calls. Note: These will probably work on most Unix-derived OSs; they may not work under Windows.

System Calls will be continued next time.

CS 321 Spring 2013: Lecture Notes for Monday, January 23, 2013 / Updated: 24 Jan 2013 / Glenn G. Chappell / ggchappell@alaska.edu