In C Programing Language, by calling fopen() function we can open or create a file. The first parameter of fopen() is the path of the file. With this path, the system will start from the inode of the root or current directory. By looking into the i_zone in the inode, system will find the file inode or the inode of the file directory (when the file does not exist, which means we will create a file in this directory). Here we only talk about creating file.
Firstly, we need to create a inode in the directory. We find an empty item on the inode list–inode_table. The inode_table denotes the currently being used files (in Linux 0.11, the whole system can only open st most 32 files at the same time). If there is no empty item in inode_table, the process will sleep to wait. Using the inode bitmap to find the unused inode number, if all the number have been used, return failed to create file. Binding the empty item in inode_table with the inode and add file name and inode number to the i_zone of the directory inode. Note: here we have not write the file to the disk, we just write the file to the buffer block. Then the system bind the new inode with one unused item in filp of the current process. In every process’s task structure, there is an array filp denoting the files being opened by the process. In Linux each process can open at most 20 files at the same time. And the normal return value of fopen() is the index of the file in filp.
With the fd returned by the fopen(), we can find the inode of the file. And using the i_zone of the inode, we can find the block number of the disk. For reading operation, we directly read the data on the disk to the buffer block, and then copy this data to the buffer of the user process. For the writing operation, we write the data to the buffer block.
This is simple operation, when we calls the fclose() function. The system will unbind the file inode with the corresponding item of filp. If there is still some asynchronous data about the file, the system will synchronize this data to the buffer block.
By using the system call unlnk(), we can delete a file. With the input path, we can find the file inode and directory inode. We set the inode number of the corresponding file in the i_zone of directory inode as 0. So we can not asscee the file by path. And then minus the i_nlink of the file inode by 1, and synchronize these changes to the buffer block. At this time, the file has not been deleted, because the file inode is still on the disk, and we has not changed the logical block bitmap has not been changed. Only when the i_nlink becomes 0, the file will be deleted.
When the i_nlink becomes 0, the system will find the logical block number of the file data and make them available and then release the inode number from the inode bitmap.
All the operations we have talked about have not change the disk. All the changes are on the buffer block. The system will synchronize the buffer block with the disk in two conditions.
- Update process. When the system execute the shell process for the first time. The shell will start a update process, the process will synchronize the buffer block with the disk once in a while.
- When the system is running out of buffer (some buffer blocks have been written, but not been used right now), the system will synchronize all the buffer blocks with the disk.
Synchronization has two steps:
- Write the data of inode_table to buffer blocks;
- Write the data in all the buffer blocks to disk.
In condition 1, the synchronization will be executed at order of 1,2. In condition 2, the synchronization will be executed at order of 2,1,2. Because step 1 will write data to the buffer block, but the system is running out of buffer at this time. So, it will clear the buffer first.