File input and output and related functions


1. Workflow of C library IO function

insert image description here

insert image description here

C language operation file related issues:

Use a fopenfunction to open a file and return a FILE* fpstructure that this pointer points to has three important members:

  • File descriptor: The file can be found through the file description , and the corresponding data block can be found inodethrough it.inode

  • File pointer: Read and write share a file pointer, and reading or writing will cause the file pointer to change.

  • File buffer: Read or write will first pass through the file buffer, the main purpose is to reduce the number of reads and writes to the disk and improve the efficiency of reading and writing to the disk.

Remark:

  • stdio.hAt line 48 of the header file : typedef struct _IO_FILE FILE;
    insert image description here insert image description here

  • libio.hAt line 241 of the header file : struct _IO_FILE, there is a _filenomember in this connector body definition, which is the file descriptor.
    insert image description here

The relationship between C library functions and system functions

insert image description here
via: man 2 writeview writefunction
insert image description here

System call: A programming interface implemented by the operating system and provided to external applications,
(Application Programming Interface, API)which is a bridge for data interaction between applications and the system.

1.1 Virtual Address Space

insert image description here

The virtual address space of a process is divided into a user area and a kernel area. The kernel area is protected, and users cannot read or write it;
a very important part of the kernel area is process management, and there is an area in process management. It is the PCB (essentially a structure);
there is a file descriptor table in the PCB, and the file descriptor table stores open file descriptors, which are used for IO operations involving files.

1.2 pcb and file descriptor table

insert image description here

Remarks:
pcb: structure: task_stuct, the structure is in:
/usr/src/linux-headers-4.4.0-97/include/linux/sched.h:1390
A process has a file descriptor table: 1024
top three One is occupied, namely STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO
file descriptors Function: find inodes through file descriptors, and find disk data blocks through inodes.

Virtual Address Space Kernel Area PCB File Description Table File Descriptor File IO Operation Using File Descriptor

1.3 File descriptors

After a process starts, three file descriptors are opened by default:

#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

The newly opened file returns the smallest unused file descriptor in the file descriptor table. Calling the open function can open or create a file and get a file descriptor.

Two, open / close

2.1 open

  • Function description: Open or create a new file

  • Function prototype:
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);

  • Function parameters:
    pathnameThe parameter is the name of the file to be opened or created fopen, pathnamewhich can be either a relative path or an absolute path.
    flagsThe parameter has a series of constant values ​​to choose from, and multiple constants can be selected at the same time to be connected with the bitwise OR operator, so the macro definitions of these constants are all O_represented by beginning with or.

  • Required: One of the following three constants must be specified, and only one is allowed.
    O_RDONLY 只读打开
    O_WRONLY 只写打开
    O_RDWR 可读可写打开

  • The following optional items can be specified at the same time, 0 or more, and the required items are bitwise ORed together as the flags parameter
    . There are many optional items, only a few common options are introduced here:
    O_APPENDmeans append. If the file already has content, the data written to open the file this time is appended to the end of the file without overwriting the original content.
    ②Create O_CREATthis file if it does not exist. When using this option, you need to provide the third parameter mode, which indicates the access permission of the file.
    ③ Final permission of the file: mode & ~umask
    O_EXCLIf it is specified at the same time O_CREATand the file already exists, an error will be returned.
    O_TRUNCIf the file already exists, truncate its length to 0bytes.
    O_NONBLOCKFor the device file, O_NONBLOCKopen in this way can do non-blocking I/O(NonblockI/O), non-blocking I/O.

  • Function return value:
    success: return a minimum and unoccupied file descriptor
    Fail: return -1, and set the errnovalue.

2.2 close

  • Function description: close the file

  • Function prototype:int close(int fd);

  • Function parameter: fdfile descriptor

  • Function return value: return on
    success, return on 0
    failure -1, and set the errnovalue.

  It should be noted that when a process is terminated, the kernel calls all file descriptors that have not been closed for the process to closeclose, so even if the user program does not call closeit, the kernel will automatically close all the files it opened when it terminates. But for a program that runs for many years (such as a network server), the open file descriptor must be remembered to close, otherwise, as more and more files are opened, it will take up a lot of file descriptors and system resources.

三、read / write

3.1 read

  • Function description: Read data from an open device or file

  • Function prototype:ssize_t read(int fd, void *buf, size_t count);

  • Function parameters:
    fd: File descriptor
    buf: The read data is stored in the buffer : the maximum number of bytes stored bufin the buffer
    countbuf

  • Function return value:
    >0: The number of bytes
    =0read: the file is read
    -1: error, and seterrno

3.2 write

  • Function description: Write data to the open device or file

  • Function prototype:ssize_t write(int fd, const void *buf, size_t count);

  • Function parameters:
    fd: file descriptor
    buf: buffer, data to be written to file or device
    count: buflength of data in

  • Function return value:
    success: return the number of bytes written
    error: return -1and seterrno

Four, lseek

  All open files have a current file offset ( current file offset), hereinafter referred to as simply cfo. cfoUsually a non-negative integer, used to indicate the number of bytes from the beginning of the file to the current position of the file. Read and write operations usually start at cfo, and Increases cfo by the number of bytes read and written. When the file is opened, cfoit is initialized to 0, unless used O_APPEND.

