Asynchronous Input and Output

Input and output represent interaction between the process and the specific device, such as a file stored on a disk. The rate of this operation depends, more on the performance of the peripheral device and data transmission link rather than on the performance of the central processing unit. The standard method of communicating with a peripheral device supposes that the process will wait for the read or write operation to accomplish on each stage of interaction. This method is called synchronous input/output. It is called synchronous because the process on each stage synchronizes its action with the state of the peripheral device. To increase the system performance when carrying out an input/output operation, asynchronous input/output was implemented. [i] To inform the system about the intention to carry out an asynchronous input/output operation, it is necessary to open the device using the CreateFile function and specify the FILE_FLAG_OVERLAPPED flag in the sixth parameter. When executing functions such as ReadFile and writeFile , the device drive places the input/output request into the queue. The functions then immediately return control to the calling process. Thus, the process can carry out other actions without worrying about the data and whether or not they have been transmitted. The most important point in the entire method is how the driver would inform the process that the data transmission has been completed and with what result.

In the course of asynchronous input/output, the role of parameters of the ReadFile and WriteFile functions slightly changes. In particular, since both functions immediately return control to the calling process, the fourth parameter ceases to do anything and is usually set to zero. The fifth parameter, on the contrary, starts to play the main role. It must point to the OVERLAPPED structure:

 OVERLAPPED STRUC             INTERN DD ?             NBYTE  DD ?             OFFSL  DD ?             OFFSH  DD ?             HEVENT DD ?     OVERLAPPED ENDS 

Note that the last three fields must be set before carrying out the operation. The fields of this structure are as follows :

  • INTERN This field would contain the operation accomplishment status. When the input/output operation is in progress, the value of this field will be set to STATUS_PENDING = 103h .

  • NBYTE When the operation is completed, this field will contain the number of transmitted bytes.

  • OFFSL and OFFSH These are the least significant and most significant parts of the pointer position within the file. For devices other than files, this must be set to zero.

  • HEVENT This takes its value depending on the method of asynchronous input/output.

It is necessary to bear in mind that the ReadFile and WriteFile functions return the 0 value in the case of asynchronous input/output. However, sometimes the system might carry out the read/write operation instantly, in which case these functions will return a positive value. If these functions return the 0 value, this doesn't necessarily mean that asynchronous input/output has started successfully. It is possible that some error has occurred. Therefore, it is necessary to call the GetLastError function. If it returns the ERROR_IO_PENDING = 997 value, this will mean that asynchronous process has started successfully. Any other value will serve as an indication that some error has occurred. Asynchronous input/output is canceled in one of the following cases:

  • The CancelIo function is executed. The only parameter of this function is the descriptor of the opened device (file). Bear in mind that all asynchronous input/output requests of this thread will be canceled.

  • When the device (file) is closed, all requests for asynchronous input/output for this file are canceled.

  • If the thread is closed, all its requests are automatically canceled.

There are four mechanisms of informing the process about the termination of the input/output operation.

  • Signaling of the kernel object controlling the device [i]

  • Signaling of the kernel object controlling events

  • Input/output notification

  • Use of the input/output termination port

Consider these approaches in more detail.

Signaling of the kernel object controlling the device . In this approach, the WaitForSingleObject API function is used (see Chapter 15). The function returns control either when the predefined time interval elapses or when a certain kernel object (e.g., an opened file) is switched to a certain state known as signal state. The first argument of this function is the descriptor of the opened device (file), and its second argument is the waiting interval. If the INFINITE = ˆ 1 constant is taken as the value of this parameter, the waiting interval will be infinitely long. The ReadFile and WriteFile functions set the object to nonsignaled state. When asynchronous input/output is completed, the device driver switches the object to the signaled state, and the WaitForSingleObject function returns the control. What is the advantage here, you might ask, since the process continues to wait for the result? Usually, for this method a separate thread is created. The thread that has opened the device might be busy-carrying out other tasks . When the process is completed, it is necessary to check the OVERLAPPED structure to discover whether there were errors and how many bytes have been transmitted. Before opening the device, this structure must be initialized . In particular, the HEVENT field must be initialized with zero.

Signaling of the kernel object controlling events . The preceding method, principally, allows the system to wait for the results of only one input/output operation. There is a more flexible approach, in which the specific event is associated with every input/output operation ( WriteFile or ReadFile function). The event can be created using the CreateEvent function (see Chapter 15), and its handle must be assigned to the HEVENT field of the OVERLAPPED structure. To wait for an event, use the WaitForMultipleObjects function.

Input/output notification . To use this method, instead of the ReadFile and WriteFile functions it is necessary to use the ReadFileEx and WriteFileEx functions. These functions have an additional, sixth parameter that represents the address of the procedure that will be called when asynchronous input/output is completed. This procedure must be created beforehand in your program. Usually, it is called the callback procedure. It has three parameters. The first parameter is the completion code. If its value is 0, this means that asynchronous input/output has completed successfully. If this parameter is equal to ERROR_HANDLE_EOF = 38 , this means that an attempt was made to read the file beyond its boundary. Provided that the operation has completed successfully, the second parameter will contain the number of read or written bytes. Finally, the third parameter is the address of the OVERLAPPED structure that I have already described. It is necessary to bear in mind that the device drive places an appropriate procedure into the queue after the completion of the respective asynchronous input/output operation. To call these procedures, the thread must be switched to the waiting state. To achieve this, use functions such as sleepEx and WaitForSingleObjectEx . Now, consider the SleepEx function in more detail. [i] The first parameter of this function is the number of milliseconds for waiting. The INFINITE value of this parameter means that it will wait infinitely. The second parameter can take two values: 0 or 1. If the value of this parameter is 0, then exiting from this function takes place only after the interval specified in the first parameter has elapsed. If this parameter is 1, the function can be exited in two additional ways:

  • When the callback function is called

  • When this function is placed into the queue

Input/output termination ports . Asynchronous input/output is not often used for file processing. In this case, asynchronous communication between the server and several client applications is considerably more important. The communications mechanism is not of primary importance. Several such mechanisms can be used, including named pipes, mailslots, or network interaction using the sockets mechanism. Two approaches are possible:

  • A single thread waits for the client requests. When a request arrives, the thread processes it. This approach is convenient when client requests are rare. If several client programs access the server simultaneously , a queue is generated. As a result, some clients may have to wait a long time before the server starts processing their queries. This approach is known as sequential processing.

  • The server thread waits for the query to arrive . When the query arrives, a new thread is created, which is delegated the responsibility of organizing communications with this client. The first thread continues to wait for new client requests; when they appear, it creates new threads for them. The thread that finishes serving the client is terminated . This approach is called parallel processing. It is significantly more efficient than sequential processing. However, research has shown that when numerous threads run simultaneously, most time is spent on context switching between threads.

The method that uses the input/output termination port is based on the assumption that a limited number of simultaneously running threads serves clients. In other words, this approach is a compromise between the sequential and the parallel approaches. This method also implements another interesting approach: Because a certain time is required for creating individual threads, the entire pool of threads is created. The threads that do not participate in the processing of client requests are in the waiting state.

I will return to considering asynchronous input/output when considering multitasking programming in Chapter 15.

[i] To get a proper understanding of this section, you'll need the material presented in Chapter 15, which provides an example of parallel asynchronous processing.

[i] The kernel is the part of the operating system that runs in the privileged mode. More detailed information on this topic will be provided in Chapter 24 (see " Kernel Mode Drivers ").

[i] Later, you will become acquainted with the Sleep function, which is simpler than this one.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net