Day4
lseek
#include <sys/types.h> #include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
- Setting File Position Pointer
- The location function of the return value file pointer is similar to ftell
Exercise 1: Implementing a function for calculating file size on a Linux system using system calls
homework
Exercise 2: Implement a cp command with coverage check
homework
dup/dup2
#include <unistd.h>
int dup(int oldfd);
- Copy the file descriptor, and the operating system will select a small return from the unused file descriptor
- oldfd Copied File Descriptor
int dup2(int oldfd, int newfd);
- Copy the specified file descriptor, and if newfd is already in use, close it before copying it
- oldfd
- newfd
- Return
#include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> void init(void){ int fd = open("log.txt",O_RDWR|O_CREAT|O_APPEND,0644); dup2(fd,1);//If it is 0, you can read a line from the log using gets } int main(){ init();//After init, printf() prints directly to log.txt int fd = dup(2);//When fd = 1/2 (STDOUT/STDERR), the data written to fd will be printed directly. write(fd,"hello",5); }
Comparison of Standard IO and System IO
Exercise 3 uses standard IO and system IO to write 100,000 integers to files randomly. Which method is faster and why? homework
Standard IO uses buffer technology, and every time the system IO is invoked, the user state and the kernel state are switched.
File synchronization
sync/fsync/fdatasync
There are usually some buffers on the hard disk to improve the efficiency of data writing. In fact, the data written by the operating system is only written to the buffer, and it is not queued to write to the hard disk until the buffer is full.
This operation reduces the number of writes, but increases the latency of data writes, resulting in data in the buffer not synchronizing with the contents of the disk.
Note that all the buffers mentioned here refer to hard disk caching
void sync(void);
- Synchronize all data in all buffers to disk
- Note that commands that synchronize data to disk are not returned after execution, but immediately after the command is issued.
int fsync(int fd);
- Buffer data of specified df file is synchronized to disk, only for one file. Data is synchronized to disk before returning.
int fdatasync(int fd);
- Specifies that the buffer data of the df file is synchronized to disk, but only the data of the file is not synchronized with the properties of the file
fcntl
int fcntl(int fd,int cmd,.../* arg */);
- cmd operation instructions, different operation instructions determine the number and type of subsequent parameters
- Note that this is a function of variable length parameters.
int fcntl(int fd,int cmd, long newfd);
- cmd F_DUPFD
- Copy the file descriptor to operate on the same file as fd
- Return value returns newfd if newfd is not used; if nrefd is occupied, return a file descriptor no less than newfd
Exercise 1: Using fcntl to realize the function of DUP and dup2
homework
int fcntl(int fd, int cmd, void/long);
-
Setting or Getting File Descriptor Flags
-
cmd
- F_GETFD
- F_SETFD
At present, only FD_CLOEXEC flag can be set.
-
Return value 0. The new process remains open, and 1. Close the file descriptor in the new process.
int fcntl(int fd, int cmd, void/long);
- Get the file status flag (the permission to open the current file and how to open it)
- cmd:
-
F_GETFL void
- O_CREAT,O_EXCL,O_NOCTTY,O_TRUNC are not available
- The return value has an int type state with a file status flag, which needs to be associated with each flag.
-
F_SETFL long
- Only O_APPEND,O_ASYNC,O_DIRECT,O_NOATIME,O_NONBLOCK can be set.
- Return Value Success 0 Failure-1
-
F_GETFL void
#include <...> void file_flags(int fd){ struct Flags{ int flag; char* name; }flags[] = { {O_RDONLY,"O_RDONLY"}, {O_WRONLY,"O_WRONLY"}, {O_RDWR,"O_RDWR"}, {O_APPEND,"O_APPEND"}, {O_ASYNC,"O_ASYNC"}, {O_CLOEXEC,"O_CLOEXEC"}, {O_SYNC,"O_SYNC"} }; int flags = fcntl(fd,F_GETFL); for(int i=0;i<sizeof(flags)/sizeof(flags[0]);i++){ if(flags[i].flag&flag) printf("%s\n",flags[i].name); } } int main(){ int fd = open("A.TXT",O_WRONLY|O_RDONLY|O_SYNC|O_CLOEXEC); fcntl(fd,F_SETFL,O_ASYNC); file_flags(fd); close(fd); }
int fcntl(int fd, int cmd, struct* flock);
- Lock the file, so that the whole file, or part of it, can be accessed.
- cmd
- F_GETLK Gets Lock Information
- F_SETLK Setting Lock
- F_SETLKW Test Lock
- Read lock and read lock do not conflict, read lock and write lock conflict, write lock and write lock conflict
- Locking does not make other processes unable to open files or operate, but users must abide by the lock agreement to ensure that the files are not mixed (warning lock)
struct flock { ... short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* Starting offset for lock */ off_t l_len; /* Number of bytes to lock */ pid_t l_pid; /* PID of process blocking our lock (set by F_GETLK and F_OFD_GETLK) */ ... };
#include <...> int rlock(int fd){ struct flock lock = {F_RDLOCK,SEEK_SET,0,0,-1}; return fcntl(fd,f_SETLK,&lock); } int wlock(int fd){ struct flock lock = {F_WRLOCK,SEEK_SET,0,0,-1}; return fcntl(fd,f_SETLK,&lock); } void show_lock(int fd){ struct flock lock = {}; printf("Acquisition locks%s\n",fcntl(fd,F_GETLK,&lock)?"fail":"Success"); if(lock.l_type == F_UNLCK){ printf("No lock\n"); }else{ printf("Locking process:%d\n",lock.l_pid); printf("Lock type:%s\n",lock.l_type == F_RDLOCK?"Read lock":"Write lock"); printf("From documents"); switch(lock.l_whence){ case SEEK_SET:printf("Start with the document");break; case SEEK_CUR:printf("From the current position");break; case SEEK_END:printf("From the end of the document");break; } if(lock.l_start > 0){ printf("Right shift%lu Begin with a byte",lock.l_start); }else if(lock.l_start < 0){ printf("Left shift%lu Begin with a byte",lock.l_start); } if(lock.len){ printf("Lock up%lu Bytes\n",lock.l_len); } else{ printf("Lock to the end of the file\n"); } } } int main(){ int fd = open("a.txt",O_RDWR); printf("%d\n",rlock(fd)); printf("%d\n",getpid()); getchar(); }