Linux system programming files

1, Open and create

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

int main()
{
        int fd;
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failed\n");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 success\n");
                }
        }
        return 0;
}


Function returns a descriptor

O_RDONLY: readable
O_WRONLY: writable
O_RDWR: readable and writable

ls -l: list all files

-rwxr-xr-x permission
Readable: r 4
Writable: w 2
Execution: x 1
0600 represents 4 + 2 permissions: readable and writable
Give file owner CLC permission

2, File writing
cat file1 view the contents of text file1

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failed\n");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 success\n");
                }
        }
        printf("open success!\n:fd = %d\n",fd);
        write(fd,buf,strlen(buf));
        close(fd);
        return 0;
}



close the file after it is opened and written
Pointer allocation 8 bytes under Linux
The calculated length cannot be sizeof(), but strlen()

3, File reading

#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;
        char *buf = "wo shi nen die!";

        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failed\n");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 success\n");
                }
        }
        printf("open success!\n:fd = %d\n",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1\n",n_write);
        }
        close(fd);
        open("file1",O_RDWR);
        char *readBuf;
        readBuf = (char *)malloc(sizeof(n_write+1));
        int n_read = read(fd,readBuf,n_write);
        printf("read %d byte context:%s",n_read,readBuf);
        close(fd);
       
        return 0;
}

Because file1 needs to be closed and reopened when reading the cursor position to move the cursor to the front before reading.

Buffer read into readBuf

4, Cursor movement

#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;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failed\n");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 success\n");
                }
        }
        printf("open success!\n:fd = %d\n",fd);
        
        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1\n",n_write);
        }

        lseek(fd,0,SEEK_SET);
        
        char *readBuf;
        readBuf = (char *)malloc(sizeof(n_write+1));
        int n_read = read(fd,readBuf,n_write);
        printf("read %d byte context:%s",n_read,readBuf);
        close(fd);
        return 0;
}
~   


SEEK_SET: the cursor moves to the initial position
SEEK_CUR: cursor moves to current position
SEEK_END: the cursor moves to the end of the high

off_t offset: offset the positive number to the right and the negative number to the left

5, Calculate file size with cursor

Returns an offset value from the biting of the file

6, File opens the created supplement

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

int main()
{
        int fd;
        fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
        if(fd == -1)
        {
                printf("file1 exsit\n");
        }
        return 0;
}

O_EXCL: returns - 1 if the file exists (an error occurs if O_CREAT is also specified and the file already exists)

#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;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR|O_APPEND);
        printf("open success!\n:fd = %d\n",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1\n",n_write);
        }
        close(fd);
        return 0;
}
~       

O_APPEND: prevent the file from being overwritten and continue writing on the next line (added to the end of the file every time)

#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;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR|O_TRUNC);
        printf("open success!\n:fd = %d\n",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1\n",n_write);
        }
        close(fd);
        return 0;
}

O_TRUNC: delete all the contents of the original file and write it again

Another create function, create

Macro representation - number
S_IRUSE - 4- readable
S_IWUSR - 2-writable
S_IXUSR - 1-executable
S_IRWXU - 7- readable, writable and executable

7, Brief description of document operation principle
https://baike.baidu.com/item/%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6/9809582?fr=aladdin

Standard input and output

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
        int fd;
        char readBuf[128];
        int n_read = read(0,readBuf,5);
        int n_write = write(1,readBuf,strlen(readBuf));
        printf("\ndone\n");
        return 0;
}

Dynamic file, static file
Traditionally, the file descriptor of standard input is 0, standard output is 1, and standard error is 2

int n_read = read(0,readBuf,5): read 5 characters into readBuf

The file is usually stored in the file system file in the block device. We call this file a static file. When we open a file, the Linux kernel does the following operations: establish a data structure of the open file in the kernel process and record the file we open; The kernel applies for a section of memory in memory, and reads the contents of the static file from the block device to a specific address in the kernel for management storage (called dynamic file)

After the file is opened, the read and write operations on the file are aimed at the dynamic file in memory, not at the static file. After we read and write the dynamic file, the dynamic file in memory is out of sync with the static file in the block device. When we close the dynamic file, the close internal kernel updates (synchronizes) the static file in the block device with the contents of the dynamic file in memory

Why is it designed so that it does not operate directly on block devices
The block device itself is very inflexible. It reads and writes by block, while the memory is operated by byte unit, and can be operated randomly. It is very flexible

8, Realization of cp function of small application

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

int main(int argc,char **argv)
{
        int fdSrc;
        int fdDes;
        char *readBuf = NULL;
        if(argc != 3)
        {
                printf("param error\n");
                exit(-1);
        }

        fdSrc = open(argv[1],O_RDWR);
        int size = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char)*size + 8);
        int n_read = read(fdSrc,readBuf,size);

        fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
        int n_write = write(fdDes,readBuf,strlen(readBuf));

        close(fdSrc);
        close(fdDes);
        return 0;
}

}

9, Modification of configuration file

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
        int fdSrc;
        char *readBuf = NULL;
        if(argc != 2)
        {
                printf("wrong\n");
                exit(-1);
        }

        fdSrc = open(argv[1],O_RDWR);
        int size = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char)*size+8);
        int n_read = read(fdSrc,readBuf,size);

        char *p = strstr(readBuf,"LENG");
        if(p==NULL)
        {
                printf("Not found");
                exit(-1);
        }

        p = p+strlen("LENG=3");
        *p = '5';
        lseek(fdSrc,0,SEEK_SET);
        int n_write = write(fdSrc,readBuf,strlen(readBuf));

        close(fdSrc);

        return 0;
}

}

strstr

The lookup return value is a pointer to the lookup header

10, Write an integer to the file

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

int main()
{
        int fd;
        int data = 100;
        int data2 = 0;

        fd = open("./file1",O_RDWR);

        int n_write = write(fd,&data,sizeof(int));

        lseek(fd,0,SEEK_SET);

        int n_read = read(fd,&data2,sizeof(int));

        printf("data2:%d\n",data2);

        close(fd);

        return 0;
}


This is a pointer data type, so take the address

11, Write structure to file
Change the soup without changing the dressing and take the address, but there may be problems in writing the linked list directly. The linked list is continuous and the structure array is a block

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

struct Test
{
        int a;
        char b;
};

int main()
{
        int fd;
        struct Test data[2] = {{99,'a'},{100,'b'}};
        struct Test data2[2];

        fd = open("./file1",O_RDWR);

        int n_write = write(fd,&data,sizeof(struct Test)*2);

        lseek(fd,0,SEEK_SET);

        int n_read = read(fd,&data2,sizeof(struct Test)*2);

        printf("data2:%d\n,%c\n",data2[0].a,data2[0].b);
        printf("data2:%d\n,%c\n",data2[1].a,data2[1].b);

        close(fd);

        return 0;
}

12, Introduction of standard C library to files
Chapter 10 of the fourth edition of C language
For these two functions with similar names, it is not easy for many beginners to figure out the differences between them. They only know to use them according to the function usage. If you can distinguish them well, I believe you have a deeper understanding of C language and UNIX system (including LINUX).

I found some information on the Internet, but I feel it is not comprehensive enough. Some answers are only explained from a certain angle, so people feel that this is also right and that is also right. But whose statement is more correct? In fact, they are all right, but the perspective of interpretation is different. Let's do some combing based on personal understanding.

  1. source
    From the perspective of source, the two can be well distinguished, which is also the most obvious difference between the two:

