En Linux, ¿existe una capa/script del sistema que maneje la apertura de archivos?

En Linux, ¿existe una capa/script del sistema que maneje la apertura de archivos?

En Linux, ¿existe una capa/script que maneje las solicitudes de programa para abrir archivos?

Como cuando abres un descriptor de archivo en bash: exec 3 <>/documents/foo.txto se abre tu editor de texto/documents/foo.txt

No puedo creer que un editor pueda "simplemente abrir un archivo" para acceso de lectura/escritura por sí solo.

Prefiero imaginar que esto es una solicitud a una "capa" (¿Secuencia de comandos init.d?) que, para empezar, solo puede abrir una cierta cantidad de archivos y que controla los archivos abiertos con sus tipos de acceso, mediante qué procesos se abren, etc.

Respuesta1

Esta capa está dentro del kernel en Linux y otros sistemas que no se alejan demasiado del diseño histórico de Unix (y también en la mayoría de los sistemas operativos que no son Unix).

Esta parte del núcleo se llamaCapa VFS (sistema de archivos virtual). La función del VFS es gestionar información sobre archivos abiertos (la correspondencia entredescriptores de archivos,abrir descripciones de archivosy entradas de directorio), para analizar rutas de archivos (interpretando y /) y para enviar operaciones en entradas de directorio al controlador correcto del sistema de archivos....

La mayoría de los controladores del sistema de archivos también están en el kernel, pero elFUSIBLEEl controlador del sistema de archivos permite delegar esta funcionalidad fuera del kernel. Las operaciones del sistema de archivos también pueden involucrar el código de tierra del usuario si un almacenamiento de nivel inferior lo hace, por ejemplo, si un sistema de archivos de disco está en undispositivo de bucle.

Respuesta2

La apertura de archivos en Linux la maneja directamente el kernelpero hay varias cosas que puedes hacer para influir y estudiar el proceso.


Diagrama de pila de almacenamiento de Linux


llamadas al sistema

Comenzando desde arriba, puede ver que la interfaz que utilizan las aplicaciones para interactuar con los archivos esllamadas al sistema.

Abierto,leeryescribirhaz lo que esperas, mientrasestadísticadevuelve información sobre un archivo sin abrirlo.

Puedes estudiar el uso que hace un programa de llamadas al sistema relacionadas con archivos usando strace:

$ strace -e trace=%file /bin/ls /etc
[...]
stat("/etc", {st_mode=S_IFDIR|0755,  ...}) = 0
openat(AT_FDCWD, "/etc", O_RDONLY...) = 3

Esto analiza las llamadas al sistema causadas por ls /etc, mostrando que staty openatson llamados en el /etcdirectorio.

Quizás se pregunte por qué llamamos a operaciones de archivos en un directorio. En UNIX, los directorios también son archivos. De hechotodo es un archivo!


Descriptores de archivos

Quizás se pregunte acerca del openat() = 3resultado anterior.

En UNIX los archivos abiertos están representados por undescriptor de archivo, que es una representación única del archivo abierto mediante un determinado proceso. Los descriptores de archivo 0, 1 y 2 generalmente están reservados para elflujos estándar(entrada/salida del usuario), por lo que el primer archivo abierto será 3.

Puede obtener una lista de descriptores de archivos abiertos para un proceso determinado utilizandolsof(yoistohbolígrafoFarchivos):

$ cat /dev/urandom > /dev/null &
[1] 3242
$ lsof -p 3242
COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
...
cat     3242 user         0u   CHR  136,0      0t0      3 /dev/pts/0
cat     3242 user         1w   CHR    1,3      0t0   1028 /dev/null
cat     3242 user         2u   CHR  136,0      0t0      3 /dev/pts/0
cat     3242 user         3r   CHR    1,9      0t0   1033 /dev/urandom

La FDcolumna le muestra el número del descriptor del archivo, junto con el acceso.

También puedes usarfuserpara buscar procesos que contienen archivos particulares:

$ fuser /dev/urandom
/dev/urandom:         ...  3242  ...

Pseudosistema de archivos de información de proceso - /proc

A estas alturas quizás te estés preguntando:pero, ¿cómo puedo lsofsaber qué archivos están abiertos en primer lugar??

Bueno, ¡echemos un vistazo!

