Understanding Java I / O

illustrate

Before discussing Java I/O, let's discuss the following:

  • buffer operation
  • kernel space user space
  • Virtual Memory
  • Sentence I / O, style I / O
  • UNIX I/O model

After understanding the above content, you will have a clearer understanding of I/O.

    

buffer operation

    Buffers are the basis for all types of I/O, which is moving data in and out of buffers.

           

       The I/O process is to move data between the user space process buffer and the kernel buffer, and the source of the data is an external I/O device. When a process requests an I/O operation, a system call is executed to transfer control to the system kernel. For example, the underlying functions of C/C++ language open() , read() , write() , close() , all they need to do is to execute system calls. When the kernel is called, it finds the data needed by the process and transfers the data to the buffer specified in user space. The kernel tries to cache or prefetch the data, so the data needed by the process may already be in the kernel space, and just copy the data to the user space. If the data is not in the kernel space, then the kernel space has to read the data, and the user space process is suspended.

        Data from kernel space to user space requires a memory copy, and data cannot be directly transferred from I/O devices to user space. Because hardware devices usually cannot directly access user space; block-based hardware devices such as disks operate on fixed-size data blocks, while user processes may request data blocks of arbitrary size or non-alignment. The kernel is responsible for processing data obtained from I/O devices.

 

kernel space, user space

    User space is where regular processes reside, and kernel space is where the operating system and some drivers reside. Applications run in user mode and operating systems run in kernel mode. Each user-mode process has its own dedicated virtual address space, and all code running in kernel mode has a single virtual address space called "system space". The virtual address space of a user-mode process is called "user space". Code running in user mode can access user space, but not system space. Code running in kernel mode can access both system space and user space.

 

Virtual Memory

    There will be a memory copy operation in the I/O process from user space to kernel space, and this memory copy can be avoided by using virtual memory technology.

   Virtual Memory Wikipedia: Virtual memory is a technique for memory management of computer systems. It makes the application think that it has contiguously available memory (a contiguous complete address space), when in fact it is usually divided into multiple physical memory fragments, and some are temporarily stored on external disk storage, when needed data exchange. Operating systems that use virtual memory technology make it easier to write large programs and use physical memory more efficiently than operating systems that do not use virtual memory technology.

    Note: Virtual memory doesn't just mean "expanding physical memory with disk space", it just means expanding the level of memory to include hard drives. Extending memory to disk is only a result of using virtual memory technology, and its effect can also be achieved by overwriting or swapping inactive programs and their data to disk. The definition of virtual memory is based on the redefinition of the address space, that is, the address space is defined as "contiguous virtual memory addresses", so as to "trick" programs into thinking that they are using a large block of "contiguous" addresses. .

                                     

   

                   

     At present, my understanding of the major changes is that the kernel space virtual and the user space virtual map the same physical memory area, because the user space of each process is independent, and the kernel space can operate any user space. After the kernel stores data in this memory area, it is also visible to the user process, thus avoiding memory copying. (However, I think this understanding should be problematic, and virtual memory technology cannot be explained clearly in one or two sentences, and needs to be studied and studied in the future).

 

Article I / O, Flow I / O

   I/O is broadly divided into two categories, file I/O and stream I/O. File I/O falls under the category of file systems, which are very different from disks. A disk is just a place for data storage, a disk is a hardware device and does not understand the concept of files. A file system is a higher-level abstraction, a unique way of arranging and interpreting disk data. The file system defines abstract concepts such as file names, paths, and file attributes. The stream I/O principle mimics the channel, the I/O byte stream must be accessed sequentially, eg: console devices, printer ports, network connections. The network communication process is Stream I/O, which is mainly studied and studied.

 

UNIX I/O model

  • Blocking I / O (bloking I / O)
  • Non-blocking I/O (non-blocking I/O)
  • Multiplexing I/O (multiplexing I/O)
  • Signal-driven I/O (signal-driven I/O)
  • 异步 I/O (asynchronous I/O)

 

