it-swarm-es.tech

¿Cómo puedo encontrar las implementaciones de las llamadas al sistema kernel de Linux?

Estoy tratando de entender cómo funciona una función, digamos mkdir, mirando la fuente del núcleo. Este es un intento de comprender las partes internas del núcleo y navegar entre varias funciones. Sé que mkdir está definido en sys/stat.h. Encontré el prototipo:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

Ahora necesito ver en qué archivo C se implementa esta función. Desde el directorio fuente, intenté

ack "int mkdir"

que se muestra

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

Pero ninguno de ellos coincide con la definición en sys/stat.h.

Preguntas

  1. ¿Qué archivo tiene la implementación mkdir?
  2. Con una definición de función como la anterior, ¿cómo puedo averiguar qué archivo tiene la implementación? ¿Hay algún patrón que el núcleo siga para definir e implementar métodos?

NOTA: Estoy usando kernel 2.6.36-rc1 .

376
Navaneeth K N

Las llamadas al sistema no se manejan como llamadas a funciones regulares. Se necesita un código especial para hacer la transición del espacio del usuario al espacio del núcleo, básicamente un poco de código de ensamblaje en línea inyectado en su programa en el sitio de la llamada. El código del lado del kernel que "atrapa" la llamada del sistema también es algo de bajo nivel que probablemente no necesite comprender profundamente, al menos al principio.

En include/linux/syscalls.h debajo de su directorio de origen del núcleo, encontrará esto:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

Luego, en /usr/include/asm*/unistd.h, Encontrará esto:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Este código dice mkdir(2) es la llamada al sistema # 83. Es decir, las llamadas al sistema se llaman por número, no por dirección como con una llamada de función normal dentro de su propio programa o a una función en una biblioteca vinculada a su programa. El código de cola de ensamblaje en línea que mencioné anteriormente usa esto para hacer la transición del usuario al espacio del núcleo, tomando sus parámetros junto con él.

