As mentioned earlier, there are two methods for device I/O: synchronous and asynchronous. This topic describes synchronous device I/O. Two functions are involved: readfile and writefile.
Do not be confused by the names of these two functions. They can act not only on files, but also on other devices, such as pipelines and mail tanks.
The simplest device I/O can be implemented through the readfile and writefile functions:
Bool readfile (
Handle hfile, // device object handle
Pvoid pvbuffer, // read the buffer
DWORD nnumbytestoread, // number of bytes read
Pdword pdwnumbytes, // returns the actual number of bytes read
Overlapped * poverlapped); // overlapping structure pointer, used only in asynchronous mode Bool writefile (
Handle hfile,
Const void * pvbuffer,
DWORD nnumbytestowrite,
Pdword pdwnumbytes, // returns the actual number of bytes written
Overlapped * poverlapped );
Use these two functions for device I/O in synchronous mode. In synchronous mode, set the last parameter poverlapped of the two functions to null. In addition, you must note that when using createfile to create or open a device, the flag parameter cannot include flag_file_overlapped. Otherwise, the system considers that you want to implement device I/O asynchronously.
In addition, readfile can only read these devices. That is, when you create or open a device using createfile, the flag parameter of this function includes generic_read. Writefile can only be written to these devices. When using the createfile function, the flag parameter includes generic_write.
Devices such as email slots, pipelines, files, and serial ports have their own high-speed caches. If the flag parameter of the createfile function does not include file_flag_no_buffering, the written data can be saved in the buffer, you can use flushfilebuffers to forcibly write all data temporarily stored in the buffer zone related to the device.
Bool flushfilebuffers (handle hfile );
The synchronous device I/O implementation is simple, but the disadvantage is obvious, that is, it will hinder other operations in the thread that are not related to the device I/O. Because the device I/O function is returned only after the device I/O Request ends, if the data volume is large, other unrelated operations may be blocked.
To solve this problem, you should try to use Asynchronous device I/O. However, in Windows APIs, The creaetfile function is not implemented asynchronously. Windows Vista provides another method: Cancel synchronizing device I/O midway through. You can use the cancelsynchronousio function to cancel ongoing synchronization device I/O operations within a thread.
Bool cancelsynchronousio (handle hthread); // The parameter is the thread handle.
This function accepts a thread handle, which is the handle of a thread waiting for the synchronization device I/O operation to complete. This handle must have the thread_terminate operation permission when it is created or opened. If you call the createthread or _ beginthreadex function to create a thread, the returned thread handle contains the thread_terminated operation permission. If you use the openthread function to obtain the handle of a created thread, pass thread_terminated to the dwdesiredaccess parameter (1st parameters ). If this permission is not set, cancelsynchronousio returns false and getlasterror is called to return error_access_denied (access rejection error ).
If the thread has ended waiting for device I/O, then calling the cancelsynchronousio function will return true instead of flase. If getlasterror is called, error_operation_aborted is returned (Operation Failure error ).
If the thread does not wait for the return of the device I/O, then calling this function will return false, and then calling getlasterror will return error_no_found (unfound error ).