Analysis of Linux file programming

file right

① Readable r
② Writable w
③ Executable x
It can also be expressed in numbers: r=4, w=2, x=1. So 7=rwx

ls -l    //View current directory file properties

The operation results are as follows:

-rwxrw-r-- 1 xdq book 1 Sep  7 16:41 read.c

10 characters are used to determine different user permissions. It is divided into four parts: type, file owner, file owner, user in the same group, and other users.

  • The first character represents file (-), directory (d), and link (l)
  • The first group rwx: the permissions of the file owner are readable, writable and executable
  • The second group rw-: the permissions of users in the same group of file owners are readable and writable
  • The third group r –: the permissions of other users are read only

File descriptor

1. For the kernel, all open files are referenced by file descriptors. fd is a nonnegative integer. When an existing file is opened or a new file is created, the kernel returns a file descriptor to the process. When reading and writing a file, use the file descriptor returned by open or create to identify the file and pass it to read and write as parameters. Default file descriptors included in Linux system:

0 Standard input   
1 standard output     
2 Standard error
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
        char readBuf[128];

        read(0,readBuf,5);
        write(1,readBuf,strlen(readBuf));
        printf("\n");

        return 0;
}

2. The number file descriptor represents a specific meaning in a process. When a file is open ed, the operating system constructs a data structure in memory to represent the dynamic file, and then returns a number to the application as a file descriptor, which is bound to the data of the dynamic file in memory. For subsequent operations, dynamic files only need to be distinguished by this file descriptor.

3. The scope of the file descriptor is the current process. The open function returns a file descriptor after successfully opening a file. If it fails, it returns - 1.

Basic flow of linux file operation

① Open / create file
② Read / write file
③ Close file

File operation analysis

1. First use the open function to open the file, open it successfully to get the file descriptor, then read and write (or other) the file, and finally use the close function to close the file. If the file is not closed, the file will be damaged.

2. Files stored in the block device file system are called static files. When opening a file, the kernel creates a data structure (structure) in the process to record the open file; At the same time, apply for a section of memory to extract the contents of the static file from the block device to a specific address in the kernel for storage and management (dynamic file).

3. After opening a file, all operations on the file are aimed at dynamic files. After the operation on the dynamic file is completed, the contents of the dynamic file and the static file do not match. When the file is closed, the kernel updates the contents of the dynamic file to the static file.

4. Why?
Block devices operate on blocks and memory operates on bytes. When modifying, you can only operate on the whole block, not on a single byte.

Open / create file (open)

Function prototype:

Parameter Description:
pathname: the name of the file opened / created (including the path)
flags: how to open a file

Main category:
O_RDONLY    read-only
O_WRONLY    Write only
O_RDWR      Readable and writable        //Only one of the three can be selected

Subcategory:
O_CREAT     If the file does not exist, it is created
O_EXCL      If used O_CREAT Option and the file exists, an error message is returned(-1)  
O_TRUNC     If the file already exists, delete the existing data in the file
O_APPEND    Open in append mode and add to the end of the file
O_NOCTTY    If the file is a terminal, the terminal cannot call open The control terminal of the process called by the system

mode: file permissions when creating files
Return value:
The file descriptor is returned successfully, and - 1 is returned for failure
example:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
        int fd;
        fd = open("./file1",O_RDWR|O_CREAT,0600);
 		printf("fd = %d\n",fd);
        if(fd == -1){
                printf("error!\n");
                exit(-1);
        }

        return 0;
}

Operation results:

fd = 3
-rw------- 1 xdq book    0 Sep  7 17:21 file1     //View via ls -l

close file

When operating (reading and writing) a file, you need to close the file after the operation, otherwise the file will be damaged.
Function prototype:

Parameter Description:
fd: file descriptor

Write file (write)

Function prototype:

Parameter Description:
fd: file descriptor
buf: buffer for writing content
count: number of bytes written
Return value:
- 1 is returned if no content is written, and the number of bytes is returned if the content is successfully written

  • Note: if there is content in the file and it is not processed when the file is opened, the original content will be overwritten

read file

Function prototype:

Parameter Description:
fd: file descriptor
buf: buffer for reading content
count: number of bytes read
Return value:
The number of bytes read is returned after successful reading. If the cursor returns 0 at the end of the file, it returns - 1 if it fails

File cursor offset (lseek)

When reading and writing a file, the cursor will constantly shift. When the content is written, the cursor shifts to the end of the file. At this time, the content cannot be read. You need to move the cursor to the file head to read normally.
Function prototype:

Parameter Description:
fd: file descriptor
Offset: offset value (number of bytes offset). Offset can be negative. Positive values offset backward, negative values offset forward)
Where: offset the base position (offset bytes on this basis)

whence Is one of the following:
SEEK_SET File header
SEEK_CUR Current file location
SEEK_END End of file

Return value:
The offset value is returned successfully, and - 1 is returned for failure

Comprehensive example

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        int fd;
        ssize_t n_write;
        ssize_t n_read;
        char *writeBuf = "hello world!";
        char *readBuf;

        //Open / create file
        fd = open("./file1",O_RDWR|O_CREAT,0600);
        printf("fd = %d\n",fd);
        if(fd == -1){
                printf("error!\n");
                exit(-1);
        }

        //Write file
        n_write = write(fd,writeBuf,strlen(writeBuf));
        printf("n_write = %d\n",(int)n_write);

        //Cursor offset
        lseek(fd,0,SEEK_SET);

        //read file
        readBuf = (char *)malloc(n_write);
        n_read = read(fd,readBuf,n_write);
        printf("n_read = %d   txt:%s\n",(int)n_read,readBuf);

        //Close file
        close(fd);
        
        return 0;
}

Operation results:

fd = 3
n_write = 12
n_read = 12   txt:hello world!

Keywords: C Linux

Added by bouncer on Tue, 07 Sep 2021 22:58:51 +0300