ITOP4412 development board Android5.1.1 transplantation tutorial

For traditional operating systems, ordinary I/O operations are generally cached by the kernel, and this I/O is called cached I/O. The file access mechanism introduced in this article does not go through the cache of the operating system kernel, and the data is directly transmitted in the disk and application address space, so the file access mechanism is called direct I/O. Linux provides such a file access mechanism. For applications that store the I/O cache in the user address space, direct I/O is a very efficient method.
"Everything is a file in Linux" has been said many times, and it will be mentioned many times later. So before in-depth study, you must master various operations on Linux files, including basic knowledge of reading, writing, and creating.
The supporting videos for this chapter are:
"Video 05_01 File IO Open Operation"
"Video 05_02 File IO Creation Operation"
"Video 05_03 File IO Write Operation"
"Video 05_04 File IO Read Operation"
16.1 Linux Middle IO Introduction to the concept
All I/O operations are done by reading files or writing files. Here, all peripheral devices, including keyboards and displays, are regarded as files in the file system.
What is cache I/O?
Cache I/O is also called standard I/O. The default I/O operation of most file systems is cache I/O. In the cache I/O mechanism of Linux, the operating system will cache the I/O data in the page cache of the file system, that is, the data will be copied to the buffer of the operating system kernel first. Then it will be copied from the buffer of the operating system kernel to the address space of the application. Cached I/O has the
following advantages:
Cached I/O uses the operating system kernel buffer, which separates the application space from the actual physical device to a certain extent.
Cached I/O can reduce the number of disk reads, thereby improving performance.
When the application program tries to read a certain piece of data, if the piece of data is already stored in the page cache, then this piece of data can be returned to the application program immediately, without the actual physical disk read operation. Of course, if the data is not stored in the page cache before the application reads it, then the data needs to be read from the disk to the page cache first. For write operations, the application also writes the data to the
page cache first . Whether the data is immediately written to the disk depends on the write operation mechanism adopted by the application: if the user uses a synchronous write mechanism (synchronous writes) ), then the data will be written back to the disk immediately, and the application will wait until the data is written; if the user uses deferred writes, then the application does not need to wait until the data is all written back To disk, the data only needs to be written to the page cache. In the case of the delayed write mechanism, the operating system will periodically flush the data placed in the page cache to the disk. Unlike asynchronous writes, the delayed write mechanism does not notify the application when the data is completely written to the disk, while the asynchronous write mechanism returns to the application when the data is completely written to the disk. . Therefore, the delayed writing mechanism itself has the risk of data loss, while the asynchronous writing mechanism does not have this concern.
Disadvantages
of cache I/O In the cache I/O mechanism, the DMA method can read data directly from the disk to the page cache, or write data from the page cache directly back to the disk, instead of directly in the application address space and Data is transferred between disks. In this case, data needs to be copied multiple times between the application address space and the page cache during data transfer. The CPU and memory overhead caused by these data copy operations is
very large.
For some special applications, avoiding the operating system kernel buffer and directly transferring data between the application address space and the disk will achieve better performance than using the operating system kernel buffer, as mentioned in the following section The self-caching application that you arrive is one of them.
Tips -A note about file-related knowledge
In Linux, files are very important, so rich file operation functions are provided in the Linux system.
In system programming, only the final API used in programming and the knowledge that must be mastered will be introduced, as well as a lot of file-related knowledge, such as advanced IO, production file system, virtual file system, file sharing, network file system and many more.
If you really want to introduce the entire linux file in detail, there may be thousands of pages of books that can't be introduced, and it will not help you much in the early learning period. The gain is not worth the loss.
The manual will also introduce file-related knowledge in other forms. Sometimes it will introduce step by step how to operate, such as making file system, NFS network boot; sometimes it will introduce how to use it, such as the virtual file system introduced in the kernel tutorial. Wait. If you are interested, you can learn more specific meanings by learning related knowledge in addition to the learning tutorial.
Files are really important for Linux, but everyone has studied the knowledge and experiments in this chapter, and understood other knowledge related to the file system. You can basically solve the problems encountered in Linux programming later.
Function header files
In all Linux systems, if you need to manipulate files, you only need to include the following 4 header files.
#include <unistd.h>
#include <sys/types.h>
#include <sys/
stat.h> #include <fcntl.h>
The above four header files contain functions for opening, closing, creating, reading and writing files, as well as flag bits, and macro variable definitions for data lengths in different 32-bit and 64-bit systems.
16.2 Open File Function Open
will return a file handle when using the open function. The file handle is the unique identifier ID of the file. The operation on the file must start from the read handle.
Let's first look at the two prototypes of the function open.
int open(const char *path, int oflags); The'open
' function with two parameters is mainly used to create files. In section 10.5.5 of this chapter, we will introduce the specific usage together with the file creation function creat and give example.
int open(const char *path, int oflags, mode_t mode); The
open function can establish the access path of a file or device. When opening or creating a file, you can specify
parameters such as file attributes and user permissions.
The first parameter path means: path name or file name. The path name is an absolute path name, such as the device node /dev/leds of the led driver on the development board.
The second parameter oflags means: the action taken to open the file. One of the following three options must be selected.
O_RDONLY File is read only
O_WRONLY File is only write
O_RDWR File is readable and writable
The following are optional.
O_APPEND Each write operation is written to the end of the file.
O_CREAT If the specified file does not exist, create this file
O_EXCL If the file to be created already exists, return -1 and modify the value of errno.
O_TRUNC If the file exists and opened in write/read-write mode, clear the entire contents of the file.
O_NOCTTY If the path name points to a terminal device, do not use this The device is used as a control terminal.
O_NONBLOCK If the path name points to a FIFO/block file/character file, set the file opening and subsequent I/O to nonblocking mode
(nonblocking mode). What is blocking and nonblocking will be introduced later.
The functions of O_NDELAY and O_NONBLOCK are similar, calling O_NDELAY and using O_NONBLOCK function are the same. The third parameter mode means: set the permission to create files.
S_IRUSR, S_IWUSER, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH. Where R: read, W: write, X: execute, USR: user to which the file belongs, GRP: group to which the file belongs, OTH: other users. The third parameter can be directly replaced by a parameter, refer to section 10.4.5 "Linux permissions".
The meaning of the command'chmod 0777 helloworld' used earlier is the same, except that chmod modifies the permissions after the file is created.
Open function code
Write a simple open.c file to test the open function. First add the header file, as shown in the figure below.
First add the header file, as shown in the figure below.

