Unlike the FILE descriptor used in advanced FILE programming, the FILE descriptor used in low-level FILE programming is a non-negative integer. 1. file opening and creation # include & lt; fcntl. h & gt; intopen (constchar * filename, character flag ,... /* mode_tmode */); -- filena...
Unlike the FILE descriptor used in advanced FILE programming, the FILE descriptor used in low-level FILE programming is a non-negative integer.
1. open and create a file
# Include
Int open (const char * filename, int oflag,.../* mode_t mode */);
-- Filename specifies the path name for opening or creating a file;
-- Oflag specifies how to open or create a file.
-- Mode is an optional parameter that determines the mode of the new file. it is only valid when the file is created.
When the function is called successfully, a file descriptor is created for the file filename and returned; otherwise,-1 is returned;
The parameter oflag controls the reading and writing modes of open files {1. O_RDONLY, O_WRONLY, O_RDWR}, General mode, and synchronization mode;
2. close and delete files
Function close closes an opened file and function unlink deletes the file. their prototype is:
# Include
Int close (int fildes );
Int unlink (char * path );
Note: You can only use a temporary file once. you can delete it before using it, so you don't have to worry about deleting the file and causing junk files on the disk.
/* ----- Use the temporary file template unlink. c -----*/
# Include
# Include
# Include
Void main ()
{
Int fno;
If (fno = open ("./tmpfile", O_RDWR | O_CREAT | O_EXCL, 0755) <0)
{
Fprintf (stderr, "open file error! /N ");
Return;
}
Unlink ("./tmpfile ");
Sleep (60 );
Printf ("end./n ");
}
3. file read/write
# Include
Ssize_t read (int fildes, void * buff, size_t nbytes );
Ssize_t write (int fildes, const void * buff, size_t nbytes );
/* The read function reads the data of nbytes bytes from the file pointed to by the file descriptor fildes to the memory pointed to by the buff. If the read operation succeeds, the function returns the number of bytes actually read. if the file ends or the value of the parameter nbytes is 0, the function returns 0. If an error occurs during the call, the function returns-1, and write the error code to errno. */
/* Write the memory data pointed to by the buff to write nbytes bytes to the file pointed to by the file descriptor fildes. If the write operation succeeds, the function returns the number of bytes actually written. Otherwise,-1 is returned and the error is written to errno */
/* -------- Read. c ------*/
# Include
Void main ()/
{
Char buff [11];
Printf ("% d", read (0, buf, sizeof (buf )));
}
/* --------- Write. c -----*/
# Include
Void main ()
{
Char buf [10] = "abcchina ";
Printf ("% d", write (1, buf, sizeof (buf )));
}
4. file location
# Include
Off_t lseek (int fildes, off_t offset, int whence );
Instance: the lseek function allows you to locate the maximum position of the current file. if the location is successful and data is written, the file is automatically extended to the write location, and the middle part is filled with 0. However, if the location is much larger than the current file length, the UNIX operating system only falsely adds the file length and does not actually allocate disk blocks. The following example shows how to design a virtual file:
# Include
# Include
Void main ()
{
Int fno;
If (fno = open ("hole. dat", O_WRONLY | O_CREAT, 0755) <0)
{
Printf ("open file hole. dat failed./n ");
Return;
}
Lseek (fno, 1000000000, SEEK_SET );
Write (fno, "eee", 3 );
Close (fno );
}
5. file Buffering
The fsync function writes the buffer information to the file. its prototype is:
# Include
Int fsync (int fildes );
The system calls fsync to write all data written into the file descriptor fildes to a disk or other devices. similar to the standard file, the system returns 0 if the system call is successful. Otherwise, the system returns-1.
6. copy the file descriptor
The function for copying a file descriptor in a low-level file programming library is as follows:
# Include
Int dup (int fildes );
Int dup2 (int fildes, int fildes2 );
The dup function copies the file descriptor fildes to the currently unused minimum available descriptor. The dup2 function copies the file descriptor fildes to the descriptor fildes2. if fildes2 is enabled, it is disabled. if fildes2 is equal to fildes, it is returned directly. The two functions return the new file descriptor when the call is successful. otherwise,-1 is returned.
7. File Control
1) file lock
File locks are an important part of multi-user multi-task operating systems. When updating files, you expect to use a mechanism to prevent the loss of files in the same region when both processes update the files at the same time, or prevent the file content from being read when it is not updated. this mechanism is a file lock.
During file operations, a process can use a file lock to lock the sensitive part of the file to prevent other processes from unauthorized operations on the part of the data. The fcntl function provides the ability to lock any part of the file, which can lock all files and some records of the file. Therefore, the file lock becomes a "record Lock ".
You can distinguish between the read lock and write lock based on the access method of the file lock. A read lock, also known as a shared lock, is used to prevent the file records read by the process from being changed. Multiple read locks can be set for file records at the same time. However, when one read lock exists, the write lock cannot be set for this record.
The write lock, also known as mutex, is used to ensure that file changes are not disturbed, ensure file consistency and integrity, and prevent write loss or read "dirty" data. Once a write lock is set for a file record, no more lock can be set unless the write lock is in contact.
Multiple read locks can be set for file records at the same time. Only one write lock can be set for a single record, and the read and write locks cannot coexist.
When the fntl function is dedicated to lock operations, its prototype is:
Int fcntl (int fildes, int cmd, struct flock * arg );
Here, the structure flock is used to describe the file lock information, defined in "fcntl. h", as shown below:
Struct flock
{
Short l_type;/* lock type. The value can be F_RDLCK, F_WRLCK, or F_UNLCK, which respectively indicate applying for a read lock, applying for a write lock, and releasing a lock */
Short l_whence;/* the relative location of the start address of the lock area, similar to the whence parameter in lseek. The value is one of SEEK_SET SEEK_CUR SEEK_END, indicates the start position, current position, and end position of the relative File */
Long l_start;/* start address offset of the lock region, which is determined by l_whence */
Long l_len;/* length of the lock. 0 indicates that the lock ends at the end of the file */
Long l_pid;/* id of the locked process */
};
When the function fcntl is used for locking, the cmd parameter has three values:
F_GETLK
F_SETLK
F_SETLKW
{File locks are typically used in two aspects: the critical data in a locked file, such as the number of votes recorded in the file during concurrent voting; the second is the use of mutually exclusive write locks, implement process Concurrency Control}
2) file lock operation
In the use of the lock mechanism, the most common operations include lock requests, release and testing. these operations are basically similar
(1) test the lock
The design function SeeLock is used to query the lock information of the file corresponding to the file descriptor fd. its prototype is:
Void SeeLock (int fd, int start, int len );
Function query the lock information in len bytes starting from the offset start of the file corresponding to the descriptor fd
/* ---- Test source code ---- lock1.c ----*/
Void SeekLock (int fd, int start, int len)
{
Struct flock arg;
Arg. l_type = F_WRLCK;
Arg. l_whence = SEEK_SET;
Arg. l_start = start;
Arg. l_len = len;
If (fcntl (fd, F_GETLK, & arg) =-1)
Fprintf (stderr, "See Lock failed./n ");
Else if (arg. l_type = F_UNLCK)
Fprintf (stderr, "no lock from % d TO % d, n", start, len );
Else if (arg. l_type = F_WRLCK)
Fprintf (stderr, "write lock from % d TO % d, id = % d/n", start, len, arg. l_pid );
Else if (arg. l_type = F_RDLCK)
Fprintf (stderr, "read lock from % d To % d, id = % d/n", start, len, arg. l_pid );
}
(2) apply for a read lock
GetReadLock, a shared lock application function, is prototype:
Void GetReadLock (int fd, int start, int len );
Apply for a shared read lock in the file descriptor fd corresponding to the file in blocking mode. len bytes starting from the offset start in the locked area
/* --- Block requests for shared read lock source code --- lockl. c */
Void GetReadLock (int fd, int start, int len)
{
Struct flock arg;
Arg. l_type = F_RDLCK;
Arg. l_whence = SEEK_SET;
Arg. l_start = start;
Arg. l_len = len;
If (fcntl (fd, F_SETLKW, & arg) =-1)
Fprintf (stderr, "[% d] Set Read Lock failed./n", getpid ());
Else
Fprintf (stderr, "[% d] Set Read Lock From % d To % d", getpid (), start, len );
}
(3) apply for a write lock
Void GetWriteLock (int fd, int start, int len );
/* --- Block requests for shared write lock source code --- lockl. c */
Void GetReadLock (int fd, int start, int len)
{
Struct flock arg;
Arg. l_type = F_WRLCK;
Arg. l_whence = SEEK_SET;
Arg. l_start = start;
Arg. l_len = len;
If (fcntl (fd, F_SETLKW, & arg) =-1)
Fprintf (stderr, "[% d] Set Write Lock failed./n", getpid ());
Else
Fprintf (stderr, "[% d] Set Write Lock From % d To % d", getpid (), start, len );
}
(4) release the lock
Design the file lock release function ReleaseLock, prototype:
Void ReleaseLock (int fd, int start, int len );
/* --- Release lock source code --- lockl. c */
Void GetReadLock (int fd, int start, int len)
{
Struct flock arg;
Arg. l_type = F_UNLCK;
Arg. l_whence = SEEK_SET;
Arg. l_start = start;
Arg. l_len = len;
If (fcntl (fd, F_SETLKW, & arg) =-1)
Fprintf (stderr, "[% d] UnLock failed./n", getpid ());
Else
Fprintf (stderr, "[% d] UnLock From % d To % d", getpid (), start, len );
}
The following is an example of a file lock control process:
# Include
# Include
Void main ()
{
Int fd;
Struct flock arg;
(Fd = open ("/tmp/tlockl", O_RDWR | O_CREAT, 0755) <0)
{
Fprintf (stderr, "open file failed./n ");
Retrun;
}
SeeLock (fd, 0, 10 );
GetReadLock (fd,);/* apply for a read lock */
SeeLock (fd, 11,20 );
GetWriteLock (fd, 11,20);/* apply for a write lock */
Sleep (30 );
ReleaseLock (fd, 0, 10 );
ReleaseLock (fd, 11,20 );
}
8. read/write function library encapsulation through the function library
This type of function includes blocking read/write and timed read/write.
1) blocked read/write function library
(1) ReadFile
This function controls the number of bytes read from a file. its prototype is:
Int ReadFile (int nFile, void * pData, int * pSize );
The function reads nSize bytes of data from the file indicated by the file descriptor nFile to the memory pData. the function returns only when an error occurs or all data is read.
(2) WriteFile
This function controls the number of bytes written to the write file. the prototype is:
Int WriteFile (int nFile, void * pData, int nSize );
/* ----------- File. c ----------*/
Int ReadFile (int nFile, void * pData, int * pSize)
{
Int nLeft, nRead;
Char * pcData = pData;
ASSERT (pData! = NULL & pSize! = NULL );
NLeft = * pSize;
While (nLeft> 0)
{
If (nRead = read (nFile, pcData, nLeft) <0)
{
If (errno! = EINTR) ASSERT (0 );
NRead = 0;
}
Else if (nRead = 0) break;
NLeft-= nRead;
PcData + = nRead;
}
* PSize = * pSIze-nLeft;
Return 0;
}
/* The error code EINTR in the program indicates that the system call read is interrupted by a signal singal before reading data. you can continue the read operation */
2) blocked read/write function library application instances
The program reads the keyboard input. the function returns only when a certain number of characters are read, as shown below:
# Include
Void main ()
{
Char buf [11];
Int size = sizeof (buf );
ReadFile (0, buf, & size );
Printf ("% d", size );
}
Author "pstary"