Windows core programming Reading Notes-completion port

Source: Internet
Author: User

The completion port is an asynchronous data processing mechanism designed by windows to handle the differences in the speed of running concurrent operations between different devices. Port completion is a key part of "Windows core programming". Recently, I spent three days reading the section about port completion in core programming and learning about the relevant technical documents of Microsoft, it seems that the design and implementation of the port can accelerate the service speed of windows to a certain extent. The use of the port does not have to affect the program logic, but for services requiring speed, this is crucial. Because the source code is not open, some internal principles can only be guessed, and many parameters are associated with each other, which is confusing. I personally think Microsoft's underlying interfaces are not well designed at the beginning, in addition, in order to be compatible with the programs developed in earlier versions, errors will not be changed, which will become increasingly messy.

Even so, as long as you are careful enough to learn how to use the complete port. It can be said that for Windows programmers, the mastery of the completed port shows the programmer's underlying platform technical level.

 

1. There seems to be few of the three basic functions. It takes a lot of time to figure out the parameters.

Createiocompletionport ()

Postqueuedcompletionstatus ()

Getqueuedcompletionstatus ()

2. Port created successfully

Use handle hiocp = createiocompletionport (invalid_handle_value, null, 0, dwthreadcount); create a complete port. Pay attention to parameter settings here, which is different from the original design of windows. The last parameter specifies the maximum number of threads that can be opened when the port kernel object is finished. thread management is performed by the port Kernel Object Management, which is not transparent to users. The prototype is as follows:

Handle winapi createiocompletionport (
_ In _ HANDLE filehandle,
_ In_opt _ HANDLE existingcompletionport,
_ In _ ulong_ptr completionkey,
_ In _ DWORD numberofconcurrentthreads
);

See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363862 (V = vs.85). aspx

3. The device handle is associated with the completion port (equivalent to a registration action)

Createiocompletionport (hfileread, hiocp, ck_read, 0); here hfileread is the handle of the corresponding device (here the device can be a commonly used device in Windows File System ), hiocp is an existing finished port handle; ck_read is a parameter set to the notification sent when the completed port event is completed, which can identify the device of the completed event; the following example uses ck_read and ck_write to identify the device that sent the completed event.

4. Manually notify the kernel that the event has been completed, that is, put the completed event into the Completion queue.

Use postqueuedcompletionstatus (hiocp, buffer_size, ck_write, & ior [nioreq]); here hiocp is the port handle, and the buffer_size parameter is the data obtained when it is passed to getqueuedcompletionstatus, ck_write indicates the event of completion (the same as the one set when the device handle is associated ). The prototype is as follows:

Bool winapi postqueuedcompletionstatus (
_ In _ HANDLE completionport,
_ In _ DWORD dwnumberofbytestransferred,
_ In _ ulong_ptr dwcompletionkey,
_ In_opt _ lpoverlapped
);

See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365458 (V = vs.85). aspx

5. retrieve a completion event from the completion event queue

Use getqueuedcompletionstatus (hiocp, & dwnumbytes, & completionkey, (overlapped **) & pior, infinite); to obtain the queue header data of the currently completed event queue. In the next action, process the completed event. This action needs to be repeated repeatedly, and the last event to be completed in the design task should let the processing program know that the task has been completed. The prototype is as follows:

Bool winapi getqueuedcompletionstatus (
_ In _ HANDLE completionport,
_ Out _ lpdword lpnumberofbytes,
_ Out _ pulong_ptr lpcompletionkey,
_ Out _ lpoverlapped * lpoverlapped,
_ In _ DWORD dwmilliseconds
);

See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa364986 (V = vs.85). aspx

6. asynchronous Io events

I mentioned above that I/O is completed, but how can I/O operations be generated and run? In fact, there can be many Io actions. If you register a device in step 1, you can use the same action. For example, if you need to enable file reading and writing, you need to use the createfile function. Note that you need to set the overlapped mode when opening the file ). The returned hfileread handle is the device handle that needs to be associated with the IO completion port.

Handle hfileread = createfile (readfilename,
Generic_read,
File_pai_read,
Null,
Open_existing,
File_flag_no_buffering | file_flag_overlapped,
Null );

 

 

The Design of other logics is also annoying. You can refer to the following example: Use Io to complete the port and set four threads to implement the file copy function quickly. The Code content comment should be helpful and can be copied directly to the vc2008 project to lower the trial run comprehension.

 

