1.. include:: ../disclaimer-sp.rst 2 3:Original: Documentation/process/4.Coding.rst 4:Translator: Carlos Bilbao <[email protected]> and Avadhut Naik <[email protected]> 5 6.. _sp_development_coding: 7 8Conseguir el código correcto 9============================ 10 11Si bien hay mucho que decir a favor de un proceso de diseño sólido y 12orientado a la comunidad, la prueba de cualquier proyecto de desarrollo del 13kernel está en el código resultante. Es el código lo que será examinado por 14otros desarrolladores y lo que será incluido (o no) en el árbol principal. 15Por lo tanto, es la calidad de este código lo que determinará el éxito 16final del proyecto. 17 18Esta sección examinará el proceso de programación. Comenzaremos observando 19algunas de las maneras en que los desarrolladores del kernel pueden cometer 20errores. Luego, el enfoque se dirigirá hacia hacer las cosas bien y las 21herramientas que pueden ayudar en dicha búsqueda. 22 23Problemas 24--------- 25 26Estilo de programación 27********************** 28 29El kernel ha tenido durante mucho tiempo un estilo de programación 30estándar, descrito en la documentación del kernel en 31`Documentation/process/coding-style.rst`. Durante gran parte de ese tiempo, 32las políticas descritas en ese archivo se tomaban como, en el mejor de los 33casos, orientativas. Como resultado, hay una cantidad considerable de 34código en el kernel que no cumple con las pautas de estilo de programación. 35La presencia de ese código lleva a dos peligros independientes para los 36desarrolladores del kernel. 37 38El primero de estos es creer que los estándares de programación del kernel 39no importan y no se aplican. La realidad es que agregar nuevo código al 40kernel es muy difícil si ese código no está escrito de acuerdo con el 41estándar; muchos desarrolladores solicitarán que el código sea reformateado 42antes de revisarlo. Una base de código tan grande como el kernel requiere 43cierta uniformidad para que los desarrolladores puedan comprender 44rápidamente cualquier parte de él. Así que ya no hay lugar para el código 45con formato extraño. 46 47Ocasionalmente, el estilo de programación del kernel entrará en conflicto 48con el estilo obligatorio de un empleador. En tales casos, el estilo del 49kernel tendrá que prevalecer antes de que el código pueda ser fusionado. 50Incluir código en el kernel significa renunciar a cierto grado de control 51de varias maneras, incluida la forma en que se formatea el código. 52 53La otra trampa es asumir que el código que ya está en el kernel necesita 54urgentemente correcciones de estilo de programación. Los desarrolladores 55pueden comenzar a generar parches de reformateo como una forma de 56familiarizarse con el proceso o como una forma de incluir su nombre en los 57registros de cambios del kernel, o ambos. Pero las correcciones puramente 58de estilo de programación son vistas como ruido por la comunidad de 59desarrollo; tienden a recibir una recepción adversa. Por lo tanto, este 60tipo de parche es mejor evitarlo. Es natural corregir el estilo de una 61parte del código mientras se trabaja en él por otras razones, pero los 62cambios de estilo de programación no deben hacerse por sí mismos. 63 64El documento de estilo de programación tampoco debe leerse como una ley 65absoluta que nunca puede transgredirse. Si hay una buena razón para ir en 66contra del estilo (una línea que se vuelve mucho menos legible si se divide 67para ajustarse al límite de 80 columnas, por ejemplo), perfecto. 68 69Tenga en cuenta que también puedes usar la herramienta `clang-format` para 70ayudarle con estas reglas, para reformatear rápidamente partes de su código 71automáticamente y para revisar archivos completos a fin de detectar errores 72de estilo de programación, errores tipográficos y posibles mejoras. También 73es útil para ordenar `#includes`, alinear variables/macros, reformatear 74texto y otras tareas similares. Consulte el archivo 75`Documentation/dev-tools/clang-format.rst` para más detalles. 76 77Algunas configuraciones básicas del editor, como la indentación y los 78finales de línea, se configurarán automáticamente si utilizas un editor 79compatible con EditorConfig. Consulte el sitio web oficial de EditorConfig 80para obtener más información: https://editorconfig.org/ 81 82Capas de abstracción 83******************** 84 85Los profesores de ciencias de la computación enseñan a los estudiantes a 86hacer un uso extensivo de capas de abstracción en nombre de la 87flexibilidad y el ocultamiento de la información. Sin duda, el kernel hace 88un uso extensivo de la abstracción; ningún proyecto que involucre varios 89millones de líneas de código podría sobrevivir de otra manera. Pero la 90experiencia ha demostrado que una abstracción excesiva o prematura puede 91ser tan perjudicial como la optimización prematura. La abstracción debe 92usarse en la medida necesaria y ya. 93 94A un nivel simple, considere una función que tiene un argumento que siempre 95se pasa como cero por todos los que la invocan. Uno podría mantener ese 96argumento por si alguien eventualmente necesita usar la flexibilidad 97adicional que proporciona. Sin embargo, para entonces, es probable que el 98código que implementa este argumento adicional se haya roto de alguna 99manera sutil que nunca se notó, porque nunca se ha utilizado. O, cuando 100surge la necesidad de flexibilidad adicional, no lo hace de una manera que 101coincida con la expectativa temprana del programador. Los desarrolladores 102del kernel rutinariamente enviarán parches para eliminar argumentos no 103utilizados; en general, no deberían añadirse en primer lugar. 104 105Las capas de abstracción que ocultan el acceso al hardware, a menudo para 106permitir que la mayor parte de un controlador se utilice con varios 107sistemas operativos, son especialmente mal vistas. Dichas capas oscurecen 108el código y pueden imponer una penalización en el rendimiento; no 109pertenecen al kernel de Linux. 110 111Por otro lado, si se encuentra copiando cantidades significativas de código 112de otro subsistema del kernel, es hora de preguntar si, de hecho, tendría 113sentido extraer parte de ese código en una biblioteca separada o 114implementar esa funcionalidad a un nivel superior. No tiene sentido 115replicar el mismo código en todo el kernel. 116 117Uso de #ifdef y del preprocesador en general 118******************************************** 119 120El preprocesador de C tiene una tentación poderosa para algunos 121programadores de C, quienes lo ven como una forma de programar 122eficientemente una gran cantidad de flexibilidad en un archivo fuente. Pero 123el preprocesador no es C, y el uso intensivo de él da como resultado un 124código mucho más difícil de leer para otros y más difícil de verificar por 125el compilador para su corrección. El uso intensivo del preprocesador es 126asi siempre un signo de un código que necesita algo de limpieza. 127 128La compilación condicional con `#ifdef` es, de hecho, una característica 129poderosa, y se usa dentro del kernel. Pero hay poco deseo de ver código que 130sté salpicado liberalmente con bloques `#ifdef`. Como regla general, el uso 131de `#ifdef` debe limitarse a los archivos de encabezado siempre que sea 132posible. El código condicionalmente compilado puede confinarse a funciones 133que, si el código no va a estar presente, simplemente se convierten en 134vacías. El compilador luego optimizará silenciosamente la llamada a la 135función vacía. El resultado es un código mucho más limpio y fácil de 136seguir. 137 138Las macros del preprocesador de C presentan varios peligros, incluida la 139posible evaluación múltiple de expresiones con efectos secundarios y la 140falta de seguridad de tipos. Si te sientes tentado a definir una macro, 141considera crear una función en línea en su lugar. El código resultante será 142el mismo, pero las funciones en línea son más fáciles de leer, no evalúan 143sus argumentos varias veces y permiten que el compilador realice 144comprobaciones de tipo en los argumentos y el valor de retorno. 145 146Funciones en línea 147****************** 148 149Las funciones en línea presentan su propio peligro, sin embargo. Los 150programadores pueden enamorarse de la eficiencia percibida al evitar una 151llamada a función y llenar un archivo fuente con funciones en línea. Esas 152funciones, sin embargo, pueden en realidad reducir el rendimiento. Dado que 153su código se replica en cada sitio de llamada, terminan hinchando el tamaño 154del kernel compilado. Eso, a su vez, crea presión en las cachés de memoria 155del procesador, lo que puede ralentizar la ejecución de manera drástica 156Las funciones en línea, como regla, deben ser bastante pequeñas y 157relativamente raras. El costo de una llamada a función, después de todo, no 158es tan alto; la creación de un gran número de funciones en línea es un 159ejemplo clásico de optimización prematura. 160 161En general, los programadores del kernel ignoran los efectos de caché bajo 162su propio riesgo. El clásico intercambio de tiempo/espacio que se enseña en 163las clases de estructuras de datos iniciales a menudo no se aplica al 164hardware contemporáneo. El espacio *es* tiempo, en el sentido de que un 165programa más grande se ejecutará más lentamente que uno más compacto. 166 167Los compiladores más recientes toman un papel cada vez más activo al 168decidir si una función dada debe realmente ser en línea o no. Por lo tanto, 169la colocación liberal de palabras clave "inline" puede no solo ser 170excesiva; también podría ser irrelevante. 171 172Bloqueo 173******* 174 175En mayo de 2006, la pila de red "Devicescape" fue, con gran fanfarria, 176lanzada bajo la licencia GPL y puesta a disposición para su inclusión en el 177kernel principal. Esta donación fue una noticia bienvenida; el soporte para 178redes inalámbricas en Linux se consideraba, en el mejor de los casos, 179deficiente, y la pila de Devicescape ofrecía la promesa de solucionar esa 180situación. Sin embargo, este código no fue incluido en el kernel principal 181hasta junio de 2007 (versión 2.6.22). ¿Qué sucedió? 182 183Este código mostró varios signos de haber sido desarrollado a puertas 184cerradas en una empresa. Pero un problema importante en particular fue que 185no estaba diseñado para funcionar en sistemas multiprocesador. Antes de que 186esta pila de red (ahora llamada mac80211) pudiera fusionarse, se tuvo que 187implementar un esquema de bloqueo en ella. 188 189Hubo un tiempo en que se podía desarrollar código para el kernel de Linux 190sin pensar en los problemas de concurrencia que presentan los sistemas 191multiprocesador. Ahora, sin embargo, este documento se está escribiendo en 192una computadora portátil con dos núcleos. Incluso en sistemas de un solo 193procesador, el trabajo que se está realizando para mejorar la capacidad de 194respuesta aumentará el nivel de concurrencia dentro del kernel. Los días en 195que se podía escribir código para el kernel sin pensar en el bloqueo han 196quedado atrás. 197 198Cualquier recurso (estructuras de datos, registros de hardware, etc.) que 199pueda ser accedido concurrentemente por más de un hilo debe estar protegido 200por un bloqueo. El nuevo código debe escribirse teniendo en cuenta este 201requisito; implementar el bloqueo después de que el código ya ha sido 202desarrollado es una tarea mucho más difícil. Los desarrolladores del kernel 203deben tomarse el tiempo para comprender bien los primitivos de bloqueo 204disponibles para elegir la herramienta adecuada para el trabajo. El código 205que muestre una falta de atención a la concurrencia tendrá un camino 206difícil para ser incluido en el kernel principal. 207 208Regresiones 209*********** 210 211Un último peligro que vale la pena mencionar es el siguiente: puede ser 212tentador realizar un cambio (que puede traer grandes mejoras) que cause un 213problema para los usuarios existentes. Este tipo de cambio se llama una 214"regresión", y las regresiones se han vuelto muy mal recibidas en el kernel 215principal. Con pocas excepciones, los cambios que causan regresiones serán 216revertidos si la regresión no se puede solucionar de manera oportuna. Es 217mucho mejor evitar la regresión desde el principio. 218 219A menudo se argumenta que una regresión puede justificarse si hace que las 220cosas funcionen para más personas de las que crea problemas. ¿Por qué no 221hacer un cambio si trae nueva funcionalidad a diez sistemas por cada uno 222que rompe? La mejor respuesta a esta pregunta fue expresada por Linus en 223julio de 2007 (traducido): 224 225:: 226 227 Entonces, no arreglamos errores introduciendo nuevos problemas. Eso 228 lleva a la locura, y nadie sabe si realmente se avanza. ¿Es dos pasos 229 adelante, uno atrás, o un paso adelante y dos atrás? 230 231(https://lwn.net/Articles/243460/). 232 233Un tipo de regresión especialmente mal recibido es cualquier tipo de cambio 234en la ABI del espacio de usuario. Una vez que se ha exportado una interfaz 235al espacio de usuario, debe ser soportada indefinidamente. Este hecho hace 236que la creación de interfaces para el espacio de usuario sea 237particularmente desafiante: dado que no pueden cambiarse de manera 238incompatible, deben hacerse bien desde el principio. Por esta razón, 239siempre se requiere una gran cantidad de reflexión, documentación clara y 240una amplia revisión para las interfaces del espacio de usuario. 241 242Herramientas de verificación de código 243************************************** 244 245Por ahora, al menos, escribir código libre de errores sigue siendo un ideal 246que pocos de nosotros podemos alcanzar. Sin embargo, lo que podemos esperar 247hacer es detectar y corregir tantos de esos errores como sea posible antes 248de que nuestro código se integre en el kernel principal. Con ese fin, los 249desarrolladores del kernel han reunido una impresionante variedad de 250herramientas que pueden detectar una amplia variedad de problemas oscuros 251de manera automatizada. Cualquier problema detectado por el ordenador es 252un problema que no afectará a un usuario más adelante, por lo que es lógico 253que las herramientas automatizadas se utilicen siempre que sea posible. 254 255El primer paso es simplemente prestar atención a las advertencias 256producidas por el compilador. Las versiones contemporáneas de gcc pueden 257detectar (y advertir sobre) una gran cantidad de errores potenciales. Con 258bastante frecuencia, estas advertencias apuntan a problemas reales. El 259código enviado para revisión no debería, por regla general, producir 260ninguna advertencia del compilador. Al silenciar las advertencias, tenga 261cuidado de comprender la causa real e intente evitar "correcciones" que 262hagan desaparecer la advertencia sin abordar su causa. 263 264Tenga en cuenta que no todas las advertencias del compilador están 265habilitadas de forma predeterminada. Compile el kernel con 266"make KCFLAGS=-W" para obtener el conjunto completo. 267 268El kernel proporciona varias opciones de configuración que activan 269funciones de depuración; la mayoría de estas se encuentran en el submenú 270"kernel hacking". Varias de estas opciones deben estar activadas para 271cualquier kernel utilizado para desarrollo o pruebas. En particular, 272debería activar: 273 274 - FRAME_WARN para obtener advertencias sobre marcos de pila más grandes 275 que una cantidad determinada. La salida generada puede ser extensa, pero 276 no es necesario preocuparse por las advertencias de otras partes del 277 kernel. 278 279 - DEBUG_OBJECTS agregará código para rastrear la vida útil de varios 280 objetos creados por el kernel y advertir cuando se realicen cosas fuera 281 de orden. Si está agregando un subsistema que crea (y exporta) objetos 282 complejos propios, considere agregar soporte para la infraestructura de 283 depuración de objetos. 284 285 - DEBUG_SLAB puede encontrar una variedad de errores en la asignación y 286 uso de memoria; debe usarse en la mayoría de los kernels de desarrollo. 287 288 - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP y DEBUG_MUTEXES encontrarán una serie 289 de errores comunes de bloqueo. 290 291Hay bastantes otras opciones de depuración, algunas de las cuales se 292discutirán más adelante. Algunas de ellas tienen un impacto significativo 293en el rendimiento y no deben usarse todo el tiempo. Pero dedicar tiempo a 294aprender las opciones disponibles probablemente será recompensado muchas 295veces en poco tiempo. 296 297Una de las herramientas de depuración más pesadas es el verificador de 298bloqueos, o "lockdep". Esta herramienta rastreará la adquisición y 299liberación de cada bloqueo (spinlock o mutex) en el sistema, el orden en 300que se adquieren los bloqueos en relación entre sí, el entorno actual de 301interrupción, y más. Luego, puede asegurarse de que los bloqueos siempre se 302adquieran en el mismo orden, que las mismas suposiciones de interrupción se 303apliquen en todas las situaciones, y así sucesivamente. En otras palabras, 304lockdep puede encontrar varios escenarios en los que el sistema podría, en 305raras ocasiones, bloquearse. Este tipo de problema puede ser doloroso 306(tanto para desarrolladores como para usuarios) en un sistema desplegado; 307lockdep permite encontrarlos de manera automatizada con anticipación. El 308código con cualquier tipo de bloqueo no trivial debe ejecutarse con lockdep 309habilitado antes de ser enviado para su inclusión. 310 311Como programador diligente del kernel, sin duda alguna, verificará el 312estado de retorno de cualquier operación (como una asignación de memoria) 313que pueda fallar. Sin embargo, el hecho es que las rutas de recuperación de 314fallos resultantes probablemente no hayan sido probadas en absoluto. El 315código no probado tiende a ser código roto; podría tener mucha más 316confianza en su código si todas esas rutas de manejo de errores se hubieran 317ejercitado algunas veces. 318 319El kernel proporciona un marco de inyección de fallos que puede hacer 320precisamente eso, especialmente donde están involucradas las asignaciones 321de memoria. Con la inyección de fallos habilitada, un porcentaje 322configurable de las asignaciones de memoria fallarán; estas fallas pueden 323restringirse a un rango específico de código. Ejecutar con la inyección de 324fallos habilitada permite al programador ver cómo responde el código cuando 325las cosas van mal. Consulte 326Documentation/fault-injection/fault-injection.rst para obtener más 327información sobre cómo utilizar esta funcionalidad. 328 329Otros tipos de errores se pueden encontrar con la herramienta de análisis 330estático "sparse". Con sparse, el programador puede recibir advertencias 331sobre confusiones entre direcciones del espacio de usuario y del kernel, 332mezcla de cantidades big-endian y little-endian, el paso de valores enteros 333donde se espera un conjunto de banderas de bits, y así sucesivamente. 334Sparse debe instalarse por separado (puede encontrarse en 335https://sparse.wiki.kernel.org/index.php/Main_Page si su distribución no lo 336empaqueta); luego, puede ejecutarse en el código agregando "C=1" a su 337comando make. 338 339La herramienta "Coccinelle" (http://coccinelle.lip6.fr/) puede encontrar 340una amplia variedad de posibles problemas de codificación; también puede 341proponer correcciones para esos problemas. Bastantes "parches semánticos" 342para el kernel se han empaquetado en el directorio scripts/coccinelle; 343ejecutar "make coccicheck" ejecutará esos parches semánticos e informará 344sobre cualquier problema encontrado. Consulte: 345ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>` para 346obtener más información. 347 348Otros tipos de errores de portabilidad se encuentran mejor compilando su 349código para otras arquitecturas. Si no tiene un sistema S/390 o una placa 350de desarrollo Blackfin a mano, aún puede realizar el paso de compilación. 351Un gran conjunto de compiladores cruzados para sistemas x86 se puede 352encontrar en 353 354 https://www.kernel.org/pub/tools/crosstool/ 355 356Muchos sistemas de compilación disponibles comercialmente también se pueden 357utilizar para compilar código de kernel para una amplia gama de 358arquitecturas. 359 360Los desarrolladores del kernel son afortunados: tienen acceso a una 361variedad de herramientas de verificación de código de la que los 362desarrolladores de la mayoría de los otros sistemas pueden estar celosos. 363Pero todas esas herramientas no servirán de nada si no las usa. El 364resultado final de ignorar estas herramientas es simple: alguien más puede 365notificarle de un problema en su código a través de un "oportuno" 366comentario en la lista de correo o, peor aún, el código problemático podría 367ser eliminado. Es mucho más fácil usar estas herramientas en primer lugar. 368 369Documentación 370************* 371 372La documentación a menudo ha sido más la excepción que la regla en el 373desarrollo del kernel. Aun así, una documentación adecuada ayudará a 374facilitar la integración de nuevo código en el kernel, hará la vida más 375fácil a otros desarrolladores, y será útil para sus usuarios. En muchos 376casos, la inclusión de documentación se ha vuelto esencialmente 377obligatoria. 378 379La primera pieza de documentación para cualquier parche es su changelog 380asociado. Las entradas de registro deben describir el problema que se está 381esolviendo, la forma de la solución, las personas que trabajaron en el 382parche, cualquier efecto relevante en el rendimiento, y cualquier otra cosa 383que pueda ser necesaria para entender el parche. Asegúrese de que el 384changelog diga *por qué* el parche vale la pena ser aplicado; un 385sorprendente número de desarrolladores no proporciona esa información. 386 387Cualquier código que agregue una nueva interfaz para el espacio de usuario, 388incluidos los nuevos archivos de sysfs o /proc, debe incluir documentación 389de esa interfaz que permita a los desarrolladores del espacio de usuario 390saber con qué están trabajando. Consulte `Documentation/ABI/README` para 391una descripción de cómo debe formatearse esta documentación y qué 392información debe proporcionarse. 393 394El archivo 395:ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>` 396describe todos los parámetros de arranque del kernel. Cualquier parche que 397agregue nuevos parámetros debe agregar las entradas correspondientes a este 398archivo. 399 400Cualquier nueva opción de configuración debe ir acompañada de un texto de 401ayuda que explique claramente las opciones y cuándo el usuario podría 402querer seleccionarlas. 403 404La información de la API interna para muchos subsistemas está documentada 405mediante comentarios especialmente formateados; estos comentarios pueden 406extraerse y formatearse de diversas maneras mediante el script 407"kernel-doc". Si está trabajando dentro de un subsistema que tiene 408comentarios de kerneldoc, debe mantenerlos y agregarlos según corresponda 409para las funciones disponibles externamente. Incluso en áreas que no han 410sido tan documentadas, no hay ningún inconveniente en agregar comentarios 411de kerneldoc para el futuro; de hecho, esta puede ser una actividad útil 412para desarrolladores de kernel principiantes. El formato de estos 413comentarios, junto con alguna información sobre cómo crear plantillas de 414kerneldoc, se puede encontrar en 415:ref:`Documentation/doc-guide/ <doc_guide>`. 416 417Cualquiera que lea una cantidad significativa de código existente del 418kernel notará que, a menudo, los comentarios son notables por su ausencia. 419Una vez más, las expectativas para el nuevo código son más altas que en el 420pasado; integrar código sin comentarios será más difícil. Dicho esto, hay 421poco deseo de tener código excesivamente comentado. El código en sí debe 422ser legible, con comentarios que expliquen los aspectos más sutiles. 423 424Ciertas cosas siempre deben comentarse. El uso de barreras de memoria debe 425ir acompañado de una línea que explique por qué la barrera es necesaria. 426Las reglas de bloqueo para las estructuras de datos generalmente necesitan 427explicarse en algún lugar. Las estructuras de datos importantes en general 428necesitan documentación completa. Las dependencias no obvias entre 429fragmentos de código separados deben señalarse. Cualquier cosa que pueda 430tentar a un maintainer de código a hacer una "limpieza" incorrecta necesita 431un comentario que explique por qué se hace de esa manera. Y así 432sucesivamente. 433 434Cambios en la API interna 435************************* 436 437La interfaz binaria proporcionada por el kernel al espacio de usuario no se 438puede romper, excepto en las circunstancias más graves. Las interfaces de 439programación internas del kernel, en cambio, son altamente fluidas y pueden 440cambiarse cuando surge la necesidad. Si usted se encuentra teniendo que 441hacer un rodeo alrededor de una API del kernel, o simplemente no utilizando 442una funcionalidad específica porque no cumple con sus necesidades, eso 443puede ser una señal de que la API necesita cambiar. Como desarrollador del 444kernel, usted está autorizado a hacer esos cambios. 445 446Hay, por supuesto, algunas condiciones. Los cambios en la API se pueden 447hacer, pero necesitan estar bien justificados. Entonces, cualquier parche 448que realice un cambio en la API interna debe ir acompañado de una 449descripción de cuál es el cambio y por qué es necesario. Este tipo de 450cambio también debe desglosarse en un parche separado, en lugar de estar 451enterrado dentro de un parche más grande. 452 453La otra condición es que un desarrollador que cambia una API interna 454generalmente está encargado de la tarea de corregir cualquier código dentro 455del árbol del kernel que se vea afectado por el cambio. Para una función 456ampliamente utilizada, este deber puede llevar a literalmente cientos o 457miles de cambios, muchos de los cuales probablemente entren en conflicto 458con el trabajo que otros desarrolladores están realizando. No hace falta 459decir que esto puede ser un trabajo grande, por lo que es mejor asegurarse 460de que la justificación sea sólida. Tenga en cuenta que la herramienta 461Coccinelle puede ayudar con los cambios de API a gran escala. 462 463Cuando se realice un cambio incompatible en la API, siempre que sea 464posible, se debe asegurar que el código que no ha sido actualizado sea 465detectado por el compilador. Esto le ayudará a estar seguro de que ha 466encontrado todos los usos en el árbol de esa interfaz. También alertará a 467los desarrolladores de código fuera del árbol de que hay un cambio al que 468necesitan responder. Apoyar el código fuera del árbol no es algo de lo que 469los desarrolladores del kernel deban preocuparse, pero tampoco tenemos que 470dificultarles la vida más de lo necesario. 471