📄 filesys.doc
字号:
dData1 = 0
dData2 = 0
-------------------------------
SetFileLFA(dHandle, dLFA): dError
DESC: This sets the current LFA (file pointer) for Stream Access files. An error occurs if the file is opened for Block access. The file LFA can not be set past the End Of File (EOF). The file will be set to EOF if you specifiy 0FFFFFFFF hex (-1 for a signed long value in C).
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
dLFA - a DWord with the LFA you want to set. 0FFFFFFFF hex will set the current LFA to End Of File.
Request Parameters for SetFileLFA:
wSvcCode = 8
nSend = 0
pData1 = 0
cbData1 = 0
pData2 = 0
cbData2 = 0
dData0 = dHandle
dData1 = dLFA
dData2 = 0
-------------------------------
GetFileSize(dHandle, pdSizeRet): dError
DESC: This gets the current file size for files opened in any access mode.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
pdSizeRet - a pointer to a DWord where the current size of the file will be returned.
Request Parameters for GetFileLFA:
wSvcCode = 9
nSend = 0
pData1 = pdSizeRet
cbData1 = 4
pData2 = 0
cbData2 = 0
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
SetFileSize(dHandle, dSize): dError
DESC: This sets the current file size for Stream and Block Access files. The file length (and allocated space on the disk) will be extended or truncated as necessary to accomidate the size you specify. The current LFA is not affected for Stream files unless it is now past the new EOF in which case it is set to EOF automatically.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
dSize - a DWord with the new size of the file.
Request Parameters for SetFileSize:
wSvcCode = 10
nSend = 0
pData1 = 0
cbData1 = 0
pData2 = 0
cbData2 = 0
dData0 = dHandle
dData1 = dSize
dData2 = 0
-------------------------------
CreateFile
Procedural Interface:
CreateFile (pName, dcbname, dAttributes): dError
Desc: This creates a new empty file in the path specified. The file is closed after creation, and ready to be opened and accessed.
Params:
pName - pointer to the filename or full file specification to create.
dcbName - DWord with length of the filename
dAttributes - A DWord with one of the following values:
0 = Normal File
2 = Hidden File
4 = System File
6 = Hidden, System file
Request Parameters for CreateFile:
wSvcCode = 11
nSend = 1
pData1 = pName
cbData1 = dcbName
pData2 = 0
cbData2 = 0
dData0 = dAttributes
dData1 = 0
dData2 = 0
-------------------------------
RenameFile
Procedural Interface:
RenameFile (pName, dcbname,
pNewName dcbNewName): dError
Desc: This renames a file. The file must not be opened in any mode (by anyone).
Params:
pName - pointer to the current filename or full file specification.
dcbName - DWord with length of the current filename
pNewName - pointer to the new filename or full file specification.
dcbName - DWord with length of the new filename
Request Parameters for RenameFile:
wSvcCode = 12
nSend = 1
pData1 = pName
cbData1 = dcbName
pData2 = pNewname
cbData2 = dcbNewname
dData0 = 0
dData1 = 0
dData2 = 0
-------------------------------
DeleteFile
Procedural Interface:
DeleteFile (dHandle): dError
Desc: This deletes a file from the system. No further access is possible, and the filename is available for reuse.
The file must be opened in MODIFY mode (which grants exclusive access).
Params:
dHandle - a DWord that was returned from OpenFile.
Request Parameters for DeleteFile:
wSvcCode = 13
nSend = 0
pData1 = 0
cbData1 = 0
pData2 = 0
cbData2 = 0
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
CreateDirectory
Procedural Interface:
CreateDirectory (pPath, dcbPath): dError
Desc: This creates a new empty directory for the path specified. The path must comtain the new directory name as the last element. This means all subdirectories above the last directory specified must already exist. If only the new directory name is specified (as opposed to a full path), the directory is created in your current path (specified in the Job Control Block).
Params:
pPath - pointer to the path (direcotry name) to create.
dcbPath - DWord with length of the path
Request Parameters for CreateDirectory:
wSvcCode = 14
nSend = 1
pData1 = pPath
cbData1 = dcbPath
pData2 = 0
cbData2 = 0
dData0 = 0
dData1 = 0
dData2 = 0
-------------------------------
DeleteDirectory
Procedural Interface:
DeleteDirectory (pPath, dcbPath, fAllFiles): dError
Desc: This deletes a directory for the path specified. The path must comtain the directory name as the last element. If only the existing directory name is specified (as opposed to a full path), the name is appended to the path from your Job Control Block (Current path).
All files and subdirectories will be deleted if fAllFiles is NON-ZERO.
Params:
pPath - pointer to the path (direcotry name) to delete.
dcbPath - DWord with length of the path
fAllFiles - If set to NON-ZERO, all files in this directory, all subdirectories, and files in subdirectories will be deleted.
Request Parameters for DeleteDirectory:
wSvcCode = 15
nSend = 1
pData1 = pPath
cbData1 = dcbPath
pData2 = 0
cbData2 = 0
dData0 = 0
dData1 = 0
dData2 = 0
-------------------------------
GetDirSector
Procedural Interface:
GetDirSector ( pPath, dcbPath,
pSectRet, dSectNum): dError
Desc: Directories on the disk are one or more sectors in size. Each sector contain 16 directory entries. This call returns one sector from a directory. You specifiy which logical directory sector you want to read (from 0 to nTotalSectors-1).
A single directory entry looks like this (16 per sector):
Name 8 Bytes
Ext 3 Bytes
Attribute 1 Byte
Reserved 10 Bytes
Time 2 Bytes
Date 2 Bytes
StartClstr 2 Bytes
FileSize 4 Bytes
Fields are read and used exactly as MS-DOS uses them.
Params:
pPath - pointer to the path (directory name) to delete.
dcbPath - DWord with length of the path
pSectRet - a pointer to a 512 byte block where the directory sector will be returned.
dSectNum - a DWord with the logical sector number to return.
Request Parameters for GetDirSector:
wSvcCode = 16
nSend = 1
pData1 = pPath
cbData1 = dcbPath
pData2 = pSectRet
cbData2 = 512
dData0 = dSectNum
dData1 = 0
dData2 = 0
The INNER WORKINGS
Internal File System Structures
The file system has several internal structures it uses to manage the logical disks and open files.
FILE CONTROL BLOCK
Every file system has some structure that is used to manage an open file. Quite a few of them use this same name (FCB).
The MMURTL FAT file system allocates file system structures dynamically when it is initialized. The maximum number of open files is currently limited by this initial allocation to 128 open files.
MMURTL starts with an initial 4Kb (one memory page) of FCBs. Each FCB is 128 bytes. Each opened file is allocated an FCB. If the file is opened in Stream mode, we allocate a one page buffer for reading and writing (4Kb).
The FCB actually contains a copy of the 32 byte directory entry from the disk (this is read in when the file is opened).
FILE USER BLOCKS
Because MMURTL is multitasking, the FCB is not directly associated with the job that opened the file. Another structure called the File User Block (FUB) is what links the user of a file to the FCB.
There is one FUB for each instance of a user with an open file.
The FUBs contain the file filepointer (where the user is currently reading or writing in the file), the open mode, buffer pointers, and other things that are required to manage the user's link to the file. The file handle is actually a pointer to the FUB. Because it is a pointer, extra checking is done to ensure it is valid in every call (a "pointer in space" could do some real damage here if we let it).
The FCB keeps track of the number of FUBs for the file. When it reaches 0, the FCB is deallocated for reuse.
FAT BUFFERS
In the FAT file system, the location of every cluster (1 or more sectors) of a file is managed in a linked list (of sorts). This linked list is contained in a table called the File Allocation Table. A more acurate name would be cluster allocation table because its actually allocating clusters of disk space to the files (it's not allocating files...).
The disk is allocated in clusters, with each cluster having an associated entry in the FAT. On most hard disks, they use what is called a FAT16. This means each FAT entry is a 16 bit word. The beginning of the FAT represents the beginning of the useable data area on the logical disk.
Lets look at an example of how you use the FAT to locate all parts of file on the disk. In our example, we'll assume that each FAT entry is worth 4Kb on disk (cluster size), and we'll assume the file size is 12Kb (3 entries).
Assume the directory entry we read says the first FAT entry is number 4.
X = not our file.
L = Last entry in our file.
FAT POSITIONS 1 2 3 4 5 6 7 8 9 10
Entry in FAT X X X 5 6 L
This means our file occupies the 4th, 5th and 6th cluster in the data area on the disk. The 4th entry "points" to the 5th, the 5th points to the 6th, and the 6th is marked as the last. Ever get LOST CLUSTERS when you ran a Chkdsk in MS-DOS? Who hasn't? It usually means it found some clusters pointing to other clusters that don't end, or it found a beginning with no corresponding directory entry pointing to it.
From this example you can see that every file we access will require a minimum of two disk accesses to read the file UNLESS the piece of the FAT you need is already in memory.
This means it's important to attempt to keep as much FAT information in memory as you can and juggle it wisely. If your disk isn't too badly fragmented, and you are sequentially reading all of a file into memory (such as loading an executable file (called a RUN file in MMURTL), you can usually do it quite rapidly. Just 1Kb of FAT space represents 2Mb of data space on the disk if clusters are 4Kb. A badly fragmented disk can force as many as 4 or 5 accesses to different parts of the FAT just to read one file.
The disk controller (IDE/MFM) can read 256 contiguous sectors in one read operation. That's 128Kb. That's a lot of FAT (or file). However, becuase of the design of the FAT file system, the actual contguous read will usually be limited to the size of a cluster.
A great number of files are read and written sequentially. Run files being executed, source files for compilers, the initial filling of buffers for a word processor (and the final save usually), vector, and raster image files... the list could go on and on. Large database files are the major random users (and only a good "level 4 mind reader" knows where in a 150 Mb file the user will strike next).
MMURTL's DOS FAT file system allocates FAT buffer (1Kb in size) based on file access patterns. A simple LRU (least recntly used) algorithym ensures the most accessed FAT sectors will remain in memory.
Reading a file is a multipart process. Let's look what the filesystem has to go through to open, read and close a file:
OPEN
1) Look through the FCBs to see if someone already has it open in ModeRead. If so, allocate an FUB and attach it. If it's open in ModeWrite, return an error (ErcFileInUse).
2) Locate the directory entry and read it into the FCB. Directories are stored as files. This means that we have to go to the FAT to find where the whole directory is stored so we can look through it. This is in itself is time consuming.
3) Load FAT buffer if required. The first cluster of the file is listed in the directory entry. From this we calculate which disk sector in the FAT has this entry and we read it into the FAT buffer (if not already in one). The file is open.
READ
What actually happens on a read depends on whether the file is opened in block or stream mode. If opened in block mode, we simply issue the read to the device driver to read the sectors into the caller's buffer (locating them using the FAT). The hardware is limited to 128Kb reads in one shot, and can only do this if 128Kb of the file is located in contiguous sectors. Usually, the commands to the device driver will be broken up into several smaller reads as the file system finds each contiguous section listed in the FAT.
CLOSE
This is the easy part. We deallocate the FLB and FCB.
======= End of File System Documentation =======
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -