VC + + file descriptor and kernel file handle handle
This article describes the C language in VC + + using the code file descriptor (file descriptor), the relationship between the kernel file handle handle, and the conversion function between the two _get_osfhandle,_open_osfhandle and the risk of using them. Code intermediate file descriptor and kernel handle handle in Windows code never share.
At the beginning of the article, I want to state that this is a bug I wrote, but it was discovered by two young lads derickhu,sasukeliu here again to thank them.
Last year, while writing some cross-platform code, we tried to simulate POSIX (Linux) functions in Windows, and found a problem, and if you want to use more of the features in Windows, you have to use the kernel file handle handle instead of VC + + The document descriptor (file descriptor) used by the C language function open, or int. To facilitate cross-platform, I try to hope that the interface is unified, we achieve the following:
Our collapsing platform code
zen_handle zen_os::open (const char *filename,
int open_mode,
mode_t perms)
Zen_handle is defined as the kernel handle handle of Windows under multiple Windows platforms, while Linux is defined as a kernel handle int for Linux.
VC + + default does implement a POSIX-compliant open function, the return value is also a standard file descriptor int
The Open function
int _open (
const char *filename,
int oflag [,
int pmode]
) implemented under Windows;
So if there is a way to switch from the C language file descriptor to the Windows kernel handle, then I can use the _open function directly. Google has found these two functions _get_osfhandle,_open_osfhandle. The understanding at the time was that _get_osfhandle converting the file descriptor to Handle,_open_osfhandle would handle the file descriptor.
MSDN
retrieves the Operating-system file handle this is associated with the specified file descriptor.
intptr_t _get_osfhandle (
int fd);
Associates a C run-time file descriptor with a existing Operating-system file handle.
int _open_osfhandle (
intptr_t osfhandle,
int flags
);
So my code is written.
When open, call _get_osfhandle get kernel handle,
//omit a lot of other code
//open function opens the file with _sopen_s, with _get_ Osfhandle Convert to handle provided to other places using
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 closed, convert HANDLE to a file descriptor with _open_osfhandle, and then _close 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 first implementation of the code is to take advantage of the Open function (our code defines _crt_nonstdc_no_deprecate, not in front of the POSIX function), and the first test is basically OK. But later found in some colleagues of the machine:: The close function will be an assertion error, a bit inexplicable, by replacing the open function of the code with the Sopen_s,close function to replace _close temporarily evade the problem (note that the _close function and the close function is indeed two implementations).
Recently refactoring online, a service program will continue to open,close files, after running 3 days will crash, the error is the file description symbol is not enough. Two of my 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,3 file descriptor is not the same
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, kernel handle consistent
HANDLE Fh_3 = (HANDLE) _get_osfhandle (filedesc_1);
Std::cout << (int) fh_3 << Std::endl;
return 0;
}
The results of the output are available in the comments above, and the result is that the file descriptor that was obtained at each call to _open_osfhandle is not the original file descriptor.
It seems completely wrong to understand the meaning of the _open_osfhandle function. _open_osfhandle is not related to the original file descriptor, but rather to handle a related C language descriptor, not to retrieve this handle corresponding (MSDN This place description incredibly use associates).
It is clear from the following figure why there are file descriptor leaks for the C function. (This is probably also the reason why the assertion was originally caused)
Of course, after reviewing MSDN, you can see that the MSDN _open_osfhandle function remark still has relevant clues (e Rotten really affects programming ability).
The _open_osfhandle function allocates a C Run-time file descriptor and associates it with the Operating-system file Handl e specified by Osfhandle .....
In fact, I think that the time to write this code is too careless, Windows must be using their own API, the kernel of their own internal handle management can be Handle,c language run-time library function encapsulation is certainly just the upper layer of a package. Therefore, the C function library to save the mapping relationship, must only be the file descriptor to the kernel handle, there is no kernel handle to the file descriptor mapping, so do not expect to get the relevant file descriptor through the kernel handle.
Mixing C Run-time Libraries and APIs is not a good way to do this, but there are similar problems with the C language encapsulating the thread's functions (_beginthread,_endthread) and the API (Createthread,closehandle), if not mistaken.
Summarize:
_open_osfhandle and _get_osfhandle are the functions to be used cautiously, _open_osfhandle to assign a file descriptor based on handle, which must be _close to close the file descriptor, _get_ Osfhandle just according to the file descriptor to get the corresponding file handle handle, you still have to manage the original file descriptor. These 2 functions attempt to connect the C Run-time library file descriptor with the kernel file handle handle, but it can actually lead to many traps, as well as not.
The best solution is not to mix the file descriptor with the kernel handle handle, and use the Windows API when using handle. When writing this piece of code to see the implementation of the ace, found that his internal implementation is honest with api,::createfile (with:: CreateFile to achieve a similar open interface to write a lot of code), I also incomparable ridicule, the results found that the turtle or himself.
Recommended Music: Black Caesar's "Xi ' an incident" and "Chuan Feng and Cang jing Empty", Derickhu,sasukeliu they are all graduated from XI ' an. Give them.
"The author is the Yan du Cold Lake, in the spirit of freedom, you can in the absence of profit complete reprint this document, reprint please attach blog link: http://www.cnblogs.com/fullsail/or http://blog.csdn.net/ Fullsail, otherwise a dollar per word, each figure 100 do not bargain. To the Baidu Library. 360doc increases by One times "