File Input/Output
Under LINUX, everything is a file. There are actually eight types of files,
for those interested. For this discussion, we will be concerned with
data files on the disk, the keyboard, and the monitor. We also will be
looking at the system calls that are used with those files. In C, you might have
used open/fopen, creat/fcreat, fprintf, fscanf, and close. In reality, they are
wrappers for the system call (overly simplified, of course!) To understand the
system calls, you can look at the code for the kernel. I have included excepts from
the appropriate files to demonstrate some of the values needed. The kernel
source code will be in the directory /usr/src/linux, if it is installed on
your system.
Standard Files
Every process under LINUX is created with three open files. It does not matter
what language created the program being executed, they are Standard In, Standard Out,
and Standard Error. They are the file descriptors of 1, 2, and 3 respectively. They
are normally the keyboard, monitor, and monitor respectively, but they can be redirected.
Redirection does not affect the file descriptors. The standard files do not need
to be opened or closed. All other files must be opened or created, as necessary.
Disk files should be closed as soon as possible to help ensure their integratity.
You can not corrupt a closed file. You might be able to corrupt an open file
if you lose power, or something similar.
I use constants for the names of the standard files:
%define STDIN 0
%define STDOUT 1
%define STDERR 2
System Calls
File System Calls
There are a set of system calls to work with files. These calls are a part
of the kernel and the information on them is in the man pages. Each call
is assigned a number, with all the calls listed in /usr/include/asm/unistd.h:
;; #define __NR_read 3
;; #define __NR_write 4
;; #define __NR_open 5
;; #define __NR_close 6
;; #define __NR_creat 8
File Opening Flags
Once again, I prefer to give these system call numbers a constant name:
%define READ 3
%define WRITE 4
%define OPEN 5
%define CLOSE 6
%define CREATE 8
OPEN is easier to remember that 5.
File Open Flags
In the OPEN call, you need a flag to tell the operating system how you want
the file opened, for read-only, for write-only, or for read-write. The flag
is built from a set of bits that is defined in the operating system. The
information for this is in /usr/include/bits/fcntl.h:
;;
;; O_RDONLY 00
;; O_WRONLY 01
;; O_RDWR 02
Once again, I prefer to give these bit settings a constant name:
%define O_RDONLY 00
%define O_WRONLY 01
%define O_RDWR 02
Parameter Passing to System Calls
The EAX register will contain the the number of the system calls.
Parameters are stored in left to right
order in the registers EBX, ECX, EDX, EDI, and ESI respectively.
Man Page Information
The man pages are divided into sections, and section one is for the user level commands
typed on command line. This is the default. Section two is for system calls and
section three is for library calls. The call is explained in detail and the
man page is definitely a good resource for you. the man pages also go into detail
about the error conditions. To get to the OPEN system call man
pages, type the command after the prompt as:
man 2 open
creat
int creat(const char *pathname, mode_t mode);
;; mov eax, dword CREATE ; System Call -- open
;; mov ebx, myFile1 ; Pointer to filename
;; mov ecx, O_WRONLY ; Flag for Write Only
;; mov edx, 01FDh ; Mode -- 755 in octal
;; int 80h
;; mov dword [ fdWrite ], eax; save the file descriptor
open
int open(const char *pathname, int flags, mode_t mode);
;; mov eax, dword OPEN ; System Call -- open
;; mov ebx, myFile ; Pointer to filename
;; mov ecx, O_RDONLY ; Flag for Read Only
;; mov edx, 0 ; Mode -- not used to open existing file
;; int 80h
;; mov dword [ fdRead ], eax ; save the file descriptor
read
One item of interest here is that the Enter key value (10) in one of the bytes
that is put into the input buffer. You will probably want to remove it by
replacing it with a null.
ssize_t read(int fd, void *buf, size_t count);
;; mov eax, READ ; System Call -- read
;; mov ebx, dword [ fdRead ]; File descriptor opened for reading
;; mov ecx, dword inBuff ; Pointer to input buffer
;; mov edx, dword BUFSIZE ; Number of bytes to read
;; int 80h
;; mov dword [ bytesRead ], eax ; Actual amount read
write
ssize_t write(int fd, const void *buf, size_t count);
;; mov eax, WRITE ; System Call -- write
;; mov ebx, dword [ fdWrite ]; File descriptor opened for writing
;; mov ecx, dword outBuff ; Pointer to output buffer
;; mov edx, dword [ bytesWritten ] ; Number of bytes to write
;; mov 80h
close
int close(int fd);
;; mov eax, CLOSE
;; mov ebx, dword [ fdRead ]
;; int 80h
;;
What is this size_t/ssize_t/mode_t stuff?????
The way that LINUX was written, it is very easy to port to other platforms.
It makes it a little more confusing for beginners to ready. Tracing the
types gives the following information:
;; /usr/src/linux/include/asm-i386/posix_types.h: typedef unsigned short __kernel_mode_t;
;; /usr/src/linux/include/linux/types.h: typedef __kernel_mode_t mode_t;
;; /usr/src/linux/include/asm-i386/posix_types.h: typedef int __kernel_ssize_t;
;; /usr/src/linux/include/linux/types.h: typedef __kernel_ssize_t ssize_t;
;; /usr/src/linux/include/asm-i386/posix_types.h: typedef unsigned int __kernel_size_t
;; /usr/src/linux/include/linux/types.h: typedef __kernel_size_t size_t;
;;
Previous |
Next
©2005, Gary L. Burt