1. What is a file descriptor?
1. Nonnegative integer.
2. Represents an open file.
3. Returned by the system call (open) and referenced by the kernel space (subsequent system calls).
4. The kernel opens three file descriptors for each process by default:
- stdin 0 - standard input
- stdout 1 - standard output
- stderr 2 - standard error
These three descriptors can also be modified, which will be described later
File descriptors range from 0 to open_ Between Max and open in traditional Unix_ Max macro is defined as 63, and modern Linux uses a larger upper limit.
2. Opening and closing of file descriptor
#include <fcntl.h> int open (//Create file and read file const char* pathname, // route int flags, // pattern mode_t mode // Permissions (only valid for creating files) ); int open ( const char* pathname, // route int flags // pattern }; // Commonly used for reading and writing files /*int creat (//A function of creating files is generally not used const char* pathname, // route mode_t mode // jurisdiction ); // Commonly used to create files*/ The above successfully returns the file descriptor as small as possible, and the failure returns-1. #include <unistd.h> int close ( int fd // File descriptor );//Close file descriptor 0 is returned for success and 0 is returned for failure-1. flags Is the bit or of the following values: O_RDONLY - Read only.\ O_WRONLY - Just write. > Select only one O_RDWR - Read and write. | O_APPEND - Add./ //When using o_ The mode bit parameter can only be filled in during create, such as: 0666 O_CREAT - Create if it does not exist(If it already exists, open it directly, And retain the original content unless...), With this bit mode Parameter is valid. //These two are matching O_CREAT's O_EXCL - Exclusion, if it already exists, it will fail.\ > Just choose one, O_TRUNC - Empty, empty if it already exists / coordination O_CREAT use (yes O_WRONLY/O_RDWR).
Here we have to talk about the octal permission code of mod bit
- The permissions of the mod bit are represented by octal
- The system can mask some permissions set by the process with a permission mask
0666 (RW RW RW -) & ~ 0022 = 0644 (rw-r -- R --) (because it is octal, the front 0 cannot be omitted to represent octal) - 6 = 110 4 = 100 2 = 010, and so on. Each octal number corresponds to a three digit binary code
- mod sets the permissions of three users
Bits 1-3 are primary permissions
Bits 4-6 are the permissions of people in the same group as the owner
Bits 7-9 are other user permissions
In fact, there is another representative in front of the real permission. The file formats are
d folder | link Block b device file p pipeline file
- Ordinary file c character device file s sets of interface documents - r read w write x execution
3. File reading and writing
write
#include <unistd.h> ssize_t write ( int fd, // File descriptor const void* buf, // buffer size_t count // The number of bytes expected to be written is unsigned ); The number of bytes actually written is returned successfully, and the number of bytes written in failure is returned-1.
read
#include <unistd.h> ssize_t read ( int fd, // File descriptor void* buf, // buffer size_t count // Number of bytes expected to be read ); The number of bytes actually read is returned successfully, and the number of bytes read in failure is returned-1
Implement a copy
#include <stdio.h> #include <sys/fcntl.h> #include <unistd.h> #include <string.h> #include <errno.h> int copy(const char *srcFileName,const char *destFileName){ int sfd = open(srcFileName,O_RDONLY); if(sfd == -1){ printf("%s\n",strerror(errno)); return -1; } int dfd = open(destFileName,O_WRONLY|O_CREAT|O_EXCL,0644); if(dfd == -1){//access stat fstat if(errno == EEXIST){//This file exists, do you want to overwrite it printf("%s File exists!\n",destFileName); }else{ printf("%s\n",strerror(errno)); } close(sfd); return -1; } char str[128] = {}; ssize_t ret; while((ret = read(sfd,str,128))>0){ write(dfd,str,ret); } close(sfd); close(dfd); return 0; } //cp int main(int argc,char *argv[]){ if(argc < 3){ printf("%s srcfile destfile\n",argv[0]); return -1; } copy(argv[1],argv[2]); return 0; }
4. Standard library IO
1. When the system call function is executed, it is necessary to switch between user state and kernel state. Frequent calls will lead to performance loss.
2. The standard library makes necessary optimization, maintains a buffer internally, and synchronizes the buffer with the system kernel only when specific conditions are met, so as to reduce the frequency of executing system calls, reduce the number of process switching back and forth between user state and kernel state, and improve the running performance. (the difference between fread and read is that read will call the memory content of the specified size, but fread will call more content than the specified content, thus reducing the switching time.)
#include <stdio.h> int main () { FILE* fp = fopen ("stdio.dat", "wb"); if (! fp) { perror ("fopen"); return -1; } unsigned int i; for (i = 0; i < 100000; i++) fwrite (&i, sizeof (i), 1, fp); fclose (fp); return 0; }
5,lseek
Change file read location
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/fcntl.h> //SEEK_ Start with set //SEEK_CUR current //SEEK_END end int main(){ int fd1 = open("a.txt",O_WRONLY|O_APPEND); int fd2 = open("a.txt",O_WRONLY|O_APPEND); int fd3 = dup(fd1); lseek(fd1,0,SEEK_END); //end printf("%ld\n",lseek(fd1,0,SEEK_CUR));//Return position printf("%ld\n",lseek(fd2,0,SEEK_CUR)); printf("%ld\n",lseek(fd3,0,SEEK_CUR)); char str[100] = "Hello wrold"; write(fd1,str,strlen(str));//Write at end lseek(fd1,0,SEEK_END); lseek(fd2,0,SEEK_END); lseek(fd3,0,SEEK_END); printf("%ld\n",lseek(fd1,0,SEEK_CUR)); printf("%ld\n",lseek(fd2,0,SEEK_CUR)); printf("%ld\n",lseek(fd3,0,SEEK_CUR)); return 0; }