関数fopen、fclose、socket、closesocketについて疑問に思っていました。fopenを呼び出したり、ソケットを開いたりするとき、正確には何が起こっていますか(特にメモリに関して)?
ファイル/ソケットを閉じずに開くと、メモリリークが発生する可能性がありますか?
そして第三に、ソケットはどのように作成され、メモリに関してはどのように見えますか?
また、ソケットの読み取りとデータの送信におけるオペレーティングシステム(Windows)の役割にも関心があります。
免責事項:私はこれについて話す資格がほとんどありません。もっと知識のある人も投稿してくれたら嬉しいです。
fopen()のようなものがどのように実装されるかの詳細は、オペレーティングシステムに大きく依存します(たとえば、UNIXにはfopen()もあります)。Windowsのバージョンでさえ、互いに大きく異なる可能性があります。
それがどのように機能するかについての私の考えをあなたに与えるでしょう、しかしそれは基本的に推測です。
fillLevel = 0
fillLevelは、まだフラッシュされていないバッファリングされたデータの量です。ファイルを開いて決して閉じないと、いくつかのことがリークします。FILE構造体がリークし、FSドライバーの内部データがリークし、キャッシュ(存在する場合)もリークします。
しかし、リークするのはメモリだけではありません。OSは開いていないときに開いていると見なすため、ファイル自体がリークします。これは、たとえばWindowsで問題になる可能性があります。この場合、書き込みモードで開いたファイルは、閉じるまで書き込みモードで再び開くことができません。
一部のファイルを閉じずにアプリを終了すると、ほとんどのOSはその後クリーンアップします。ただし、アプリは終了する前に長時間実行される可能性があり、その間もすべてのファイルを適切に閉じる必要があるため、あまり役に立ちません。また、後のクリーンアップをOSに完全に依存することはできません。これは、C標準では保証されていません。
ソケットの実装は、ソケットのタイプ(ネットワークリッスンソケット、ネットワーククライアントソケット、プロセス間ソケットなど)によって異なります。
すべてのタイプのソケットとそれらの可能な実装の完全な説明は、ここには当てはまりません。
要するに:
ソケットを閉じないと、これらすべてのものがリークします。
OSは、TCP / IP標準、イーサネット、および接続のスケジュール/ディスパッチ/受け入れに必要なその他のプロトコルを実装し、バークレーソケットなどのAPIを介してユーザーコードでそれらを利用できるようにします。
OSは、ネットワークI / O(ネットワークカードとの通信)をネットワークドライバーに委任します。
Windows 10のVS2017では、コールスタックで内部を確認できます。
ntdll.dll!NtCreateFile() Unknown
KernelBase.dll!CreateFileInternal() Unknown
KernelBase.dll!CreateFileW() Unknown
ucrtbased.dll!create_file(const wchar_t * const path, _SECURITY_ATTRIBUTES * const security_attributes, const `anonymous-namespace'::file_options options) Line 234 C++
ucrtbased.dll!_wsopen_nolock(int * punlock_flag, int * pfh, const wchar_t * path, int oflag, int shflag, int pmode, int secure) Line 702 C++
ucrtbased.dll!_sopen_nolock(int * punlock_flag, int * pfh, const char * path, int oflag, int shflag, int pmode, int secure) Line 852 C++
ucrtbased.dll!__crt_char_traits<char>::tsopen_nolock<int * __ptr64,int * __ptr64,char const * __ptr64 const & __ptr64,int const & __ptr64,int,int const & __ptr64,int>(int * && <args_0>, int * && <args_1>, const char * const & <args_2>, const int & <args_3>, int && <args_4>, const int & <args_5>, int && <args_6>) Line 109 C++
ucrtbased.dll!common_sopen_dispatch<char>(const char * const path, const int oflag, const int shflag, const int pmode, int * const pfh, const int secure) Line 172 C++
ucrtbased.dll!_sopen_dispatch(const char * path, int oflag, int shflag, int pmode, int * pfh, int secure) Line 204 C++
ucrtbased.dll!_sopen_s(int * pfh, const char * path, int oflag, int shflag, int pmode) Line 895 C++
ucrtbased.dll!__crt_char_traits<char>::tsopen_s<int * __ptr64,char const * __ptr64 const & __ptr64,int const & __ptr64,int const & __ptr64,int>(int * && <args_0>, const char * const & <args_1>, const int & <args_2>, const int & <args_3>, int && <args_4>) Line 109 C++
ucrtbased.dll!common_openfile<char>(const char * const file_name, const char * const mode, const int share_flag, const __crt_stdio_stream stream) Line 38 C++
ucrtbased.dll!_openfile(const char * file_name, const char * mode, int share_flag, _iobuf * public_stream) Line 67 C++
ucrtbased.dll!__crt_char_traits<char>::open_file<char const * __ptr64 const & __ptr64,char const * __ptr64 const & __ptr64,int const & __ptr64,_iobuf * __ptr64>(const char * const & <args_0>, const char * const & <args_1>, const int & <args_2>, _iobuf * && <args_3>) Line 109 C++
ucrtbased.dll!common_fsopen<char>(const char * const file_name, const char * const mode, const int share_flag) Line 54 C++
ucrtbased.dll!fopen(const char * file, const char * mode) Line 104 C++
ほとんどのコードは次のとおりです。
C:\Program Files (x86)\Windows Kits\10\Source\10.0.17763.0\ucrt\stdio\fopen.cpp
C:\Program Files (x86)\Windows Kits\10\Source\10.0.17763.0\ucrt\stdio\openfile.cpp
C:\Program Files (x86)\Windows Kits\10\Source\10.0.17763.0\ucrt\lowio\open.cpp
open.cppの_wsopen_nolockには、次のものがあります。
// Allocate the CRT file handle. Note that if a handle is allocated, it is
// locked when it is returned by the allocation function. It is our caller's
// responsibility to unlock the file handle (we do not unlock it before
// returning).
*pfh = _alloc_osfhnd();
最後に、アセンブリコードが次の非表示API「NtCreateFile」を呼び出すWindowsAPICreateFileWを呼び出します。
NtCreateFile:
00007FFFD81A0120 mov r10,rcx
00007FFFD81A0123 mov eax,55h
00007FFFD81A0128 test byte ptr[7FFE0308h],1
00007FFFD81A0130 jne NtCreateFile+15h(07FFFD81A0135h)
00007FFFD81A0132 syscall
00007FFFD81A0134 ret
00007FFFD81A0135 int 2Eh
00007FFFD81A0137 ret
00007FFFD81A0138 nop dword ptr[rax + rax]
最後に、カーネルコードに入るsyscall命令を実行します。