Otra evidencia de que las cosas son un poco raras aquí es que no siempre hay una lista estricta de parámetros para las llamadas al sistema: open(2), por ejemplo, puede tomar 2 o 3 parámetros. Eso significa que open(2) es sobrecargado , una característica de C++, no C, pero la interfaz syscall es compatible con C. (Esto no es lo mismo que C's función varargs , que permite que una sola función tome un número variable de argumentos).

Para responder a su primera pregunta, no existe un archivo único donde exista mkdir(). Linux admite muchos sistemas de archivos diferentes y cada uno tiene su propia implementación de la operación "mkdir". La capa de abstracción que permite que el núcleo oculte todo eso detrás de una sola llamada al sistema se llama VFS . Entonces, probablemente desee comenzar a cavar en fs/namei.c, Con vfs_mkdir(). Las implementaciones reales del código de modificación del sistema de archivos de bajo nivel están en otra parte. Por ejemplo, la implementación de ext4 se llama ext4_mkdir(), definida en fs/ext4/namei.c .

En cuanto a su segunda pregunta, sí, hay patrones para todo esto, pero no hay una sola regla. Lo que realmente necesita es una comprensión bastante amplia de cómo funciona el kernel para determinar dónde debe buscar cualquier llamada de sistema en particular. No todas las llamadas al sistema involucran el VFS, por lo que sus cadenas de llamadas del lado del kernel no comienzan todas en fs/namei.c. mmap(2), por ejemplo, comienza en mm/mmap.c , porque es parte del subsistema de gestión de memoria ("mm") del núcleo.

Le recomiendo que obtenga una copia de " Comprensión del kernel de Linux " de Bovet y Cesati.

388
Warren Young

Esto probablemente no responda su pregunta directamente, pero he encontrado que strace es realmente genial cuando trato de entender las llamadas subyacentes del sistema, en acción, que están hechas incluso para los comandos de Shell más simples. p.ej.

strace -o trace.txt mkdir mynewdir

El sistema solicita el comando mkdir mynewdir se volcará a trace.txt para su placer visual.

86
Banjer

Un buen lugar para leer la fuente del kernel de Linux es referencia cruzada de Linux (LXR) ¹. Las búsquedas devuelven coincidencias escritas (prototipos de funciones, declaraciones de variables, etc.) además de los resultados de búsqueda de texto libre, por lo que es más práctico que un simple grep (y más rápido también).

LXR no expande las definiciones de preprocesador. Las llamadas al sistema tienen su nombre destrozado por el preprocesador en todo el lugar. Sin embargo, la mayoría de las llamadas al sistema (¿todas?) Se definen con una de las SYSCALL_DEFINEx familias de macros. Como mkdir toma dos argumentos, una búsqueda de SYSCALL_DEFINE2(mkdir conduce a declaración de mkdir syscall :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

okay, sys_mkdirat significa que es el mkdirat syscall, por lo que hacer clic en él solo te lleva a la declaración en include/linux/syscalls.h, pero la definición está justo arriba.

El trabajo principal de mkdirat es llamar a vfs_mkdir (VFS es la capa genérica del sistema de archivos). Al hacer clic en eso, se muestran dos resultados de búsqueda: la declaración en include/linux/fs.h, y la definición algunas líneas arriba. El trabajo principal de vfs_mkdir es llamar a la implementación específica del sistema de archivos: dir->i_op->mkdir. Para saber cómo se implementa ¡esto, debe recurrir a la implementación del sistema de archivos individual, y no existe una regla estricta, incluso podría ser un módulo fuera del árbol del núcleo.

¹ LXR es un programa de indexación. Hay varios sitios web que proporcionan una interfaz para LXR, con conjuntos ligeramente diferentes de versiones conocidas e interfaces web ligeramente diferentes. Tienden a ir y venir, así que si el que estás acostumbrado no está disponible, realiza una búsqueda en la web de "referencia cruzada de Linux" para encontrar otro.

Las llamadas al sistema generalmente se envuelven en la macro SYSCALL_DEFINEx(), por lo que un simple grep no las encuentra:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

El nombre de la función final después de expandir la macro termina siendo sys_mkdir. La macro SYSCALL_DEFINEx() agrega elementos repetitivos como el código de rastreo que debe tener cada definición de syscall.

22
stefanha

Nota: el archivo .h no define la función. Es declarado en ese archivo .h y definido (implementado) en otro lugar. Esto permite que el compilador incluya información sobre la firma de la función (prototipo) para permitir la verificación de tipo de argumentos y hacer coincidir los tipos de retorno con cualquier contexto de llamada en su código.

En general, los archivos .h (encabezado) en C se utilizan para declarar funciones y definir macros.

mkdir en particular es una llamada al sistema. Puede haber un GNU libc envoltorio alrededor de esa llamada del sistema (de hecho es casi seguro). La verdadera implementación del núcleo de mkdir se puede encontrar buscando las fuentes del núcleo y las llamadas del sistema en particular.

Tenga en cuenta que también habrá una implementación de algún tipo de código de creación de directorio para cada sistema de archivos. La capa VFS (sistema de archivos virtual) proporciona una API común a la que puede llamar la capa de llamada del sistema. Cada sistema de archivos debe registrar funciones para que la capa VFS llame. Esto permite que diferentes sistemas de archivos implementen su propia semántica de cómo se estructuran los directorios (por ejemplo, si se almacenan utilizando algún tipo de esquema de hash para que la búsqueda de entradas específicas sea más eficiente). Menciono esto porque es probable que se tropiece con estas funciones de creación de directorio específicas del sistema de archivos si está buscando en el árbol de fuentes del kernel de Linux.

17
Jim Dennis

Ninguna de las implementaciones que encontró coincide con el prototipo en sys/stat.h ¿Quizás sería más exitoso buscar una declaración de inclusión con este archivo de encabezado?

8
greg0ire

Aquí hay un par de publicaciones de blog realmente geniales que describen varias técnicas para buscar el código fuente de kernel de bajo nivel.

6
An̲̳̳drew