$ strace -e trace=%file lsof -p 3242
...
stat("/proc/3242/", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
openat(AT_FDCWD, "/proc/3242/stat", O_RDONLY) = 4
...
openat(AT_FDCWD, "/proc/3242/fd", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 4
readlink("/proc/3242/fd/0", "/dev/pts/0", 4096) = 10
lstat("/proc/3242/fd/0", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0
stat("/proc/3242/fd/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
openat(AT_FDCWD, "/proc/3242/fdinfo/0", O_RDONLY) = 7
...

Entonces lsofsabe qué archivos están abiertos... ¡leyendo más archivos! En concreto, el directorio /proc/3242/fd. Todo lo que aparece a continuación /proces un sistema de archivos "falso" mantenido por el kernel. Puedes ls -lverlo para ver su estructura.


Influir en la apertura de archivos

Hay varios métodos que puede utilizar para influir en la apertura de archivos, aunque no son tan fáciles como simplemente reemplazar algún script.

Si está buscando cambiar la forma en que se almacenan o se accede a los archivos, como proporcionar cifrado, almacenarlos en caché, distribuirlos en varios discos o algo similar, es muy probable que ya exista unamapeador de dispositivosque se adapta a tus necesidades.

Si desea un control detallado sobre la apertura de archivos en un directorio/montaje en particular, puede escribir un simpleFUSIBLEsistema de archivos y montarlo.

A nivel de programa/proceso, puede utilizarLD_PRELOADpara cambiar las llamadas a la biblioteca C y evitar que realicen las llamadas al sistema normales.

La forma más difícil pero más flexible sería escribir su propio controlador de sistema de archivos.

Respuesta3

Administrar el acceso a los archivos es la primera y más importante función de un sistema operativo. DOS, que es uno de los sistemas operativos más antiguos en computadoras personales, significa Sistema Operativo de Disco. Permitió que los programas accedieran directamente al hardware en su mayor parte, pero no así para acceder a los archivos. Los programas tenían que usar llamadas de DOS y DOS se encargaba de ingresar y sacar datos de los archivos para el programa. Sólo las utilidades de disco accederían al disco duro y a los archivos directamente en DOS.

Los sistemas operativos modernos en modo protegido, como Linux, manejan el acceso a archivos como lo hace DOS, pero también requieren que cada acceso a cualquier cosa fuera del programa en sí (o cualquier otro programa con el que se haya configurado para compartir memoria) pase por el kernel (Linux es un núcleo).

Su programa en Linux puede llamar a una función en la biblioteca C para leer o escribir datos en un archivo. Luego, la biblioteca C hace su parte de organizar el acceso a los datos del archivo mientras se ejecuta en el mismo contexto que su programa. Luego, la biblioteca C llamará al kernel (Linux) con la función correcta para acceder a un archivo, lo que cambia la CPU al modo ring 0 o privilegiado. La CPU ahora ejecuta el controlador del sistema de archivos de Linux y el software del controlador del disco duro en modo privilegiado, que accede directamente al hardware para acceder al archivo. Los datos se copian al área de memoria donde la biblioteca C le indicó a Linux que colocara los datos, y la CPU vuelve al modo de usuario con el contexto de seguridad de su programa y la biblioteca C se reanuda y realiza cualquier procesamiento necesario. esos datos y luego vuelve a ejecutar su programa.

Respuesta4

En resumen, esto es lo que sucede cuando un programa escribe en un archivo.

  1. El programa le pide al kernel que openescriba un archivo, proporcionado por una ruta.
  2. El kernel configura algunas estructuras internas y delega parte de la tarea de abrir el archivo a un controlador específico para el tipo de sistema de archivos. Luego, el núcleo devuelve un descriptor de archivo, que es simplemente un número entero (por ejemplo, 3), al programa.
  3. El programa solicita al núcleo writeuna secuencia de bytes (por ejemplo, una cadena) al archivo al que hace referencia el descriptor de archivo.
  4. El núcleo nuevamente delega trabajo al controlador.
  5. Los pasos 3 y 4 probablemente se repitan varias veces.
  6. El programa solicita al kernel closeel archivo al que hace referencia el descriptor de archivo.
  7. El núcleo nuevamente delega trabajo al controlador y luego destruye las estructuras internas.

Aquí hay un programa ensamblador bastante minimalista que escribe "¡Hola mundo!" al archivo saludo.txt:

.text
.globl _start

_start:
    # Open and possible create file
    mov $2,             %rax        # syscall 'open'
    mov $path_start,    %rdi        # path
    mov $0101,          %rsi        # create + write
    mov $400,           %edx        # only user gets read permissions
    syscall

    mov %rax,           %r10        # file descriptor

    # Write string to file
    mov $1,             %rax        # syscall 'write'
    mov %r10,           %rdi        # file descriptor
    mov $msg_start,     %rsi        # start of data
    mov $msg_length,    %edx        # length of data
    syscall                         # perform syscall

    # Close file
    mov $3,             %rax        # syscall 'close'
    mov %r10,           %rdi        # file descriptor
    syscall

    # Exit program
    mov $60,            %rax        # syscall 'exit'
    syscall                         # perform syscall


.section .rodata

path_start:
    .string "greeting.txt\0"
path_end:
path_length = path_end - path_start


msg_start:
    .string "Hello World!\n"
msg_end:
msg_length = msg_end - msg_start

Guarde el código en write.s y compílelo usando

as -o write.o write.s
ld -o write   write.o

y luego correr con

./write

Ojalá todo funcione.

(Nota: no manejo ningún error. Esto es solo código de juguete).

información relacionada