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()
, andwait()
implement the key ideas in the Linux strategy for starting new programs.)zombie process -- process called
exit()
, but its parent hasn't calledwait()
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 variableNAME
is thought of as having the valuevalue
.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 newlpr
process is programmed to check for an environment variablePRINTER
, and will use the value ofPRINTER
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
andtcsh
shells, the command% setenv X val
sets the environment variable namedX
to have the valueval
.Environment variables are assigned differently in the
bash
,sh
, andksh
shells:$ export X $ set X=val
(note that these shells typically use$
for a prompt character). Theexport
command only needs to be entered once per shell, and declares thatset
commands involvingX
should change the environment.In a C or C++ program, the optional third argument of
Shell command:main()
becomes automatically filled with the address of the environment array when that third argument is included. Seereverse.c
in Lab 1 for an example of including that third argument formain()
. The third argument has typechar **
, 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.% reverse a b c
Header formain()
in codereverse.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 callsopen(), read(), write(),
andexit()
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, thewrite
manual page indicates that thewrite()
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 fileunistd.h
.The call of
write()
inmopen.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 theexit()
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 withwrite()
) would cause a compiler error.getline
library function, for reading a line of input (including newline, with nullbyte appended). This is safer thangets()
orfgets()
, 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 typeFILE*
Don't mix I/O system calls (e.g.,
open()
,read()
,write()
) andstdio.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
andgetlinebuff
).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
.#include
s of header filesDefinition of
try_open()
helper functionmain()
Processing of command-line arguments in
argv
Print instructions for entering
mopen
commandsLoop for reading and acting on
mopen
commandsPrint
mopen
command promptNested
if - else
cases for recognizing eachmopen
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 newif - else
case with proper error checking)
< >