Notizen
Lecture 02 – 10/3/2016
Inhalt der Notizen (1)
Seite 1
File System Part I
C – API
File table
Keyboard
Screen
cout
Difference between:
cout
<< “Ducks are good” << endl;
cerr
<< “Lizards are cute” << endl;
If you want to really see the cerr there
are ways around that
Preliminaries
Why discuss this first? Because we know something about file
systems, it is a nice simple place to start. Also file access is the foundation for
other services in the UNIX. E.g. pipes and internet communications.
Review the hardware fundamentals. Format of disk, seek, latency,
transfer rate.
Discuss some of the directory structure in UNIX. I would like to
say that it is consistently defined on every system, but it isn't.
/bin
: were most of the commands and system programs may be found.
-> Examples mkdir, ls, ed.
/etc
: Just what the name implies. A place to put a whole bunch of stuff.
-> Examples: passwd and hosts file
/usr
: Usually information associated with users. (i.e. Home directories - we
use /home)
-> Example student and faculty sub-directories.
/usr/include
: where many of the include files may be found. Like iostream
/tmp
: temporary directory. Goes away on bootup.
/unix
: where UNIX system found. We are using /kernel
/dev
: description of devices.
Basic services that we expect any
file system to provide.
create
open
On many file systems, include Linux, the open also serves the role of
create
read
write
close
rewind
seek
delete
Notes on the UNIX file system:
UNIX see a file as a string of bytes. The UNIX
operating system does NOT see records or lines.
Mention that UNIX makes use of disk caching. Files accesses
are not buffered within the code for these calls. Let's discuss the
pros and cons of this in class.
There
are also C and C++ files systems. These are implemented using the UNIX
file system. Why use the UNIX file system rather than the file
system provided in a programming language? Why use the file system
provided by the programming language?
File names may be made up of any characters. For example
"*" and " " may be file names. You can even have
the ASCII code to ring the "bell:. Hard to remove these using
the rm command.
Microsoft
has implemented the basic UNIX file system calls. So, if you ever
need unbuffered I/O these will do it for you. I will explain why in
class.
We access these file services through UNIX system calls. These
look like C function calls, because they are. Is this a problem??
It does require a way to identify an open file.
For example:
nb = read( fd,
buff, NumBytes );
System calls "talk" to the operating system. How does
this happen? (svc, int, sys assembler calls are made to transfer control to the
operating system). Because of requiring a context switch to
and from the operating system, there is additional overhead associated with
calls like the read.
How are errors returned? Rule: UNIX usually returns -1 if there is
an error. For functions that return addresses, NULL is usually
returned if there is an error. The external int errno contains a code
that describes the error. We MUST always check for errors on each system call we
use. I will not accept your lab if you don't do this. Make sure that everyone
understands external variables.
Let's look at errno.h to see what is there. (Look in the
/usr/include directory.) Note the extern int errno; statement.
Note that errno can be a function. Why? Note: the errno.h file
contains other include file. These contain the defines for the error
codes.
Error Reporting
Error reporting is essential. When a function in the API
fails, you want to find this out and why. We will use the perror function
to report errors. Let's look this function up in the man pages. It
is a lot easier to do this on the site:
http://linux.die.net
This function reports the error number, a description of the error
and your message. I expect to see you using it on your quizzes and
programming assignments.
Previous to this function you had to write your own to do
it. Those days are long gone. See below for an example of the type
of function you would have to write. We will talk about it for the sake
of its ideas.
errno contains a number that stands for the error. Sometimes
it is nicer to read text. "sys_errlist" is an array of pointers to
ASCII strings that describe the errors. "sys_nerr" is the size of
this array. These are global variables The following is a function that we will
use to display errors. Note that the man pages list error returns
from system calls. We are discussing this function because it opens up a
discussion ofa number of ideas.
The following is an example of how to write your own function for
reporting errors. I will use perror in the class examples and
expect you to use it in your programming assignments and quizes.
#include <iostream>
using namespace std;
void syserr( const char *msg ) /*
print sys error message and terminate. */
{
extern
int errno, sys_nerr;
extern
char *sys_errlist[];
cerr
<< "ERROR: " << msg << "(" <<
errno;
if(
errno > 0 && errno < sys_nerr ) {
cerr
<< " - " << sys_errlist[errno] << ")"
<< endl;
}
else {
cerr
<< ")" << endl;
}
exit(1);
}
Why cerr instead of cout?
See ex1.cpp for an example of how perror works. I
will use the gdb (our debugger) to demonstrate this function. Also, discuss the
basics of make. See Makefile file for the make file for this
project. We will also create this program in Eclipse.
Note: it is not a good move to name your program test.
Note: for Eclipse, see the following article if there is not an
autosave before a build:
http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Ftasks%2Fcdt_t_autosave.htmhttp://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Ftasks%2Fcdt_t_autosave.htm
The following is an example of more sophisticated file use to
get a perspective on why these calls are very useful.
Discuss the problem of accessing minute data from FasTick.
Picture simulations that require 500 days of 1 minute tick data with a
thousands stocks. By using FasTick directly, it would take about 10 hours
to download. So each simulation involving this data would take more than
10 hours. We need an alternative approach. What approach do you think
I came up with
The file access calls 9/26
starts here. Start by creating a workspace
Let's go through the basic system calls to do file access. We are
diving right in rather than given background material first. We will come back
to things like how the file system is set up. Note: Windows
have a similar set of unbuffered calls that you might want to use when you need
this functionality.
The Linux file system is important because large parts of the
operating system use it. For example, process to process communications
and network programming go through the file system.
The first API call presented will be the open. You can
find all the information I am discussing using the man command or by reading
the text or look this up on the web. (Note: the following link is very
useful for man pages:http://linux.die.net/man/ Yes, I am
repeating myself.) I will show how to do this through emacs. The
open call prepares your program to access a file. What does
this mean??
Note: there is an ancient call called creat to
create new files. We will not talk about it, but you might run into
it. It has a similar format to the open function and has beenmade obsolete by
the open call. Someone who uses it has probably been around for a while
or the code you are working on has been.
#include < sys/types.h >
#include < sys/stat.h >
#include < fcntl.h >
#include < limits.h > /* definition of OPEN_MAX */
int open( const char * path, int flags,
mode_t mode)
path : the name of the file optionally including a full
directory path. If no path is given, the file is assume to be in the working
directory from which the program was executed.
flags : defines how the file is to be opened. This argument is
formed by OR'ing the following values (I will not list all of them):
O_RDONLY
: Open for reading only.
O_WRONLY
: Open for writing only.
O_RDWR
: Open for reading and writing.
O_APPEND
: Append on each write.
O_CREAT
: Create file if it does not exist.
O_TRUNC
: Truncate size to 0.
O_EXCL
: Error if create and file exists.
O_SYNC
: Do file writes synchronously. That is each write must
fully complete before and other operation occurs. This guy is super
safe.
Make sure everyone recalls how to do bit wise or's using the
"|" operator. Note: some flags are system dependent. It
is always good to choose the least level of flags. Why?
mode : this parameter is optional. (How does this
happen?) It is only used if the file is created by this call. The mode is used
to describe permissions associated with the file In the old days people used a
3 digit octal number to describe the permission. The digits correspond to
owner, group, and other. The bits within a digit indicate read, write, and
execute permissions. How do you specify an octal number in C++. To
give read and write permission to the owner only, mode = 0600.
Lets look at /usr/include/sys/stat.h for newer way of specifying
permissions. I will stick with the old way. Usually the new way is
better, but at least for me, the old way is quicker to write and almost
everyone understands it. The following is a section from the stat.h
file:
#define S_IRWXU 00700 /* read, write, execute: owner */
#define S_IRUSR 00400 /* read permission: owner */
#define S_IWUSR 00200 /* write permission: owner */
#define S_IXUSR 00100 /* execute permission: owner */
#define S_IRWXG 00070 /* read, write, execute: group */
#define S_IRGRP 00040 /* read permission: group */
#define S_IWGRP 00020 /* write permission: group */
#define S_IXGRP 00010 /* execute permission: group */
#define S_IRWXO 00007 /* read, write, execute: other */
#define S_IROTH 00004 /* read permission: other */
#define S_IWOTH 00002 /* write permission: other */
#define S_IXOTH 00001 /* execute permission: other */
Make sure that if you specify the O_CREAT flag that you put this
option in. Otherwise, life will get interesting. :-) I will explain
why.
Returns -1 if there is and error and a nonnegative integer (file
descriptor) if the function succeeds. All subsequent system calls that
reference this file will use this file descriptor.
Notes:
File descriptors 0, 1, and 2 are are pre-assigned. These correspond
to the keyboards, screen, and screen (for error messages)
respectively. If you close file descriptor 1, you will cause
interesting effects. For example, the cout object will no longer
work. Why?
The
previous statement has interesting implications. It means that
access to a screen or from a keyboard goes through file descriptors in the
same manner as a file. This is also true of other means of
communications and other devices.
File
descriptors represent a position in a local table.
File
descriptors are not global across processes. That means file
descriptor 4 in one process has no relationship to file descriptor 4 in
another.
File
descriptors are assigned lowest available number first. So, on your
first open, your should see a File descriptor having the value of 3.
There
is a limit on how many files may be opened by a single process. Most
Linux systems have 1024 as the limit. How would you find this
out? (ulimit -n) This can be changed.
If
you use the equivalent calls in Microsoft OSs, be aware that the file
descriptors are not assigned sequentially and are not small numbers.
There
is a separate function to create files called creat. This
function is less powerful than open and obsolete, so it should not be
used. It exists for the sake of maintaining old code.
The read function reads data from an open file. It has the
following format:
ssize_t read(int fd, void *buff, size_t
nbyte);
fd : the file descriptor for an open file.
nbytes : the number of bytes to be read.
buff : address of a buffer into which the data will be read.
What is size_t? What is ssize_t. What the heck are they
thinking!
Returns: If the returned value is 0, then end-of-file has been
reached. If the read is successful, the number of bytes actually read is
returned. Otherwise, a -1 is returned and the global variable errno is set to
indicate the error.
Note about where in the file we are reading from and what the
"current file" offset or file pointer refers to.
Note: man page can describe the arguments slightly differently
depending on whose UNIX we are using. But, the use is the same.
This is one of the problems with using UNIX.
The write system call is used to write data to a file. It has the
following format:
ssize_t write(int fd, const void *buff,
size_t nbytes);
fd : the file descriptor for an open file.
nbytes : the number of bytes to be written.
buff : buffer for the data to be written.
This function returns the number of bytes written to the file. It returns -1 if
there was an error. Question: why the use of const?
The close function allows the operating system to
recover the resources that were allocated when the file was opened. All the
files that your program has opened are automatically closed when your program
terminates. The close function has the following format:
int close(int fd)
fd : the file descriptor of an open file.
This function returns 0 if it is successful and -1 if it fails.
Sometime you might want to read from the middle of a file.
Why? The lseek function allows you to position the current file offset so
that you can read from or write to anywhere in the file. If you try to read
beyond the end of the file what do you think happens? You get a zero length
read. If you attempt to write beyond the end of a file what do you think
happens?
The format of the lseek is as follows:
#include < sys/types.h >
#include < unistd.h >
off_t lseek( int fd, off_t offset, int
whence)
fd: a file descriptor from an open file.
offset: a file offset.
whence: indicates what the offset is from.
If whence is SEEK_SET, the pointer is set to offset bytes.
If whence is SEEK_CUR the pointer is set to its current location plus offset.
If whence is SEEK_END, the pointer is set to the size of the file plus the
offset.
Note: the offset may be positive or negative.
Note: lseek can be used to find the current location. How?
Returns the new file offset if successful and -1 if fails.
Examples:
ex2.cpp and copy.cpp -
is an example of a function to copy the contents of one file into
another. I have an error reporting function. We will replace
it with perror. Note the way I can use the debugger to find why a program
core dumps. We will also create this executable without using Eclipse.
ex3.cpp Shows the use of lseek and what happens when you write
beyond the end of a file. Note about how this can be used to mess up
people who do backups. :-) DO NOT DO THIS!
Lab1
Write a program called rctail which will take a file name as its command line
argument and display the last 10 lines in the file. Don't make any assumptions
on the size of the file you are displaying. You are to use the UNIX system
calls. Make this program as efficient as
possible. We will discuss more in class. To get it right,
this lab takes more time that you would expect, so start it right away.
Note: In class we will determine how lines of text in a file
are delimited. We will use the od command. This allows us to dump
in octal and other formals.
If there is time, write an example in class that will display the
contents of a file in reverse order.
I/O Efficiency
Recall that disk data is cached. So, this does not mean we
have to read from the disk every time we want data. The text has a nice
table (3.5) that I would like to discuss. It give measures of speed in
accessing data from a large file through Linux. It uses a variety of
buffer sizes. Please read the text about this table and how they did the
experiment. Note, they are doing fresh reads from the disk. Why?
Buff Size
User CPU Time
System CPU Time
Clock Time
#Loops
1
124.89
161.65
288.64
103,316,352
2
63.10
80.96
145.81
51,658,176
128
1.01
1.27
6.82
807,159
1024
0.17
0.23
7.84
100,894
4096
0.03
0.16
6.86
25,223
16,384
0.02
0.18
6.87
6,305
524,288
0.00
0.22
7.35
198
Note:
Reads and writes are atomic. That is they will not be
interrupted once started. That is a write to a file will be allowed to
complete before another read or write operation can occur. *How is this
accomplished by the operating system?) This is important for
multithreaded and multiprocess applications.
The pread and pwrite function
calls
These calls combine seek and a read or write in a single
operation. Why???
The readv and writev function
calls
These calls allow us to read and write vectors of data.
Why?? Maybe later.
Informationen
- Beschreibung
- CMPS 315 Unix Environment Notiz am Lecture 02 – 10/3/2016, erstellt von Lisa Lini am 03/10/2016.
- Erstellt von
- Lisa Lini · Okt 2016
- Aktualisiert
- 7 Mär 2018
- Aufrufe
- 1
- Tags
- Bewertung