Transcript lesson07

The ‘system-call’ ID-numbers
How can Linux applications
written in assembly language
create and access files?
A Modern OS Design
Application
Application
Application
Shared Runtime Libraries
user-mode
supervisor-mode
System Call Interface
memory
manager
process
manager
file
manager
network
manager
Device Driver Components
OS Kernel
Hardware
Role of ‘runtime libraries’
• To understand what role is played by the
kernel’s interface with ‘runtime libraries,’
let’s see how we could go around them.
• We can create a demo-program that does
not need to use the standard C library – it
will perform all their work on its own.
• If you fire your janitor, you will very quickly
come to appreciate all that he did for you!
Apps can call kernel directly
Assembly Language
application
C application
C++ application
Shared Runtime Libraries
user-mode
supervisor-mode
System Call Interface
memory
manager
process
manager
file
manager
network
manager
Device Driver Components
OS Kernel
Hardware
Standard C library functions
• The functions ‘write()’ and ‘exit()’ were not
actually defined within our program-code
• They are examples of ‘external’ functions
• Header-files let the compiler know how to
generate assembler code that calls them
• Their actual definitions are part of the
standard GNU/C runtime-library (‘glibc’)
• The linker connects our code to ‘glibc’
The function ‘prototypes’
ssize_t write( int fd, void * buf, size_t count );
void exit( int status );
The C/C++ compiler needs this information to
correctly generate the machine-code for calls
to these ‘external’ library-functions.
C/C++ type names
• Some data-types used in C and C++ have
sizes that are dependent on the underlying
CPU architecture and OS design, and are
not identical for all platforms and compilers
• A few relevant examples:
– ‘long int’
– ‘size_t’
– ‘ssize_t’
– ‘off_t’
POSIX
• The ‘Portable Operating System Interface’
• Defines a conformance ‘standard’ that lets
application programmers write code which
is ‘portable’ across differing architectures
• Implemented with header-files and shared
runtime libraries
• Documented as an ANSI standard
• Online reference available via ‘man’ pages
Frequently needed functions
• Here are a few of the POSIX standard functions
which are most frequently used by applications:
–
–
–
–
–
–
open()
read()
write()
close()
lseek()
exit()
• It’s advisable to learn them! (will save you time)
Their C function-prototypes
ssize_t read( int fd, void *buf, size_t count );
ssize_t write( int fd, void *buf, int count );
int open( char *fname, int flags, … );
int close( int fd );
off_t lseek( int fd, off_t offset, int whence );
void exit( int status );
NOTE: These POSIX functions correspond
directly to Linux kernel system-calls
Linux x86_64 system-call IDs
• All the Linux system-calls are assigned IDnumbers in this header-file:
</usr/src/linux/include/asm/unistd_64.h>
// System-call examples for x86_64 Linux
#define __NR_read
0
#define __NR_write
1
#define __NR_open
2
#define __NR_close
3
…
#define __NR_lseek
8
…
#define __NR_exit
60
…
function semantics
• We will give a rough general description of
the actions taken by the kernel when these
six frequently needed functions are called
• Additional details about each function can
be found online, using the ‘man’ command
• Example:
$ man 2 read
ssize_t write( int fd, void *buf, size_t count )
• This function asks the kernel to transfer
‘count’ bytes from the array pointed to by
‘buf’ to the previously-opened file specified
by the file-descriptor ‘fd’.
• If the kernel cannot transfer any bytes, it
returns the value -1; otherwise it returns
the number of bytes that the kernel was
able to transfer successfully and advances
the file-pointer accordingly.
ssize_t read( int fd, void *buf, size_t count )
• This function asks the kernel to transfer ‘count’
bytes into the array pointed to by ‘buf’ from the
previously-opened file specified by ‘fd’.
• If the kernel cannot transfer any bytes, it returns
a value of -1 -- unless the file-pointer is already
at the end of the file; otherwise, it returns the
number of bytes successfully transferred and
advances the file-pointer accordingly.
int open( char *fname, int flags, … )
• This function asks the kernel to set up an
internel record establishing a connection
between the file named ‘fname’ and an unused
nonnegative integer known as a file-descriptor,
provided the file’s access permissions allow the
kind of access that is specified by the ‘flags’
argument
• The function returns -1 if it cannot perform this
operation; otherwise, it returns the file-descriptor
value.
• An additional argument when creating a new file
int close( int fd )
• This function asks the kernel to remove
the connection it had previously set up
between the file-descriptor ‘fd’ and the
internal kernel record of an associated file.
• The value -1 is returned if the kernel was
not succesful in performing this operation
(e.g., the file had already been closed);
otherwise, this function returns 0.
off_t lseek( int fd, off_t offset, int whence)
• This function asks the kernel to reposition
the offset of the open file associated with
the file descriptor ‘fd’ to the position given
as ‘offset’ according to the given ‘whence’
directive, as follows:
– SEEK_SET (=0): position is set to ‘offset’
– SEEK_CUR (=1): position += ‘offset’
– SEEK_END (=2): position = EOF + ‘offset’
void exit( int status )
• This function asks the kernel to terminate
the current program, and place the value
of ‘status’ into the internal record that the
kernel had associated with this program
when it was first launched.
• This function will not return any value
(because it does not return at all!)