Embedded Linux Development - (4) File I/O Basics

Series Article Directory



foreword

Everything under Linux is a file. As the core concept of Linux system design, files are particularly important under Linux system, so the I/O operation on files is both the foundation and the most important part. This chapter will introduce you to the concept of file descriptors in the Linux system, and then explain the system calls that constitute the general I/O model one by one, such as opening files, closing files, reading data from files, writing data to files, and these The parameters involved in the system call, etc.

1. File descriptor

This is an int type of data. When the open function is executed successfully, it will return a non-negative integer. The return value is a file descriptor, which means that the file descriptor is a non-negative integer. All opened files will pass A file descriptor is an index.
We can use the ulimit command to view the maximum number of files that a process can open:

ulimit -n

The default value is 1024.
When calling the open function to open a file, the allocated file descriptors generally start from 3, because the first three have been allocated:

  • 0: system standard input
  • 1: standard output
  • 2: standard error

Standard input generally corresponds to the keyboard, which can be understood as 0 is the file descriptor obtained when opening the device file corresponding to the keyboard; standard output generally refers to the LCD display, which can be understood as 1 is to open the device file corresponding to the LCD device The file descriptor obtained when; and the standard error generally refers to the LCD display

二、open、close、read、write、lseek、perror、exit、_exit、_Exit、pread、pwrite、fcntl、ioctl、truncate、fruncate

open

Function prototype:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

Function parameter return value meaning:
pathname : string type, used to identify the file to be opened or created, which can contain path (absolute path or relative path) information; if pathname is a symbolic link, it will be dereferenced.
flags : The flags that need to be provided to call the open function include file access mode flags and other file-related flags.
The flags parameters of the open function are as follows
Please add a picture description
Please add a picture description
: O_APPEND, O_ASYNC, O_DSYNC, O_NOATIME, O_NONBLOCK, O_SYNC, O_TRUNC, etc.
O_TRUNC flag: When the open function is called to open the file, all the original content of the file will be discarded, and the file size will become 0.
O_APPEND: Every time the write() function is used to write to a file, the offset of the current position of the file will be automatically moved to the end of the file, and data will be written from the end of the file.

mode : This parameter is used to specify the access rights of the newly created file. It is only valid when the flags parameter contains the O_CREAT or O_TEMPFILE (O_TEMOFILE flag is used to create a temporary file) flag. Parameter type: mode_t (32-bit unsigned integer data), the permission expression method is as follows:
insert image description here
We look at the lower bits from the top, and the 3 bits are divided into one group, which respectively represent:
O—represents the authority of other users;
G— Indicates the authority of the same group user (group), that is, all users with the same group ID as the file owner;
U—indicates the authority of the user to whom the file belongs, that is, the owner of the file or directory;
S—indicates the special authority of the file;
the highest bit ( The weight is 4) means read permission, 1 means read permission, 0 means no read permission; the middle bit (weight 2) means write permission, 1 means write permission, 0 means no write permission ;The lowest bit (with a weight of 1) indicates the execution permission, when it is 1, it means that it has the execution permission, and when it is 0, it does not have the execution permission.
The file permission macro of the open function is as follows:
Please add a picture description
Return value : If successful, the file descriptor will be returned, and the file descriptor is a non-negative integer; if it fails, -1 will be returned;

write write file

Function prototype:

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

Function parameters :
fd : file descriptor.
buf : Specifies the buffer corresponding to the written data.
**count:** Specifies the number of bytes written.
**Return value:** If it succeeds, it will return the number of bytes written (0 means no bytes have been written), if this number is less than the count parameter, it may be that the disk space is full; if it is wrong, it will return - 1.

read read file

Function prototype :

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

Function parameters and return value:
fd : file descriptor.
buf : Specifies the buffer used to store the read data.
count : Specifies the number of bytes to read.
Return value : If successful, the number of bytes to be read will be returned, and 0 will be returned when the end of the file is read.

close closes the file

Function prototype :

#include <unistd.h>
int close(int fd);

Function parameters and return value :
fd : file descriptor.
Return value : Returns 0 if successful, returns -1 if failed.

lseek file offset

Function prototype :

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

Function parameters and return values :
fd : file descriptor
offset : offset, in bytes
whence : reference value used to define offset offset, this parameter is one of the following:

  • SEEK_SET : The read and write offset points to the offset byte position.
  • SEEK_CUR : The read and write offset will point to the current position offset + offset byte position, offset can be positive or negative,
    if it is positive, it means backward offset, if it is negative, it means forward offset;
  • SEEK_END : The read and write offset will point to the end of the file + offset byte position. Similarly, offset can be positive or negative. If it is a positive number, it means a backward offset, and if it is a negative number, it means a forward offset.

Return value : If successful, it will return the position offset (in bytes) from the beginning of the file, that is, the current read and write position; if an error occurs, it will return -1.

perror view error message

Function prototype :

#include <stdio.h>
void perror(const char *s);

Function parameters and return value :
s: Before the error prompt string information, you can add your own print information, or you can not add it, and if you don’t add it, just pass in an empty string.
Return value: void no return value

exit、_exit、_Exit

exit() : Library function, terminate the process
** _exit() **: Calling the _exit() function will clear the memory space used by it, destroy its various data structures in the kernel, and close all file descriptors of the process , and terminate the process, passing control to the operating system. The _exit() function prototype is as follows:

#include <unistd.h>
void _exit(int status);
#include <stdlib.h>
void _Exit(int status);

Note : Both functions are system calls

pread and pwrite

Function prototype :

#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

Function parameters and return value :
fd, buf, count parameters have the same meaning as the read or write function.
offset : Indicates the current position offset that needs to be read or written.
Return value : The return value has the same meaning as the return value of the read and write functions.
⚫ When the pread function is called, its positioning and reading operations (that is, atomic operations) cannot be interrupted;
⚫ The current position offset in the file table is not updated.

