Si la función recibe un puntero a los datos del espacio de usuario, debe usar copy_from_user()
para copiar los datos apuntados desde el espacio del usuario al espacio del núcleo (y viceversa).
Tenga en cuenta que el valor del puntero en sí se pasa por valor (como todos los parámetros de C), por lo que no tiene que hacer un copy_from_user()
para obtener el valor del puntero antes de poder copy_from_user()
los datos a los que apunta.
Los argumentos numéricos funcionan de la misma manera que los argumentos de puntero; en términos de C, ambos son escalares. No tienes que usar copy_from_user()
para copiar el valor del parámetro; eso ya esta copiado. Solo tiene que usarlo para copiar datos a los que apunta un puntero pasado.
Entonces, si tiene un parámetro de tipo int
, puedes usarlo directamente. Si su parámetro apunta a un int
, luego el int
el objeto estará en el espacio del usuario, y debe usar copy_to_user
para copiar el valor de ese objeto en el espacio del kernel.
Cuando un usuario pasa datos al espacio del kernel, estos datos se pueden dividir en varias páginas, y estas páginas pueden estar incluso en memoria intercambiada . En estos casos, tendrá que esperar a que el núcleo cambie de página y obtenga acceso a la página donde se encuentran los datos. En el caso de tipos de datos elementales (como int o punteros), también es cierto que algunas arquitecturas (en particular, Intel x86) no obligue al usuario a alinear los datos para que incluso un número entero se pueda dividir alrededor de un borde de página. Puede tener acceso a la primera parte de su entero, pero debe esperar a que el administrador de memoria intercambie la segunda antes de acceder a todo.
Puede ahorrar algunos viajes de ida y vuelta colocando todos los datos del usuario en una estructura cuyo puntero se pasa al kernel. Puede copy_from_user como un bloque y guardar los accesos (y correr el riesgo de ser bloqueado varias veces)
Entonces, y como conclusión, use las funciones incluso para tipos básicos , ya que hay un montón de ellos. No asuma nada sobre dónde pueden estar los datos del usuario cuando se ejecuta en modo kernel. Tiene acceso a él, pero las direcciones virtuales del núcleo de los datos de usuario no tienen nada que ver con las direcciones virtuales que se ven en el modo de usuario.