Then the main function is as follows.

The three files opened in the above figure belong to different situations.
/dev/leds already exists in the development board and belongs to the device node of the driver. It will be specifically introduced in the linux driver tutorial.
/bin/test1 and /bin/test2 do not exist.
Use the open function to call the above three files. If an error occurs Print error, then print the handle.
Compile and run the test
in the Ubuntu system, as shown in the figure below, enter the directory "/home/linuxsystemcode/iofile" created in the previous experiment, use the command "mkdir iofile" to create a new iofile folder, copy the source code open.c into it, and enter the newly created The folder iofileopen, as shown in the figure below.

Use the command "arm-none-linux-gnueabi-gcc -o open open.c -static" to compile the open file, as shown in the figure below, use the command "ls" to see that the open executable file is generated.

Here we introduce the method of copying code from U disk, which can also be compiled into the file system. Please refer to section 10.3.5 for the specific method. Open the compiled executable file, copy it to the U disk, start the development board, insert the U disk, load the U disk, and run the program as follows.

As shown in the figure above, you can see the success of opening /dev/leds. This is the kernel driver of the onboard LED. When it is called, the function in the kernel driver is also called. This function will print "LEDS_CTL DEBUG: Device Opened Success!" And "LEDS_CTL DEBUG: DeviceOpened Success!"
and then print the handle ID, /dev/leds fd is 3
calling "/bin/test1" will report an error "open /bin/test1 failed", this way of opening files is standard in linux Usage, almost all open operations on files will add an error warning statement.
Creating "/bin/test2" will print "/bin/test2 fd is 4", indicating that the creation of "/bin/test2" is successful.
Use the command "ls /bin/test2" to check that "test2" should be newly created under the corresponding directory "/bin", as shown in the figure below.

The other "dev/leds" itself exists. As shown in the figure below, this is the device node file of the driver. In the following experiment, we will introduce how to operate and call. In the linux driver experiment, we will introduce how this device node file is generated.

16.3 Create function creat and open
creat function introduction
Regarding the creat function, first of all, the word does not mean to create. The English word created is "create". This is a small spelling error in the early days, but it has been used all the time.
When introducing the open function, you can see that the open function has two forms, one with two parameters and the other with three parameters. In the early days, open had only three parameters. The three-parameter form would cause the open function to fail to open. An uncreated file means that the file cannot be created, so there is this creat function.
Now the creat function can be completely replaced with open. Considering that you may encounter it when reading the code, I will briefly introduce it.
The prototype of the creat function is as follows.
int creat(const char * pathname, mode_t mode); The
creat function has only two parameters, and the meaning of the parameters is similar to that of open. When you see this function, you know that it creates a file, and you can use open instead when writing code.
creat function routine
Write a simple creat.c file to test the creat function. First add the header file as shown below.

Then the main function is shown below.

Line 22, line 27, 31, open can open an existing file, or open a file that does not exist, that is, create a file. When creating a file, you need to add the flag O_CREAT to the parameter. In line 27 of the code, there is no flag bit added, and an error will definitely be reported when running. This is written in the hope that everyone can remember this parameter.
Line 36 is to use the creat function to create the file "test3". Pay attention to the difference between the parameters of the creat function and the open function when creating the file.
Compile and run the test

In the Ubuntu system, as shown in the figure below, enter the directory "/home/linuxsystemcode/iofile" created in the previous experiment and copy the source code creat.c into it, as shown in the figure below.

Use the command "arm-none-linux-gnueabi-gcc -o creat creat.c -static" to compile the creat.c file, as shown in the figure below, use the command "ls" to see that the creat executable file is generated.