**使用 lseek 函数可以改变文件的 cfo.**
>#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

* 函数描述: 移动文件指针

* 函数原型: off_t lseek(int fd, off_t offset, int whence);

* 函数参数:
fd:文件描述符

* 3.0参数 offset 的含义取决于参数 whence:
如果 whence 是 SEEK_SET,文件偏移量将设置为 offset。
如果 whence 是 SEEK_CUR,文件偏移量将被设置为 cfo 加上 offset,offset 可以为正也可以为负。
如果 whence 是 SEEK_END,文件偏移量将被设置为文件长度加上 offset,offset 可以为正也可以为负。

* 函数返回值: 若lseek成功执行, 则返回新的偏移量。

lseek函数常用操作

* 文件指针移动到头部
lseek(fd, 0, SEEK_SET);

* 获取文件指针当前位置
int len = lseek(fd, 0, SEEK_CUR);

* 获取文件长度
int len = lseek(fd, 0, SEEK_END);

* lseek实现文件拓展
off_t currpos;
// 从文件尾部开始向后拓展1000个字节
currpos = lseek(fd, 1000, SEEK_END); 
// 额外执行一次写操作,否则文件无法完成拓展
write(fd, “a”, 1);	// 数据随便写

5. perror and errno

errnoIt is a global variable. If an error occurs after the system call, it will errnobe set, and perrorthe corresponding description information can be errnoprinted.
For example: perror("open");if an error is reported, print: : open(space) error message

Use the above function
insert image description here

//IO函数测试--->open close read write lseek
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
    
    
        //打开文件
        //int fd = open("./test.log",O_RDWR | O_CREAT,0777);
        int fd = open(argv[1],O_RDWR | O_CREAT,0777);
        if(fd<0)
        {
    
    
                perror("open error");
                return -1;
        }

        //写文件
        //ssize_t write(int fd,const void *buf,size_t count);
        write(fd,"hello world",strlen("hello world"));

        //移动文件指针到文件开始处
        //off_t lseek(int fd,off_t offset,int whence);
        lseek(fd,0,SEEK_SET);

        //读文件
        //ssize_t read(int fd,void *buf,size_t count);
        char buf[1024];
        memset(buf,0x00,sizeof(buf));
        int n = read(fd,buf,sizeof(buf));
        printf("n==[%d],buf==[%s]\n",n,buf);

        //关闭文件
        close(fd);

        return 0;
}

insert image description here
insert image description here
insert image description here

insert image description here

//lseek函数获取文件大小
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
    
    
        //打开文件
        //int fd = open("./test.log",O_RDWR | O_CREAT,0777);
        int fd = open(argv[1],O_RDWR);
        if(fd<0)
        {
    
    
                perror("open error");
                return -1;
        }

        //调用lseek函数获取文件大小
        int len = lseek(fd,0,SEEK_END);
        printf("file size:[%d]\n",len);

        //关闭文件
        close(fd);

        return 0;
}

insert image description here

Six, blocking and non-blocking:

Thinking: Are blocking and non-blocking properties of files or properties of readfunctions?

  • Normal file: hello.c
    non-blocking by default

  • Terminal devices: such as /dev/tty
    default blocking

  • Pipes and sockets
    block by default

insert image description here
insert image description here

insert image description here

//read函数测试阻塞
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
    
    
        //打开文件
        //int fd = open("./test.log",O_RDWR | O_CREAT,0777);
        int fd = open(argv[1],O_RDWR);
        if(fd<0)
        {
    
    
                perror("open error");
                return -1;
        }



        //读文件
        //ssize_t read(int fd,void *buf,size_t count);
        char buf[1024];
        memset(buf,0x00,sizeof(buf));
        int n = read(fd,buf,sizeof(buf));
        printf("FIRST: n==[%d],buf==[%s]\n",n,buf);

        memset(buf,0x00,sizeof(buf));
        n = read(fd,buf,sizeof(buf));
        printf("SECOND: n==[%d],buf==[%s]\n",n,buf);
        //关闭文件
        close(fd);

        return 0;
}
//read函数测试阻塞
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(int argc,char *argv[])
{
    
    
        //打开文件
        //int fd = open("./test.log",O_RDWR | O_CREAT,0777);
        int fd = open("/dev/tty",O_RDWR);
        if(fd<0)
        {
    
    
                perror("open error");
                return -1;
        }



        //读文件
        //ssize_t read(int fd,void *buf,size_t count);
        char buf[1024];
        memset(buf,0x00,sizeof(buf));
        int n = read(fd,buf,sizeof(buf));
        printf("FIRST: n==[%d],buf==[%s]\n",n,buf);

        memset(buf,0x00,sizeof(buf));
        n = read(fd,buf,sizeof(buf));
        printf("SECOND: n==[%d],buf==[%s]\n",n,buf);
        //关闭文件
        close(fd);

        return 0;
}

Summarize

I look forward to your communication with me, leave a message or private message, learn together and make progress together!

Guess you like

Origin blog.csdn.net/CltCj/article/details/123621578