File descriptor and Kernel File handle of VC ++

Source: Internet
Author: User
File descriptor and Kernel File handle of VC ++

This article describes the relationship between C language in VC ++ and the kernel file handle using the code file descriptor (file descriptor), and the conversion function _ get_osfhandle between the two, _ open_osfhandle and the risks of using them. In Windows code, do not share the file description symbols and Kernel Handle handle.

At the beginning of the article, I want to declare that this is a bug I wrote, but it was discovered by two young boys, derickhu. sasukeliu, and again thanked them.

When I wrote some cross-platform code last year, we tried to simulate POSIX (Linux) functions in windows and found a problem, if you want to use more functions in Windows, you must use the file handle of the kernel instead of the file descriptor (file descriptor) used in C language function open in VC ++ ), that is, Int. To facilitate cross-platform communication, I try to ensure that the interfaces are unified. The implementation is as follows:

// Our crash platform code zen_handle zen_ OS: open (const char * filename, int open_mode, mode_t perms)

Zen_handle is defined as the Windows Kernel Handle handle on multiple Windows platforms, while Linux is defined as the Linux Kernel Handle Int.

By default, VC ++ implements a POSIX-compliant OPEN function. The returned value is also the standard file descriptor Int.

// The OPEN function int _ open (const char * filename, int Oflag [, int pmode]) implemented in windows;

If there is a way to convert from the C language file descriptor to the Windows Kernel Handle, then I can directly use the _ OPEN function. Google discovered these two functions: _ get_osfhandle and _ open_osfhandle. At that time, it was understood that _ get_osfhandle converted the file description into handle, and _ open_osfhandle converted the handle into the file descriptor.

//MSDNRetrieves the operating-system file handle that is associated with the specified file descriptor.intptr_t _get_osfhandle(    int fd );Associates a C run-time file descriptor with an existing operating-system file handle.int _open_osfhandle (   intptr_t osfhandle,   int flags );

 

So I wrote the code.

// When opening, call _ get_osfhandle to get the Kernel Handle. // many other codes are omitted. // After the OPEN function opens the file with _ sopen_s, use _ get_osfhandle to convert the handle to other places and use zen_handle zen_ OS: open (const char * filename, int open_mode, mode_t perms) {int file_id =-1; errno_t open_error = :: _ sopen_s (& file_id, filename, open_mode, _ sh_denyno, nt_perms); handle openfile_handle = (handle): _ get_osfhandle (file_id); Return openfile_handle;} // when disabled, use _ open_osfhandle to convert handle into a file descriptor, and use _ close to close int zen_ OS: Close (zen_handle handle) {int file_des =: _ open_osfhandle (intptr_t) handle, _ o_rdonly); If (-1 = file_des) {return-1;} return: _ close (file_des );}

 

The initial implementation of the code is to use the open function (our code defines _ crt_nonstdc_no_deprecate, without adding _ in front of the POSIX function), and the test at the beginning is basically OK. But later I came to the machine of some colleagues: the close function may have an asserted error. It was a bit strange at the time. By changing the code OPEN function to sopen_s, the replacement of the close function _ close avoids the problem temporarily (note that the _ close function and the close function are indeed two implementations ).

Recently, the refactoring went live, and a service program will keep opening and close the file. It will crash after three days of running. The error is that the file description symbol is insufficient. The two colleagues extracted the above Code and found the problem. Their test code is roughly as follows:

Int test_osadapt_file (INT/* argc */, char */* argv */[]) {int file_desc = open ("C: \ 123.txt", o_creat | o_append ); if (file_desc = 0) {return 0;} // fh_1 = fh_2 Kernel Handle consistent handle fh_1 = (handle) _ get_osfhandle (file_desc); handle fh_2 = (handle) _ get_osfhandle (file_desc); STD: cout <(INT) fh_1 <STD: Endl; STD: cout <(INT) fh_2 <STD: Endl; // file_desc = 3 filedesc_1 = 4 filedesc_2 = 5 different file descriptors int filedesc_1 = _ open_osfhandle (intptr_t) fh_1, o_rdonly ); int filedesc_2 = _ open_osfhandle (intptr_t) fh_1, o_rdonly); STD: cout <(INT) filedesc_1 <STD: Endl; STD: cout <(INT) filedesc_2 <STD: Endl; // fh_1 = fh_2 = fh_3, The Kernel Handle must be consistent with handle fh_3 = (handle) _ get_osfhandle (filedesc_1); STD :: cout <(INT) fh_3 <STD: Endl; return 0 ;}

 

The output results are shown in the preceding annotations. It is found that the file description symbol obtained by calling _ open_osfhandle is not the original file descriptor.

It seems that it is totally wrong to understand the meaning of the _ open_osfhandle function. _ Open_osfhandle is not associated with the original file descriptor, but instead re-allocates a C language descriptor for handle, the handle is not retrieved (associates are used for the description of msdn ).

 

From the figure below, we can clearly explain why the file descriptor of the C function is leaked. (This is probably the reason for the original assertions)

Of course, after carefully reading msdn, we can see that the remark of the msdn _ open_osfhandle function still has the relevant clues (e-文 ).

The _open_osfhandle function allocates a C run-time file descriptor and associates it with the operating-system file handle specified by osfhandle.……To close a file opened with _open_osfhandle, call _close. The underlying handle is also closed by a call to _close, so it is not necessary to call the Win32 function CloseHandle on the original handle. 

In fact, I think it is too careless to write this Code. In windows, I must use my own API, And the handle management in the kernel can be set to handle, the function encapsulation of the C Language Runtime Library must be a set of encapsulation at the upper layer. Therefore, the ing relationships stored in the C function library must be from file descriptors to the Kernel Handle. There is no ing between the Kernel Handle and the file descriptor. Therefore, do not expect to get the relevant file descriptor through the Kernel Handle.

Mixing C Runtime libraries and APIS is not a good method. If you remember correctly, C language encapsulates the thread functions (_ beginthread, _ endthread) and APIs (createthread, closehandle) there are similar issues between the two.

Summary:

_ Open_osfhandle and _ get_osfhandle are both functions to be used with caution. _ open_osfhandle allocates a file descriptor Based on handle. In this case, _ close must be used to close the file descriptor, _ get_osfhandle only obtains the corresponding file handle Handle Based on the file descriptor. You still need to manage the original file descriptor. These two functions try to connect the C Runtime Library file descriptor and the kernel file handle, but in fact it will lead to many traps.

The best solution is not to mix file descriptors and Kernel Handle handle. When handle is used, Windows APIs are honestly used. When I wrote this code, I saw the implementation of ACE and found that his internal implementation is an honest and practical API: createfile (Use :: createfile has to write a lot of code to implement an interface similar to open.) I still have to laugh at it, and I found myself the best.

Recommended Music: the "Xi'an Incident" and "Liu chuanfeng and cangjingkong", derickhu, and sasukeliu of heshe graduated from Xi'an. To them.

[The author of this article is Yan du Han tan, in the spirit of freedom, you can be in the profit of the complete reprinted this document, reprinted Please attach blog link: http://www.cnblogs.com/fullsail/ or http://blog.csdn.net/fullsail, the negative is a dollar, every figure one hundred no. For the Baidu Library. 360doc price doubled]

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.