Here we introduce the method of copying code from U disk, which can also be compiled into the file system. For the specific method, please refer to section 10.3.5.
Copy the compiled executable file creat to U disk, start the development board, insert U disk, load U disk, and run The procedure is as follows.

As shown in FIG.
Opening the file "/dev/leds" was successful, the file already exists.
Opening the file "/bin/test1" failed because the parameter O_CREAT was not added, and the file does not exist. The parameter
O_CREAT is required when creating a new file .
Open the file "/bin/test2" successfully. If the file does not exist, the creation is successful.
Open the file "/bin/test3" successfully, this file does not exist, use creat to create a new one successfully.
As shown in the figure below, use the command "ls /bin/test*" to see the newly created files test2 and test3 in the "/bin" directory.

16.4 Close function close
Any file needs to be closed after the operation is completed. At this time, the close function needs to be called.
Introduction
to the close function After calling the close function, the mapping relationship established by the open function will be cancelled, the handle will no longer be valid, and the occupied space will be released by the system.
The close function is in the header file "#include <unistd.h>". The use and parameters of the close function are relatively simple.
int close(int fd); The
parameter fd is the handle returned after the file is opened using the open function. The return value, generally the return value of close is rarely used.
The close function routine
is very simple to call, and the close function will be used forever in the next experiment.

16.5 The write function write writes
files, and the write function is used more.
Introduction to the
write function The write function is in the header file "#include <unistd.h>".
The function prototype is ssize_t write(int fd, const void *buf, size_t count) parameter fd,
the handle returned after opening the file with the open function .
Parameter *buf, the data to be written.
Parameter count, write up to count bytes in parameter *buf into the file.
The return value is of type ssize. If error occurs, -1 will be returned. Other values ​​indicate the number of bytes actually written.
Write function routine
Write a simple write.c file to test the write function. First add the header file as shown below.
//Standard input and output header file
#include <stdio.h>
//File operation function header file
#include <sys/types.h>
#include <sys/
stat.h>
#include <fcntl.h > #include <unistd .h>
#include <string.h>
Then the main function is as follows.

As shown in the code above.
The buffer_write character array is defined in line 16.
In line 18, before writing, you must get the file handle. In this line, use the open function to create and open the file "/bin/testwrite".
The write function will be called in line 23 to write the contents of the buffer_write character array to the newly created file.
Call the close function on line 31 to close the "/bin/testwrite" file.
When testing later, you can open the "/bin/testwrite" file with the vi editor in the HyperTerminal, and you can see the characters Hello Write Function!.
Compile and run the test
in the Ubuntu system, as shown in the figure below, enter Copy the source code write.c into the directory "/home/linuxsystemcode/iofile" created in the previous experiment, as shown in the figure below.

Use the command "arm-none-linux-gnueabi-gcc -o write write.c -static" to compile the write.c file, as shown in the figure below, use the command "ls" to see that the write executable file is generated.

Here is how to copy the code from the USB flash drive, which can also be compiled into the file system.
Write the compiled executable file, copy it to a U disk, start the development board, insert the U disk, load the U disk, and run the program. As shown in the figure below, Write Function OK! is printed out.

The file defined in the code is "/bin/testwrite". Use the vi editor to open the file. As shown in the figure below, the program runs successfully.

16.6 The read function
of the file The read function is used for writing to the file.
The read function is introduced
in the header file "#include <unistd.h>".
The function prototype is ssize_t read (int fd, void *buf, size_t len)
parameter fd, and the handle returned after the file is opened using the open function.
Parameter *buf, the location where the read data is saved.
Parameter len, read at most len ​​bytes each time.
The return value is of type ssize. If error occurs, -1 will be returned. Other values ​​indicate the number of bytes actually written. The return value is greater than 0 but less than len
.
Read function routine
Write a simple read.c file to test the read function.
First add the header file and define the read function buffer as 1000, as shown in the figure below.
//Standard input and output header file
#include <stdio.h>
//File operation function header file

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
Then the main function is shown in the figure below.

As shown in the code above. On lines 1-9, the header file.
In line 20, use the open function to open or create a new "/bin/testwrite" file.
In line 23, use the write function to write the contents of the buffer to the "/bin/testwrite" file. In line 35, use the read function to read out the contents of the "/bin/testwrite" file.
In line 38, use the print function printf to print the data read by the read function. At line 39, call the close function to close the opened file and the program ends.
In the final test, in addition to the "/bin/testwrite" file, the data read by the read function will be printed.
Compile and run the test
In the Ubuntu system, as shown in the figure below, enter the directory "/home/linuxsystemcode/iofile" created in the previous experiment, and copy the source code read.c into it, as shown in the figure below.

Use the command "arm-none-linux-gnueabi-gcc -o read read.c -static" to compile the read.c file, as shown in the figure below, use the command "ls" to see that the read executable file is generated.

Here is how to copy the code from the USB flash drive, which can also be compiled into the file system.
Copy the compiled executable file read to the U disk, start the development board, insert the U disk, load the U disk, and run the program. As shown in the figure below, you can see that "Files Content is Hello Write Function" is printed out, making the expected result in the code.

 

Guess you like

Origin blog.csdn.net/mucheni/article/details/112918891