open is a UNIX system call function (including LINUX, etc.), and returns a File Descriptor, which is the index of the file in the File Descriptor table.
fopen is a C language library function in ANSIC standard. Different kernel APIs should be called in different systems. Returns a pointer to the file structure.
PS: from the source, the two are inextricably linked. After all, the library functions of C language still need to be implemented by calling the system API.

  1. Transplantability
    It can be inferred from the above sources that fopen is a C standard function, so it has good portability; open is a UNIX system call with limited portability. For similar functions under windows, use the API function CreateFile.

  2. Scope of application
    open returns the file descriptor, which is an important concept in UNIX system. All devices in UNIX operate in the form of files. Such as network sockets, hardware devices, etc. Of course, it includes the operation of ordinary files.
    fopen is used to manipulate regular files.

  3. File IO hierarchy
    From the perspective of file IO, the former belongs to low-level IO functions and the latter belongs to high-level IO functions. The simple distinction between low-level and high-level is: who is closer to the system kernel. Low level file IO runs in kernel mode and high-level file IO runs in user mode.

  4. buffer
    Buffered file system
    The characteristics of buffered file system are: opening a "buffer" in memory for each file in the program; When reading a file, read the data from the disk file into the memory "buffer", fill it up, and then read the required data from the memory "buffer". When writing a file, write the data to the memory "buffer" first, and then write the file after the memory "buffer" is full. It can be seen that the size of the memory "buffer" affects the actual number of external memory operations. The larger the memory "buffer", the less the number of external memory operations, the faster the execution speed and the higher the efficiency. In general, the size of the file "buffer" depends on the machine. fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind, etc.
    Unbuffered file system
    Buffer file system manages files with the help of file structure pointer, and accesses files through file pointer. It can not only read and write characters, strings, formatted data, but also read and write binary data. The non buffered file system depends on the operating system. It reads and writes files through the functions of the operating system. It is a system level input and output. It does not set a file structure pointer and can only read and write binary files, but it is efficient and fast. Because the ANSI standard no longer includes the non buffered file system, it is recommended that you should not choose it. open, close, read, write, getc, getchar, putc, putchar, etc.
    In a word, open has no buffer and fopen has buffer. The former is used with read, write, etc., while the latter is used with fread,fwrite, etc.

Using the fopen function, since there is a buffer in the user state, the switching between the user state and the kernel state is reduced when reading and writing files (switching to the kernel state calls still need to call the system call API:read, write); When using the open function, you need to switch between kernel state and user state every time when reading and writing files; It is shown that if files are accessed sequentially, fopen series functions are faster than directly calling open series functions; If the file is accessed randomly, the opposite is true.

After such a summary, I believe you have a more comprehensive and clear understanding of the two functions and series of functions, and you should also know what kind of functions are more appropriate and efficient under what circumstances.

13, Open the standard C library, create a read-write file, and move the cursor

#include <stdio.h>
#include <string.h>

int main()
{
        FILE *fd;
        char *buf = "wo shi nen die";
        char readBuf[128] = {0};
        fd = fopen("./zhang.txt","w+");

        fwrite(buf,sizeof(char),strlen(buf),fd);

        fseek(fd,0,SEEK_SET);

        fread(readBuf,sizeof(char),strlen(buf),fd);

        printf("%s",readBuf);

        fclose(fd);

        return 0;
}



fd = fopen("./zhang.txt","w+");
w+ : Pay attention to double quotes
int write = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);

int nread = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);
The return value depends on the third parameter, which is slightly different

14, Standard C library writes structure to file

#include <stdio.h>
#include <string.h>
struct Test
{
        int a;
        char c;
};

int main()
{
        FILE *fd;

        struct Test data = {100,'a'};
        struct Test data2;

        fd = fopen("./file1","w+");

        fwrite(&data,sizeof(struct Test),1,fd);

        fseek(fd,0,SEEK_SET);

        fread(&data2,sizeof(struct Test),1,fd);

        printf("%d,%c",data2.a,data2.c);

        fclose(fd);

        return 0;
}

15, Supplement
fputc:

#include <stdio.h>
#include <string.h>

int main()
{
        int i;
        int len;
        FILE *fp;
        char *str = "wo shi nen die";
        len = strlen(str);
        fp = fopen("./test.txt","w+");
        for(i=0;i<len,i++)
        {
        fputc(*str,fp);
        str++;
        }

        fclose(fp);
        return 0;

}

feof: determine whether to reach the tail of the file
fgetc

Return 0 when file tail is reached

#include <stdio.h>

int main()
{
        FILE *fp;
        char c;
        fp = fopen("./test.txt","r");

        while(!feof(fp)) //! Reverse
        {
                c = fgetc(fp);
                printf("%c",c);
        }

        fclose(fp);

        return 0;

}

Tags: C C++ Linux

Posted on Sun, 12 Sep 2021 22:41:45 -0400 by Sk~