fcntl

Function : The fcntl() function can perform a series of control operations on an opened file descriptor, such as copying a file descriptor (same as dup and dup2), getting/setting the file descriptor flag, getting/setting the file status flag etc., similar to a multifunctional file descriptor management toolbox.
Function prototype :

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ )

Function parameters and return value :
fd : file descriptor.
cmd : Operation command. For example:
⚫ Duplicate File Descriptor (cmd=F_DUPFD or cmd=F_DUPFD_CLOEXEC);
⚫ Get/Set File Descriptor Flags (cmd=F_GETFD or cmd=F_SETFD);
⚫ Get/Set File Status Flags (cmd=F_GETFL or cmd=F_SETFL );
⚫ get/set asynchronous IO ownership (cmd=F_GETOWN or cmd=F_SETOWN);
⚫ get/set record lock (cmd=F_GETLK or cmd=F_SETLK);
return value : in case of execution failure, return -1 and set errno; if the execution is successful, the return value is related to cmd (operation command), for example, cmd=F_DUPFD (duplicate file descriptor) will return a new file descriptor, cmd=F_GETFD (get file descriptor flag) will return File descriptor flags, cmd=F_GETFL (get file status flags) will return file status flags, etc.

ioctl

Function : Generally used to operate special files or hardware peripherals.
Function prototype :

#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);

Function parameters and return value :
fd:: file descriptor.
request : Indicates that the corresponding operation is requested from the file descriptor.
: Used with request.
Return value : returns 0 on success, -1 on failure.

truncate()和fruncate()

Function: It can truncate ordinary files to the specified byte length.
Function prototype :

#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

length<file length, excess data will be lost.
length>file length, expand the multi-part, and read the extended part to get a null byte "\0". The call
returns 0 if it succeeds, and -1 if it fails, and sets errno to indicate the cause of the error.

3. Simple programming examples

(1) Open an existing file (such as src_file) and use the read-only mode; then open a new file (such as dest_file) and use the write-only method. The permissions of the new file are set as follows: the owner of the file has read, write,
execute Permissions;
users in the same group and other users only have read permissions.
Read 1Kbyte byte data from the 500-byte offset header of the src_file file, and then write the read data into the
dest_file file, starting from the beginning of the file, 1Kbyte byte size, after the operation is completed Use close to explicitly close all files and exit the program.

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

int main(){
    
    
  char data[1024];
  /*打开文件1*/
  int fd1  = open("./data.txt",O_RDWR,S_IRWXU|S_IRGRP|S_IROTH);
  if(-1 == fd1)
    printf("file no exist!");
  /*文件偏移量指到500*/
  lseek(fd1,500,SEEK_SET);
  /*读取文件1的1024个数据*/
  read(fd1,data,sizeof(data));
  //printf("%d",(int)sizeof(data));
  /*打开文件2*/
  int fd2 = open("./data2.txt",O_WRONLY);
  if(-1 == fd2) printf("open fd2 error!");
  /*写入数据*/
  int rec = write(fd2,data,sizeof(data));
  if(-1 == rec){
    
    
    printf("write error!\r\n");
  }
  else printf("write corrent!\r\n");
  /*关闭文件*/
  close(fd1);
  close(fd2);
  return 0;
}

(2) Use the open function to judge whether the file exists (such as test_file), and display the judgment result.

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

int main(){
    
    
	/*打开文件,如果文件存在则返回-1,如果不存在则创建该文件*/
    int fd = open("./test_file",O_RDONLY|O_CREAT|O_EXCL);
    if(-1 == fd) printf("the file exist!\r\n");
    return 0;
}

(3) Create a new file (such as new_file), and set the permissions of the new file as follows: the
owner of the file has read, write, and execute permissions;
users in the same group and other users only have read permissions.
Open the file in write-only mode, fill the first 1Kbyte data of the file with 0x00, fill the next 1Kbyte data with 0xFF, close the file explicitly after the operation is completed, and exit the program.

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

int main(){
    
    
    char start[1024];
    /*以只写方式打开文件,文件所属者拥有读、写、执行权限;*/
    int fd = open("./new_file.txt",O_WRONLY|O_CREAT,S_IRWXU|S_IRGRP|S_IROTH);
    if(-1 == fd) printf("OPEN ERROR!");
    /*写入0x00*/
    memset(start,0x00,sizeof(start));
    int fwr = write(fd,start,sizeof(start));
    if(-1 == fwr) printf("WRITE ERROR!");
    /*写入0xFF*/
    memset(start,0xFF,sizeof(start));
    fwr = write(fd,start,sizeof(start));
    if(-1 == fwr) printf("WRITE SECOND ERROR!");
    close(fd);
    printf("FILE CLSOE!");
    return 0;
}

(4) Open an existing file (such as test_file), calculate the size of the file through the lseek function, and print it out.

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

int main(){
    
    
    int i = 0;
    char data;
    /*以只读方式打开文件*/
    int fd = open("./data2.txt",O_RDONLY);
    if(-1 == fd) printf("OPEN ERROR!");
	/*将文件指针从开头读取到末尾,读取到末尾会返回0*/
    while(read(fd,&data,1)){
    
    
        lseek(fd,1,SEEK_CUR);
        i++;
        printf("%d\r\n",i);
    }
    close(fd);
    printf("THE FILE HAVE %d bite\r\n",i);
    return 0;
}

Summarize

The above has a preliminary understanding of the file system in Linux, mainly learning the usage of several functions: open, close, read, write, lseek, and practicing a few chestnuts.

Guess you like

Origin blog.csdn.net/qq_52608074/article/details/127535733