UMBC CMSC 313 -- File Input/Output Previous | Next


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