Estoy tratando de entender cómo funciona una función, digamos mkdir
, funciona mirando el código fuente del kernel. Este es un intento de comprender las funciones internas del kernel y navegar entre varias funciones. Sé 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 está implementada esta función. Desde el directorio de origen, probé
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 el
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 siga el kernel al definir e implementar métodos?
NOTA:estoy usando el kernel 2.6.36-rc1.
Respuesta aceptada:
Las llamadas al sistema no se manejan como llamadas a funciones normales. 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 ensamblador en línea inyectado en su programa en el sitio de la llamada. El código del lado del kernel que "capta" la llamada del sistema también es un material de bajo nivel que probablemente no necesite comprender en profundidad, al menos al principio.
En include/linux/syscalls.h
en el directorio fuente de su kernel, encontrará esto:
asmlinkage long sys_mkdir(const char __user *pathname, int mode);
Luego en /usr/include/asm*/unistd.h
, encuentras 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 oa una función en una biblioteca vinculada a su programa. El código de unión de ensamblado en línea que mencioné anteriormente usa esto para hacer la transición del espacio del usuario al kernel, llevándose sus parámetros junto con él.
Otra prueba 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 open(2)
está sobrecargado, una característica de C++, no de 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 una cantidad variable de argumentos).
Para responder a su primera pregunta, no hay un solo archivo donde mkdir()
existe 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 kernel oculte todo eso detrás de una sola llamada al sistema se llama VFS. Entonces, probablemente quieras comenzar a investigar 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()
, definido en fs/ext4/namei.c
.
En cuanto a su segunda pregunta, sí, hay patrones para todo esto, pero no una sola regla. Lo que realmente necesita es una comprensión bastante amplia de cómo funciona el kernel para averiguar dónde debe buscar cualquier llamada al 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 kernel.
Le recomiendo que obtenga una copia de "Understanding the Linux Kernel" de Bovet y Cesati.