Estoy tratando de entender cómo funciona una función, por ejemplo 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
se define 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
- ¿Qué archivo tiene la
mkdir
implementación? - 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 el kernel 2.6.36-rc1 .
linux-kernel
source
system-calls
Navaneeth KN
fuente
fuente
Respuestas:
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:Luego en
/usr/include/asm*/unistd.h
, encuentras esto:Este código dice que
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 queopen(2)
está sobrecargado , una característica de C ++, no C, pero la interfaz syscall es compatible con C. (Esto no es lo mismo que la función varargs de C , 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
mkdir()
exista. 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 quieras comenzar a cavarfs/namei.c
, convfs_mkdir()
. Las implementaciones reales del código de modificación del sistema de archivos de bajo nivel están en otra parte. Por ejemplo, se llama a la implementación ext4ext4_mkdir()
, definida enfs/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 núcleo para averiguar 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
fs/namei.c
.mmap(2)
, por ejemplo, comienza enmm/mmap.c
, porque es parte del subsistema de gestión de memoria ("mm") del núcleo.Le recomiendo que obtenga una copia de " Comprender el kernel de Linux " de Bovet y Cesati.
fuente
Documentation
subdirectorio del árbol de origen del núcleo con el que estoy trabajando....
como función varargs. Por supuesto, esto se implementa a nivel de libc. Puede pasar 0 o un valor basura al núcleo ABI cuando no se utiliza el tercer parámetro.Probablemente esto no responda su pregunta directamente, pero he encontrado
strace
que 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.ejEl sistema solicita el comando
mkdir mynewdir
se volcará a trace.txt para su placer visual.fuente
Un buen lugar para leer la fuente del kernel de Linux es la 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 también más rápido).
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. Comomkdir
toma dos argumentos, una búsqueda deSYSCALL_DEFINE2(mkdir
conduce a la declaración de lamkdir
llamada al sistema :ok,
sys_mkdirat
significa que es lamkdirat
llamada al sistema, por lo que hacer clic en él solo te lleva a la declaracióninclude/linux/syscalls.h
, pero la definición está justo arriba.El trabajo principal de
mkdirat
es llamarvfs_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 eninclude/linux/fs.h
y la definición algunas líneas arriba. La tarea principal devfs_mkdir
es llamar a la implementación del sistema de ficheros específicos:dir->i_op->mkdir
. Para saber cómo esto se lleva a cabo, hay que girar a la aplicación del sistema de archivos individuales, y no hay regla dura y rápida - que 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, por lo que si el que estás acostumbrado no está disponible, realiza una búsqueda web de "referencia cruzada de Linux" para encontrar otro.
fuente
Las llamadas al sistema generalmente se envuelven en la
SYSCALL_DEFINEx()
macro, por lo que un simplegrep
no las encuentra:El nombre de la función final después de que se expande la macro termina siendo
sys_mkdir
. LaSYSCALL_DEFINEx()
macro agrega elementos repetitivos como el código de seguimiento que cada definición de syscall debe tener.fuente
Nota: el archivo .h no define la función. Se declara en ese archivo .h y se define (implementa) 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 contenedor de libc de GNU alrededor de esa llamada al sistema (de hecho es casi seguro). La verdadera implementación del kernelmkdir
se puede encontrar buscando las fuentes del kernel 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 directorios específicas del sistema de archivos si está buscando en el árbol de fuentes del kernel de Linux.
fuente
Ninguna de las implementaciones que encontró coincide con el prototipo en sys / stat.h ¿Quizás la búsqueda de una declaración de inclusión con este archivo de encabezado sería más exitosa?
fuente
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.
fuente