File descriptor correlation function summary dup2 dup

Keywords: C Linux

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;	
}

Posted by gregghealy on Mon, 20 Sep 2021 00:21:12 -0700