Blocking I/O Model

                  

     Step 1. The application triggers the operating system to read data;

     Step 2 The controller is handed over to the kernel, and if there is data to read, it will be read, and if there is no data to be read, it will wait;

     The third step reads the data, and copies the data from the kernel space buffer to the user space buffer;

     Step 4. The data copy is completed. The kernel informs the application that the data is successfully read;

     Until these 4 steps are completed, the application process will be blocked.

 

non-blocking I/O model

                       

    The improvement of the non-blocking mode is that before step 4 is completed, the polling executes step 1. At this time, the reference program process will not block. When no success indication is received, the process can do other things. After receiving the success indication, you can process the read data without blocking and waiting.

    

Multiplexed I/O Model

    Multiplexing I/O is often referred to as select, poll, and epoll. There is also a place where this I/O method is called event driven I/O. The advantage of multiplexing I/O is that a process can handle multiple network connection I/Os. Its working principle is that the select/poll/epoll function will continuously query whether there is a socket ready in the monitored socket file descriptor. Read and write, if there is, then the system will notify the user process.

                    

    select does not block for a long time like blocking I/O until there is data to read, select traverses all sockets and returns the ones that are in a readable state. Then the application process can perform I/O operations on these sockets. Since there is already data in these sockets, only memory copying is required at this time, and the I/O operations are completed by copying the data from the kernel space to the user space. . The biggest flaw of select is that the socket descriptor opened by a single process has a certain limit, which is set by FD_SETSIZE, and the default is 1024. Too few for large servers that require thousands of TCP connections. epoll does not have this limitation. The upper limit of the FD it supports is the maximum number of file handles of the operating system. For example, on a machine with 1G of memory, it is about 100,000 handles. Another fatal disadvantage of select/poll is that when there is a large set of sockets, only a small number of sockets are "active" at any time due to network delay or idle link, but each call of select/poll will be linear of scanning all socket sets, resulting in a linear decrease in efficiency. epoll does not have this problem, it only operates on "active" sockets.

Blocking mode, and non-blocking mode can only handle one I/O operation at a time. The multiplexing model can handle multiple I/O operations at once. The idea of ​​event driven is that you can choose sockets in different states, such as accept , connect , read , write , and more different states for corresponding processing.

 

Signal-driven I/O

                   

      The working principle of Signal Driven I/O  is that the user process first establishes a signal notification mechanism with the kernel, that is, the user process tells the kernel that if the data in the kernel is ready, it will  SIGIO notify me through a signal. Then the user space process will call the read system call to copy the prepared data from the kernel to the user space.

But this I/O model has a very significant flaw : SIGIO there is only one such signal per process! If the signal is made to work on both descriptors in the process (both file descriptors are waiting for I/O operations), then the process cannot tell which file descriptor is ready after receiving this signal . So the  Signal Driven I/O  model is rarely used in reality.

 

Asynchronous I/O

            

 

Blocking I/O Java Server Communication Model

    Java runs on the JVM, the JVM runs on the operating system, and the JVM is a user process. Java applications are not really I/O bound. The operating system is not incapable of passing data quickly. It's because the JVM is inefficient at I/O. There is a write mismatch between the operating system and Java's stream-based I/O model. The operating system moves large chunks of data (buffers), and the JVM's I/O classes like to operate on small chunks of data—a single byte, a few lines of text. As a result, the operating system sends the data of the entire buffer, and the Java I/O stream data class spends a lot of time splitting them into small pieces, and often copying a small piece requires going back and forth between several layers of objects. JDK only supports blocking I/O before 1.4, and Java's network programming can only work based on blocking I/O mode. In order to avoid the problem of thread blocking during I/O, only multi-threaded processing can be used. connection request.

                    

    Whenever there is a client connection, the server must allocate a new thread to process the client request. With the increase of clients, the server thread also grows linearly, the memory overhead increases, and the CPU context switching performance overhead is large. Threads are very valuable system resources of the JVM. When the number of threads is very large, the system performance drops sharply. This mode struggles in scenarios with high concurrency and large traffic.

                    

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325896190&siteId=291194637