// Class for secondary file reading and writing, class cioreq: Public overlapped {public: cioreq () {internal = internalhigh = 0; offset = offsethigh = 0; hevent = NULL; m_nbuffsize = 0; m_pvdata = 0 ;};~ Cioreq () {If (m_pvdata! = NULL) {virtualfree (m_pvdata, 0, mem_release) ;}}; bool allocbuffer (optional nbuffsize) {m_nbuffsize = nbuffsize; m_pvdata = virtualalloc (null, m_nbuffsize, mem_commit, page_readwrite ); return (m_pvdata! = NULL) ;}; bool read (handle hdevice, plarge_integer plioffset = NULL) {If (plioffset! = NULL) {offset = plioffset-> lowpart; offsethigh = plioffset-> highpart;} return (: readfile (hdevice, m_pvdata, m_nbuffsize, null, this ));}; bool write (handle hdevice, plarge_integer plioffset = NULL) {If (plioffset! = NULL) {offset = plioffset-> lowpart; offsethigh = plioffset-> highpart;} return (: writefile (hdevice, m_pvdata, m_nbuffsize, null, this ));}; PRIVATE: size_t m_nbuffsize; pvoid m_pvdata;}; long chroundup (long src_size, long align) {long T = src_size % align; If (t) {return (src_size/align) * align + align;} return src_size;} bool filecopy (const wchar * des, const wchar * SRC) {# define buffer_size (64*1024) // In file_flag_no_buffering mode, use the file size to align up to this size, use this size as the basic unit of Io data # define ck_write 1 // mark completed by writing file data events # define ck_read 2 // mark completed by reading file data events # define max_pending_io_reqs 4 // set the maximum number of threads for running Io simultaneously to 4. If it is too small, it does not reflect the advantages of multithreading. If it is too large, it takes too much time for switching and the efficiency is low. Bool Fok = false; const wchar * readfilename = SRC; const wchar * writefilename = des; large_integer lifilesizesrc = {0}; large_integer lifilesizedes = {0 }; try {// The created port handle hiocp = createiocompletionport (invalid_handle_value, null, 0, success); // open the source file in overlapped mode for reading the handle hfileread = createfile (readfilename, generic_read, file_cmd_read, null, open_existing, file_flag_no_buffering | file_flag_o Verlapped, null); // associates the source file device with the completion port. The event flag used is ck_readif (hiocp! = Createiocompletionport (hfileread, hiocp, ck_read, 0) {return 0;} // type the target file in overlapped mode for writing to handle hfilewrite = createfile (writefilename, generic_write, file_cmd_read | file_cmd_write, null, create_always, file_flag_overlapped | file_flag_no_buffering, null); // associates the target file device with the completion port, and the event flag is ck_writeif (hiocp! = Createiocompletionport (hfilewrite, hiocp, ck_write, 0) {return 0;} // obtain the logical size of the source file (not physical size) getfilesizeex (hfileread, & lifilesizesrc ); // because file_flag_no_buffering opens the parameter, alignment the target file to buffer_size lifilesizedes. quadpart = chroundup (lifilesizesrc. quadpart, buffer_size); setfilepointerex (hfilewrite, lifilesizedes, null, file_begin); setendoffile (hfilewrite ); // these two variables are used to represent the current read and write Io operands int nreadsinprogress = 0; int nwritesin Progress = 0; // operation object required to create four threads, which encapsulates the cioreq ior [max_pending_io_reqs]; large_integer linextreadoffset = {0}; For (INT nioreq = 0; nioreq <_ countof (IOR); nioreq ++) {ior [nioreq]. allocbuffer (buffer_size); // each object manually triggers a write completion event to enable the receiver to start working. Postqueuedcompletionstatus (hiocp, buffer_size, ck_write, & ior [nioreq]); nwritesinprogress ++;} // as long as there are still Io operations not completed, continue listening to complete the event list while (nwritesinprogress> 0 | nreadsinprogress> 0) {ulong_ptr completionkey; DWORD dwnumbytes; cioreq * pior; // infinite indicates an indefinite listener, until there is a completed event getqueuedcompletionstatus (hiocp, & dwnumbytes, & completionkey, (overlapped **) & pior, infinite); Switch (completionkey) {Case ck_write: // The write completion event nwritesinprogress is received --; // The number of write tasks is reduced by 1if (linextreadoffset. quadpart <lifilesizedes. quadpart) // if the source file has not been read {// read the source file pior-> Read (hfileread, & linextreadoffset); nreadsinprogress ++; // The number of reading files increases by 1linextreadoffset. quadpart + = buffer_size;} break; Case ck_read: // nreadsinprogress --; // reduce the number of reading tasks by 1pior-> write (hfilewrite ); nwritesinprogress ++; // increase the number of writes by 1 break;} closehandle (hfilewrite); closehandle (hfileread); closehandle (hiocp); Fok = true ;} catch (...) {} If (FOK = true) {// fix the size of the target file and change it back to the original logical size handle hfile = createfile (writefilename, generic_write, 0, null, open_existing, 0, null); setfilepointerex (hfile, lifilesizesrc, null, file_begin); setendoffile (hfile); closehandle (hfile);} return Fok ;}

 

Add two connections to finish the Port:
1. Detailed Principles and usage articles, which are strongly recommended

Http://blog.csdn.net/piggyxp/article/details/6922277

2. The simple program shows the application scenarios of ports in the network.

Http://www.cnblogs.com/pen-ink/articles/1834088.html

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.