Python's I/O model

Source: Internet
Author: User
Tags epoll

I/O Model:

Synchronous (synchronous) IO

Asynchronous (asynchronous) IO

Blocking (blocking) IO

Non-blocking (non-blocking) IO

For a network IO (read example here) occurs when two system objects are involved, one is the process or thread that calls this IO, and the other is the kernel kernel of the system. When a read operation occurs, the operation goes through two stages.

1) Wait for data preparation (wait)

2) Copy the data from the kernel to the process (copying)

Blocking IO

Linux, by default all sockets are blocking, a typical read operation is as follows:

When the user process invokes the RECVFROM system call, Kernel begins the first phase of IO: Preparing the data. For network IO, there are times when the data has not arrived at the beginning (for example, a full UDP packet has not been received), and kernel waits for enough data to arrive. On this side of the user process, the entire process is blocked. When kernel waits until the data is ready, it copies the data from the kernel to the user's memory, and then kernel returns the result, and the user process removes the block state and re-runs it.
Therefore, the blocking IO is characterized by block in both phases of IO execution.

Two. Non-blocking io (non-blocking IO)

Under Linux, you can make it non-blocking by setting the socket. When you perform a read operation on a non-blocking socket, the process looks like this:

As you can see, when the user process issues a read operation, if the data in kernel is not ready, it does not block the user process, but returns an error immediately. From the user process point of view, it initiates a read operation and does not need to wait, but immediately gets a result. When the user process determines that the result is an error, it knows that the data is not ready, so it can send the read operation again. Once the data in the kernel is ready and again receives the system call of the user process, it immediately copies the data to the user's memory and then returns. Therefore, the user process is in fact need to constantly actively ask kernel data well no.

Attention:

In the network IO, the non-blocking IO will also make recvform system calls, check whether the data is ready, and blocking IO is not the same, "non-blocking the large block of time is divided into more than n small blocking, so the process has a chance to ' be ' CPU patronage." That is, each time the Recvform system calls, the CPU's permissions are still in the hands of the process, this time can do other things,

That is, after a non-blocking recvform system call, the process is not blocked, the kernel is returned to the process immediately, and if the data is not ready, an error is returned. After the process returns, it can do something else before initiating the recvform system call. Repeat the above process and iterate through the recvform system calls. This process is often called polling. Poll the kernel data until the data is ready, and then copy the data to the process for data processing. It is important to note that the process of copying data is still a blocking state.

Import Timeimport Socketsk = Socket.socket (socket.af_inet,socket. Sock_stream) Sk.setsockoptsk.bind ((' 127.0.0.1 ', 6667)) Sk.listen (5) sk.setblocking (False) while True:    try:        Print (' Waiting client connection ... ')        connection,address = Sk.accept ()   # process actively polls        print ("+ + +", address )        Client_messge = Connection.recv (1024x768)        print (str (client_messge, ' UTF8 '))        connection.close ()    Except Exception as E:        print (e)        time.sleep (4) ############################ #clientimport timeimport Socketsk = Socket.socket (socket.af_inet,socket. SOCK_STREAM) while True:    sk.connect ((' 127.0.0.1 ', 6667))    print ("Hello")    sk.sendall (bytes ("Hello", " UTF8 "))    Time.sleep (2)    break
View Code

Pros: Ability to do other work while waiting for the task to complete (including submitting other tasks, i.e. "backstage" can have multiple tasks at the same time).

Disadvantage: The response delay for task completion is increased because each time a read operation is polled, the task may be completed at any time between polling two times. This can result in a decrease in overall data throughput.

Three. Io multiplexing (IO multiplexing) IO multiplexing The word may be a little strange, but if I say select,epoll, I will probably understand. Some places also call this IO mode for event driven IO. As we all know, the benefit of Select/epoll is that a single process can simultaneously handle multiple network connections of IO. The basic principle of the select/epoll is that the function will constantly poll all sockets that are responsible, and when a socket has data arrives, notifies the user of the process. It's process  

  When the user process invokes select, the entire process is blocked, and at the same time, kernel "monitors" all select-responsible sockets, and when the data in any one socket is ready, select returns. This time the user process then invokes the read operation, copying the data from the kernel to the user process.
This figure is not much different from the blocking IO diagram, in fact, it's even worse. Because two system calls (select and Recvfrom) are required, blocking IO only invokes one system call (Recvfrom). However, the advantage of using select is that it can handle multiple connection at the same time. (Say one more word.) Therefore, if the number of connections processed is not high, Web server using Select/epoll does not necessarily perform better than the Web server using multi-threading + blocking IO, and may be more delayed. The advantage of Select/epoll is not that a single connection can be processed faster, but that it can handle more connections. )
In the IO multiplexing model, the actual, for each socket, is generally set to become non-blocking, but, as shown, the entire user's process is actually always block. Only the process is the block of the Select function, not the socket IO.

Note that if a file is readable in the return result of the 1:select function, the process can let kernel copy the data that is in the kernel to the user area by calling accept () or recv ().

Note The advantage of 2:select is that it can handle multiple connections, not a single connection

#***********************server.pyimport socketimport Selectsk=socket.socket () sk.bind ("127.0.0.1", 8801) Sk.listen (5) inputs=[sk,]while True:    r,w,e=select.select (inputs,[],[],5)    print (Len (r)) for    obj in R:        if Obj==sk:            conn,add=obj.accept ()            print (conn)            Inputs.append (conn)        else:            data_byte= OBJ.RECV (1024x768)            print (str (data_byte, ' UTF8 '))            inp=input (' answer%s customer >>> '%inputs.index (obj)            ) Obj.sendall (Bytes (INP, ' UTF8 '))    print (' >> ', R) #***********************client.pyimport socketsk= Socket.socket () Sk.connect ((' 127.0.0.1 ', 8801)) while True:    inp=input (">>>>")    Sk.sendall ( Bytes (INP, "UTF8"))    Data=sk.recv (1024x768)    print (str (data, ' UTF8 '))
View Code

Import Selectorsimport Socketsel = selectors. Defaultselector ()   #会根据操作系统自动选择一个IO多用复用模型def accept (sock, mask):    conn, addr = Sock.accept ()  # should be Ready    print (' accepted ', Conn, ' from ', addr)    conn.setblocking (False)    Sel.register (conn, selectors. Event_read, read) def READ (Conn, mask):    data = CONN.RECV (+)  # should is ready    if data:        print (' echoing ', repr (data), ' to ', conn)        conn.send (data)  # Hope It won ' t block    else:        print (' closing ', conn)        Sel.unregister (conn)        conn.close () sock = Socket.socket () sock.bind ((' 127.0.0.1 ', 8080)) Sock.listen (100) Sock.setblocking (False)     #设置非阻塞 # Register  to bind the sock descriptor and the Accept function Sel.register (sock, selectors. Event_read, accept) while True:    events = Sel.select ()    for key, mask in events:        callback = Key.data        Callback (Key.fileobj, mask)
Selectors

Four. asynchronous I/O (asynchronous IO)

Asynchronous maximum features: no blocking throughout

The asynchronous IO under Linux is actually used very little. Let's take a look at its process:

  After the user process initiates the read operation, you can begin to do other things immediately. On the other hand, from the perspective of kernel, when it receives a asynchronous read, first it returns immediately, so no block is generated for the user process. Then, kernel waits for the data to be ready and then copies the data to the user's memory, and when all this is done, kernel sends a signal to the user process to tell it that the read operation is complete.

Python's I/O model

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.