Saltar al contenido

¿Cómo funciona exactamente fopen (), fclose ()?

Hola, hemos encontrado la solución a tu interrogante, desplázate y la verás a continuación.

Solución:

Descargo de responsabilidad: en su mayoría, no estoy calificado para hablar de esto. Sería genial si alguien con más conocimientos también publicara.

Archivos

Los detalles de cómo se implementan cosas como fopen () dependerán mucho del sistema operativo (UNIX también tiene fopen (), por ejemplo). Incluso las versiones de Windows pueden diferir mucho entre sí.

Te daré mi idea de cómo funciona, pero es básicamente una especulación.

  • Cuando se llama, fopen asigna un objeto FILE en el montón. Tenga en cuenta que los datos en un objeto FILE no están documentados: FILE es una estructura opaca, solo puede usar punteros a FILE desde su código.
  • El objeto FILE se inicializa. Por ejemplo, algo como fillLevel = 0 donde fillLevel es la cantidad de datos almacenados en búfer que aún no se han vaciado.
  • Una llamada al controlador del sistema de archivos (controlador FS) abre el archivo y le proporciona un identificador, que se coloca en algún lugar de la estructura FILE.
    • Para hacer esto, el controlador FS determina la dirección de HDD correspondiente a la ruta solicitada y recuerda internamente esta dirección de HDD, para que luego pueda cumplir con las llamadas a fread, etc.
      • El controlador FS utiliza una especie de tabla de indexación (almacenada en el disco duro) para averiguar la dirección del disco duro correspondiente a la ruta solicitada. Esto diferirá mucho según el tipo de sistema de archivos: FAT32, NTFS, etc.
      • El controlador FS se basa en el controlador HDD para realizar las lecturas y escrituras reales en el HDD.
  • Se puede asignar una caché en la RAM para el archivo. De esta manera, si el usuario solicita la lectura de 1 byte, C ++ puede leer una KB por si acaso, por lo que las lecturas posteriores serán instantáneas.
  • Un puntero al ARCHIVO asignado se devuelve desde fopen.

Si abre un archivo y nunca lo cierra, algunas cosas se filtrarán, sí. La estructura FILE se filtrará, los datos internos del controlador FS se filtrarán, el caché (si lo hay) también se filtrará.

Pero la memoria no es lo único que se filtrará. El archivo en sí se filtrará, porque el sistema operativo pensará que está abierto cuando no lo está. Esto puede convertirse en un problema, por ejemplo, en Windows, donde un archivo abierto en modo de escritura no se puede volver a abrir en modo de escritura hasta que se haya cerrado.

Si su aplicación se cierra sin cerrar algún archivo, la mayoría de los sistemas operativos se limpiarán después. Pero eso no sirve de mucho, porque su aplicación probablemente se ejecutará durante mucho tiempo antes de salir, y durante ese tiempo, aún deberá cerrar correctamente todos los archivos. Además, no puede confiar completamente en el sistema operativo para limpiar después de usted; no está garantizado en el estándar C.

Enchufes

La implementación de un socket dependerá del tipo de socket: socket de escucha de red, socket de cliente de red, socket entre procesos, etc.

Una discusión completa de todos los tipos de sockets y sus posibles implementaciones no encajaría aquí.

En breve:

  • al igual que un archivo, un socket mantiene cierta información en la RAM, describiendo cosas relevantes para su funcionamiento, como la IP del host remoto.
  • también puede tener cachés en RAM por razones de rendimiento
  • Puede retener recursos del sistema operativo finitos, como puertos abiertos, lo que los hace no disponibles para su uso por otras aplicaciones.

Todas estas cosas se filtrarán si no cierra el enchufe.

El papel del SO en los sockets

El sistema operativo implementa el estándar TCP / IP, Ethernet y otros protocolos necesarios para programar / enviar / aceptar conexiones y hacerlas disponibles para el código de usuario a través de una API como Berkeley Sockets.

El sistema operativo delegará la E / S de red (comunicación con la tarjeta de red) al controlador de red.

Con VS2017 en Windows 10, puede ver el interno por pila de llamadas:

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::tsopen_nolock(int * && , int * && , const char * const & , const int & , int && , const int & , int && ) Line 109  C++
ucrtbased.dll!common_sopen_dispatch(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::tsopen_s(int * && , const char * const & , const int & , const int & , int && ) Line 109 C++
ucrtbased.dll!common_openfile(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::open_file(const char * const & , const char * const & , const int & , _iobuf * && ) Line 109 C++
ucrtbased.dll!common_fsopen(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++

La mayoría de los códigos están en:

C:Program Files (x86)Windows Kits10Source10.0.17763.0ucrtstdiofopen.cpp
C:Program Files (x86)Windows Kits10Source10.0.17763.0ucrtstdioopenfile.cpp
C:Program Files (x86)Windows Kits10Source10.0.17763.0ucrtlowioopen.cpp

En _wsopen_nolock en open.cpp, hay:

// 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();

Finalmente, llama a la API de Windows CreateFileW que llama a la API oculta “NtCreateFile” cuyo código de ensamblaje es:

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]

Así que finalmente ejecuta la instrucción syscall que entra en el código del kernel.

Puntuaciones y reseñas

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *