File input and output and related functions
1. Workflow of C library IO function
C language operation file related issues:
Use a fopen
function to open a file and return a FILE* fp
structure 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
inode
through 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.h
At line 48 of the header file :typedef struct _IO_FILE FILE
;
-
libio.h
At line 241 of the header file :struct _IO_FILE
, there is a_fileno
member in this connector body definition, which is the file descriptor.
The relationship between C library functions and system functions
via: man 2 write
view write
function
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
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
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:
pathname
The parameter is the name of the file to be opened or createdfopen
,pathname
which can be either a relative path or an absolute path.
flags
The 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 allO_
represented by beginning withor
. -
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_APPEND
means 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.
②CreateO_CREAT
this 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_EXCL
If it is specified at the same timeO_CREAT
and the file already exists, an error will be returned.
⑤O_TRUNC
If the file already exists, truncate its length to0
bytes.
⑥O_NONBLOCK
For the device file,O_NONBLOCK
open in this way can do non-blockingI/O(NonblockI/O)
, non-blockingI/O
. -
Function return value:
success: return a minimum and unoccupied file descriptor
Fail: return-1
, and set theerrno
value.
2.2 close
-
Function description: close the file
-
Function prototype:
int close(int fd);
-
Function parameter:
fd
file descriptor -
Function return value: return on
success, return on0
failure-1
, and set theerrno
value.
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 close
close, so even if the user program does not call close
it, 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 storedbuf
in the buffer
count
buf
-
Function return value:
>0
: The number of bytes
=0
read: 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
:buf
length of data in -
Function return value:
success: return the number of bytes written
error: return-1
and seterrno
Four, lseek
All open files have a current file offset ( current file offset
), hereinafter referred to as simply cfo
. cfo
Usually 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, cfo
it 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
errno
It is a global variable. If an error occurs after the system call, it will errno
be set, and perror
the corresponding description information can be errno
printed.
For example: perror("open");
if an error is reported, print: : open
(space) error message
Use the above function
//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;
}
//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;
}
Six, blocking and non-blocking:
Thinking: Are blocking and non-blocking properties of files or properties of read
functions?
-
Normal file:
hello.c
non-blocking by default -
Terminal devices: such as
/dev/tty
default blocking -
Pipes and sockets
block by default
//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!