Recientemente recibí un fragmento de código en el kernel de Linux:
static int fb_mmap(struct file *file, struct vm_area_struct * vma) __acquires(&info->lock) __releases(&info->lock) { ... } Lo que me confundió son las dos funciones __ que siguen a static int fb_mmap() justo antes de "{" ,
a). ¿Cuál es el propósito de las dos __funciones?
b). ¿Por qué en esa posición?
c). ¿Por qué tienen el prefijo "__" ?
d). ¿Hay otros ejemplos similares a este?
No todo lo que termina con un par de paréntesis es una función (llamada). En este caso son ampliaciones de macros parametrizadas. Las macros se definen como
#define __acquires(x) __attribute__((context(x,0,1))) #define __releases(x) __attribute__((context(x,1,0))) en el archivo include/linux/compiler.h en el árbol de compilación del kernel.
El propósito de esas macros que se expanden en definiciones de atributos es anotar los símbolos de función con información sobre qué estructuras de bloqueo adquirirá la función (es decir, bloqueará) y liberará (es decir, desbloqueará). El propósito de estos en particular es depurar los mecanismos de bloqueo (el kernel de Linux contiene algún código que le permite detectar posibles situaciones de interbloqueo e informar sobre esto).
https://en.wikipedia.org/wiki/Sparse
__attribute__ es una palabra clave específica del compilador GCC, que permite asignar atributos a un símbolo dado http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#Function-Attributes
Dado que las macros se expanden a nivel de texto, antes de que el compilador las mire, el resultado de su fragmento en particular, que ven los compiladores reales, sería
static int fb_mmap(struct file *file, struct vm_area_struct * vma) __attribute__((context(&info->lock,0,1))) __attribute__((context(&info->lock,1,0))) { … } Esas macros comienzan con un doble guión bajo __ para indicar que son parte del entorno del compilador. Todos los identificadores que comienzan con uno o dos guiones bajos están reservados para la implementación del entorno del compilador. En el caso del kernel de Linux, debido a que Linux es un kernel de sistema operativo que no (porque simplemente no está disponible) usa la biblioteca estándar, es natural para él, define sus propias definiciones de entorno de compilación, privadas para él. Por lo tanto, los dos guiones bajos indican que se trata de cosas específicas del entorno/implementación del compilador.
Probablemente sean macros definidas con #define . Debe buscar la definición de tales macros y ver a qué se expanden. Podrían expandirse a algún pragma dando pistas al compilador; pueden expandirse a nada dando pistas a los desarrolladores o alguna herramienta de análisis. El significado puede variar
El __attribute__ que evalúan estas macros son características específicas del compilador. man gcc explica algunos de los usos.
El prefijo __ generalmente se usa para evitar conflictos de nombres; el guión bajo doble como prefijo y el postfijo marcan un identificador como utilizado por el propio compilador.
Puede encontrar más información sobre los atributos gcc aquí .
Puede encontrar más información sobre el uso del núcleo de estos aquí .