Overview
The explanation in this book is general, mainly for explanation
缓冲区
通道
选择器
正则表达式
字符集
It mainly explains the use of api and some system knowledge, which is relatively low-level, and most of them are the source code explanation of the code, or the explanation of the api usage, which is too detailed.
You can take a look at this before learning netty, or the two can make up for each other.
The suggestion is that if you don't use Netty, then don't learn it. It's relatively low-level, and you will forget it after reading it.
I bite the bullet and read it roughly, and if I have time, let's watch it a second time.
1 Introduction
The difference between java io and system io
In most cases, Java applications are not really constrained by I/O. It is not that the operating system cannot transfer
data quickly so that Java has something to do; on the contrary, the JVM itself is not efficient in terms of I/O. The operating system
does not match Java's stream-based I/O model. What the operating system wants to move is a large block of data (buffer), which is often
done with the assistance of hardware direct memory access (DMA). The I/O class of JVM likes to manipulate small pieces of data-a single byte, a few lines of text. As a result, the
operating system sends the data in the entire buffer, and java.io's stream data class spends a lot of time breaking them into small pieces, often copying a
small piece to and from several layers of objects. The operating system likes to transport data in whole trucks, while the java.io class likes
to process the data one shovel by shovel . With NIO, you can easily back up a truckload of data to a place where you can directly use it (ByteBuffer
object).
Just stick to the array-based read() and write() methods. These methods are quite close to the underlying operating system calls, although at least one copy of the buffer must be kept.
The buffer, and how the buffer works, is the basis of all I/O. The so-called "input/output" is nothing more than moving data into or out of the buffer.
I/O buffer operation diagram
Divergent read operation of three buffers
Memory space multiple mapping
The prerequisite is that the kernel and user buffers must use the same page alignment, and the size of the buffer must also be a multiple of the disk controller block size (usually 512-byte disk sectors). The operating system divides the memory address space into pages, which are fixed-size byte groups. The size of the memory page is always a multiple of the disk block size, usually to the power of 2 (this simplifies the addressing operation).
The page fault immediately generates a trap (similar to a system call), which transfers control to the kernel with information about the virtual address that caused the error, and then the kernel takes steps to verify the validity of the page.
1.4.1 File IO
- Disks are hardware devices and don't know anything about files.
- The file system is a higher level of abstraction, a unique way of arranging and interpreting data on a disk (or other random access block device).
User memory to file system page mapping
File lock
- The file locking mechanism allows a process to prevent other processes from accessing a file or restrict its access methods. The usual use is to control the update method of shared information, or for transaction isolation. File locking is essential in controlling concurrent access to common resources by multiple entities.
数据库等复杂应用严重信赖于文件锁定
There are two ways to lock files: shared and exclusive. Multiple shared locks can act on the same file area at the same time; exclusive locks are different, it requires that the related area cannot have other locks in effect.
2. Buffer
- The buffer is an array of basic data elements wrapped in an object.
2.1 Properties
All buffers have four attributes to provide information about the data elements they contain. They are:
Capacity
The maximum number of data elements that the buffer can hold. This capacity is set when the buffer is created and can never be changed.
Upper bound (Limit)
The first element of the buffer that cannot be read or written. In other words, the count of existing elements in the buffer.
Position
The index of the next element to be read or written. The position is automatically updated by the corresponding get() and put() functions.
Mark
A memo location. Call mark() to set mark = postion. Call reset() to set position = mark. The mark is undefined before it is set.
The four attributes always follow the following relationship:
0 <= mark <= position <= limit <= capacity
This chapter mainly introduces various buffers.
2.2 flip
The Flip() function flips a buffer that can continue to add data elements in a filled state to a released state that is ready to read elements.
Similar to the code below
buffer.limit(buffer.position()).position(0);
2.3 clear
The Clear() function resets the buffer to an empty state. It does not change any data elements in the buffer, but only sets the upper bound to the value of the capacity and sets the position back to 0.
2.4 mark
Mark so that the buffer can remember a position and return it later. The mark of the buffer is undefined before the mark() function is called, and the mark is set to the value of the current position when called. The reset() function sets the position to the current mark value. If the mark value is not defined, calling reset() will cause an InvalidMarkException exception. Some buffer functions discard the flags that have been set (rewind( ), clear( ), and flip() always discard the marks). If the newly set value is smaller than the current mark, calling limit() or position() with an index parameter will discard the mark.
2.5 Comparison
The necessary and sufficient conditions for two buffers to be considered equal are: 32
- The two objects are of the same type. Buffers containing different data types are never equal, and buffers are never equal to non-buffer objects.
- Both objects have the same number of elements remaining. The capacity of the buffer does not need to be the same, and the index of the remaining data in the buffer does not need to be the same. But the number of remaining elements in each buffer (from position to upper bound) must be the same.
- The sequence of the remaining data elements that should be returned by the Get() function in each buffer must be consistent.
Two buffers considered equal
Two buffers that are considered unequal
3.6 Byte order
Big-endian byte order
Little-endian byte order
The way multibyte values are stored in memory is generally called endian-ness (byte order). If the highest byte of the digital value-big end (big end), is located at the low address, then the system is in big endian byte order. If the lowest byte is stored in memory first, then little-endian byte order.
The ByteOrder class defines constants that determine which byte order to use when storing or retrieving multi-byte values from the buffer.
The ByteBuffer class is different: the default byte order is always ByteBuffer.BIG_ENDIAN, regardless of the inherent byte order of the system. Java's default byte order is big-endian byte order.