The Operating System: The Purpose
The Operating System: The Purpose
The operating system must try to satisfy these requests in a multi-user, multi-process
environment while managing
• Resource allocation
• Error Detection
• Protection
The Operating System: Process Control
Processes need to be able to control their own execution, as well as spawn new processes
to perform tasks concurrently. Processes request services to
• fork : create a new process
• exit: normal termination, abort: abnormal termination
• execve: load and execute another program
• wait : wait for another process to finish
• Signal Management: handling asynchronous events
– signal, sigaction : setting signal handlers
– kill : sending signal
• Threads: creating and managing multiple execution threads in a single process
The File System: The User’s View
ddedeh YWWYY
d ddd d
e d
eedededhedhedhedhedhoehohoo \ NNNWNWYNWYWYWYWYWYWYYYYY
d
dd ee h o NNN WWWWWYYYYYYY
dddddddeeeee hhhh oo WWWW YYYYYYY
ddddededededeeeeeehehhhhhhh oooo NNN WWWW
ddddddd dddddd
e eee hhh oo NNN WWWW YYYYYYYYYYY
dq dddddd reeeeee shhhh wo & WW+ YYYY,
...
bin etc dev home proc cdrom usr var
bash passwd pts kaharris 1 assign1 include log
2 51081OO status stdio.h wtmp
OOO
OOO
OOO
O'
assign1 notes
but underneath the hood things are not as they first appear . . .
The File System: Smoke and Mirrors
Device Drivers
Program
User
The Operating System: File System Management
The Unix File System is organized as an acyclic directed graph with nodes representing
files and arcs representing a containment relation. Directories are nodes with children,
so contain files. Processes move around and modify the structure:
• chdir : moving to a new directory
• getcwd : get the current working directory
• opendir, closedir : open and close a directory
• readdir : read from a directory
• stat, fstat : Retrieving file status information
• link, unlink : create and release a hard link (an alias for a file.)
• symlink : create a soft link (a pointer to another file)
The Operating System: I/O Operation
Unix uses a uniform device interface that allows the same I/O calls to be
used for terminals, disks, audio and network communication.
Unix provides a variety of means for processes to communicate with each other:
• pipe : a one-way data stream between related processes
• mkfifo : a one-way data stream between unrelated precesses (called a named pipe
or FIFO)
• System V IPC: refined communication channels for unrelated processes
– Message Queues : Linked lists of messages stored in the operating system
– Shared Memory : Allows two processes to share a given region of memory
– Semaphores : Provides controlled access to a shared object
• Sockets : Two-way data stream, used to establish Network connections.
The Operating System: System Information
Unix provides means for accessing information about the system for process use or
accounting:
• Special directories which provide Start-up and Run-time information. Some of the
files are specially configured, so provide special functions to retrieve information.
Examples
– /etc/ : System configuration files. Examples
∗ /etc/passwd
∗ /etc/group
– /var/ : Runtime changable files. Examples
∗ /var/run/utmp : Currently logged in users
∗ /var/log/wtmp : All logins and logouts
– /proc/ : Process information
• Time and Date functions in <time.h>
• uname : system identification
• sysconf, pathconf : Information on system limits
Unix System Call: The System Call Model
The system call represents the interface of a program to the kernel of the Operating
System
1. The system call API (Application Program Interface) is given in C
2. The system call is actually a wrapper routine typically consisting of a short piece of
assembly language code.
3. The system call generates a hardware trap, and passes the user’s arguments and an
index into the kernel’s system call table for the service requested.
4. The kernel processes the request by looking-up the index passed to see the service
to perform, and carries out the request.
5. Upon completion, the kernel returns a value which represents either successful com-
pletion of the request or an error. If an error occurs, the kernel sets a global variable,
errno, indicating the reason for the error.
6. The process is delivered the return value and continues its execution.
Unix System Call: Motivation behind the Model
There are layers of interaction in the system to ensure fair access to resources,
protect privacy, and provide convenience.
Users
O
User Programs
O
Kernel
O
CPU/Devices
System Calls versus Standard Library Functions
The system call model is very different from the implementation of Standard
C Library functions
• Library functions provide an interface which may be run on any operating system
which has a C compiler; System calls are specific to Unix Operating Systems.
• Library functions are executed by your program; System calls are executed by the
kernel.
• Library functions handle error checking; you are responsible for error checking with
system calls.
• Library functions provide a convenient interface: such as I/O buffering and formatted
input and output; system calls are raw–the programmer is responsible for making
them convenient.
• The standard C library interface is found in the manpages in section 3; the system
call interface is found in the manpages in section 2.
Error handling functions for System Calls
SYNOPSIS
#include <errno.h>
int errno;
SYNOPSIS
#include <stdlib.h>
SYNOPSIS
#include <string.h>
You must examine the return value of every library function that can return
an error.
• Traditionally, Unix system calls return -1 (or sometimes NULL) and set a global
variable errno.
• POSIX standard committee has specified a list of errors that each system call must
report. In addition to these Unix implementations may have more errors. The
manpages list all possible errors for each system call on the system.
• There are two standard C library functions for reading errors:
– perror(s) prints a message to standard error: s :msg where msg is a short
description of the error. The text of msg is based upon the current value of
errno.
– strerror(errnum) returns a pointer to a string which contains a short descrip-
tion of the error number errnum. Beware: you may not modify this string, and
subsequent calls to strerr may overwrite this string!!
• Beware: errno is a global variable. Many standard C library routines use system
calls which may overwrite the value in errno. If you need this value, then save it to
another variable.
System Calls for I/O Operation: The Universal Interface
• All I/O devices are represented by files that are located in directory /dev and can
be accessed for I/O exactly as any regular file on disk.
• The Kernel communicates to devices using device drivers.
• Processes access and control devices for I/O through four system calls to the Kernel.
• I/O operation is a simple three step procedure for any file, whether it is an I/O
device or regular file:
1. Open the file for I/O.
2. Read and Write to the file.
3. Close the file when finished with I/O.
• Access to an open file is through a file descriptor.
File I/O: The Universal Interface
All devices are represented by files that are located in directory /dev
• /dev/tty is the terminal
• /dev/null is a byte black hole: reading from it always produces EOF and writing
to it eats bytes.
• /dev/zero is an infinite source of 0’s
• /dev/stdin /dev/stdout , /dev/stderr . Example of use:
$: cat file1 /dev/stdin
Outputs file1 then waits for a line of input and appends this to the end of its
output. Equivalent to cat file1 - .
• See Molay, Understanding Unix/Linux Programming section 5.2 for further discus-
sion of some of the devices found in the directory /dev .
File Descriptors: The Process handle on I/O
Most Unix file I/O can be performed using only the following five functions:
SYNOPSIS
#include <unistd.h>
errno
EINTR Call was interrupted by signal before any data was read
SYNOPSIS
#include <unistd.h>
errno
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
The argument flag is obtained by OR’ing together one of the following constants with
an optional flag (defined in <fcntl.h>)
Example:
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
creates the file path for writing only. This operation is equivalent to
fd = creat(path, mode);
Example:
fd = open(path, O_RDWR | O_CREAT | O_EXCL, mode);
Guarantees the file path is a new file or returns EEXIST error.
open: Flags
flag
mode
S_IRUSR read by owner
S_IWUSR write by owner
S_IXUSR execute by owner
S_IRWXU read, write, execute by owner
S_IRGRP read by group
S_IWGRP write by group
S_IXGRP execute by group
S_IRWXG read, write, execute by group
S_IROTH read by others
S_IWOTH write by others
S_IXOTH execute by others
S_IRWXO read, write, execute by others
S_ISUID set user ID on execution
S_ISGID set group ID on execution
close: close a file descriptor
SYNOPSIS
#include <unistd.h>
errno
Usage of close
• When a process terminates all open files are automatically closed by the kernel.
• A process has a limited number of file descriptors available to it, OPEN_MAX (defined
in <limits.h>.)
• Closing a file releases any record locks that the process may have on the file.
Usage of open
• The initial file offset is set to 0 when opening file, unless O_APPEND is specified, in
which case the offset is set to the end of the file.
• The file descriptor returned by open is guaranteed to be the lowest numbered unused
descriptor. This is useful
close(STDOUT_FILENO);
fd = open("my_file,) O_WRONLY);
Any output to stdout will now go to the file my_file
Always check for errors, but you may not always want to bail-out. See the restart
library.
lseek: reposition read/write file offset
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
whence
SEEK SET New file offset is offset bytes from beginning of the file.
SEEK CUR New file offset is current value plus offset bytes
SEEK END New file offset is the size of the file plus offset bytes
lseek: All Errors
errno
• Every open file has associate a current file offset: the number of bytes from the
beginning of the file.
• Certain devices allow negative offsets; but for regular files the offset must be non-
negative. Thus, for regular files offset must be non-negative if whence is SEEK_SET.
• lseek only changes the current file offset within the kernel–it does not cause I/O to
take place. (See next point.)
• The file offset can be repositioned beyond the file size. In this case the next write
begins beyond the file size. This is referred to as creating a hole in the file. Any
bytes in the file that have not been written to are read back as 0. Why is this? (A
sparse file, such as a database with few entries.)
• lseek can be used to determine the current file offset
currpos = lseek(fd, 0, SEEK_CUR);
• The previous code can also be used to determine if the current file is a pipe, socket
of FIFO by testing (currpos == -1 && errno == EPIPE) . Why do we need the
second clause?