simple - Desarrollo del kernel y C++.
how to write an operating system (8)
El paradigma OOP favorece un modelo de memoria que es subóptimo cuando se trata de ejecución. Con la POO, los datos se diseñan para ser encapsulados dentro de las instancias del objeto. Para un rendimiento óptimo, necesita que los datos se distribuyan de acuerdo con las secuencias de procedimientos. Debido a esto, apoyarse en una implementación OOP resultará en un código menos eficiente, principalmente debido a la contaminación de la memoria caché, las fallas de la memoria caché y el acceso más frecuente a la memoria principal, que es lento. Y el bajo rendimiento es algo muy malo en el desarrollo del núcleo. Mucho sobre el modelo de datos.
Otro aspecto principal de la POO es el polimorfismo, que también conlleva penalizaciones de rendimiento: el acceso a los métodos virtuales no es directo sino que se determina durante el tiempo de ejecución, que es lento en sí mismo, pero aún más significativo es el hecho de que los métodos virtuales no pueden integrarse, por lo que las llamadas de funciones no pueden ser integradas. evitado
En resumen, optando por un diseño fuertemente orientado a la programación orientada a objetos, con profundas jerarquías polimórficas se explica una IDEA BAD ruidosa cuando se trata del desarrollo del núcleo o cualquier otro escenario de rendimiento intensivo.
Por supuesto, todo esto siempre que optes por un diseño fuertemente orientado a OOP, que es lo que separa a C ++ de C.
Sin embargo, dado que C ++ también implementa casi todas las funciones de C, no hay nada que le impida evitar los defectos de la POO y crear un diseño más orientado a los datos, que se puede implementar en C ++.
En mi opinión, la afirmación de que C ++ es mala para el desarrollo del kernel se debe a que para la mayoría de las personas, C ++ casi implica OOP, lo que es malo para los escenarios de rendimiento intensivo, pero C ++ NO es Java, no es OOP estrictamente forzado, es un lenguaje de propósito general. Dicho esto, la orientación de los datos es una cuestión de diseño, incluso podría implementarse en Java, pero el rendimiento de Java suele ser inferior al de C / C ++.
Por lo que know , aunque el sistema operativo común tiene partes escritas en otros idiomas, el núcleo está escrito completamente en C.
Quiero saber si es posible escribir un Kernel en C ++ y, de no ser así, cuáles serían los inconvenientes.
Esto está cubierto explícitamente en el Wiki OSDev .
Básicamente, debe implementar el soporte de tiempo de ejecución para ciertas cosas (como RTTI, excepciones), o abstenerse de usarlas (dejando solo un subconjunto de C ++ para ser usado).
Aparte de eso, C ++ es el lenguaje más complejo, por lo que necesitas tener desarrolladores un poco más competentes que no lo arruinen. Linus Torvalds odia que C ++ sea pura coincidencia, por supuesto.
Hay muchos ejemplos de sistemas operativos bien utilizados (o partes de ellos) implementados en C ++ - IOKit - el subsistema de controladores de dispositivo de MacOSX e IOS se implementa en EC++ . Luego está el eCOS RTOS, donde el núcleo se implementa en C ++, incluso haciendo uso de plantillas.
Los sistemas operativos tradicionalmente están inundados de ejemplos de conceptos OO implementados de la manera más difícil en C. En el modelo de dispositivo linux, kobject
es efectivamente la clase base para los objetos de controlador y dispositivo, completa con v-tables de bricolaje y algunos arreglos funky implementados en macros para arriba y castigados.
El kernel de Windows NT tiene una jerarquía de herencia aún más arraigada de los objetos del kernel. Y para todos los vecinos que se quejan de la idoneidad del manejo de excepciones en el código del kernel, se proporciona tal mecanismo.
Tradicionalmente, los argumentos en contra de usar C ++ en el código del kernel han sido:
- Portabilidad: disponibilidad de compiladores de C ++ para todas las plataformas de destino previstas. Esto ya no es realmente un problema
- Costo de los mecanismos del lenguaje C ++ como RTTI y excepciones. Claramente, si se usaran, la implementación estándar no es adecuada y es necesario usar una variante específica del kernel. Este es generalmente el controlador detrás del uso de EC ++
- Robustez de las API de C ++, y particularmente el problema de clase base Frágil
Sin lugar a dudas, el uso de las excepciones y el paradigma RAII mejoraría en gran medida la calidad del código del kernel: solo tiene que buscar el código fuente de BSD o Linux para ver la alternativa: enormes cantidades de código de manejo de errores implementado con goto
s.
La viabilidad de escribir un kernel en C ++ se puede establecer fácilmente: ya se ha hecho. EKA2 es el núcleo de Symbian OS, que se ha escrito en C ++.
Sin embargo, algunas restrictions al uso de ciertas funciones de C ++ se aplican en el entorno Symbian.
Para abordar las inquietudes de Torvalds y otras mencionadas en otra parte aquí: En los sistemas de hardware rígido escritos en C ++, no se utilizan excepciones STL / RTTI y se puede aplicar el mismo principio al kernel de Linux mucho más indulgente. Otras preocupaciones sobre el "modelo de memoria OOP" o la "sobrecarga de polimorfismo" básicamente muestran a los programadores que realmente nunca verificaron lo que sucede en el nivel de ensamblaje o en la estructura de la memoria. C ++ es igual de eficiente, y debido a que los compiladores optimizados son mucho más eficientes que un programador de C, escribe mal las tablas de búsqueda ya que no tiene funciones virtuales disponibles.
En las manos de un programador promedio, C ++ no agrega ningún código de ensamblaje adicional frente a una pieza de código escrita en C. Habiendo leído la traducción asm de la mayoría de las construcciones y mecanismos de C ++, diría que el compilador incluso tiene más espacio para optimizar vs C y, a veces, puede crear un código aún más simple. Por lo tanto, en cuanto al rendimiento, es bastante fácil usar C ++ tan eficientemente como C, mientras se sigue utilizando el poder de la POO en C ++.
Entonces, la respuesta es que no está relacionada con los hechos, y básicamente gira en torno a los prejuicios y no saber realmente qué código crea el CPP. Personalmente disfruto de C casi tanto como C ++ y no me importa, pero no hay racional contra el uso de un diseño orientado a objetos por encima de Linux, o en el propio Kernel, habría hecho a Linux mucho bien.
Puedes escribir un kernel de SO en más o menos el idioma que quieras.
Hay algunas razones para preferir C, sin embargo.
- ¡Es un lenguaje sencillo! Hay muy poca magia. Puede razonar sobre el código de máquina que el compilador generará a partir de su código fuente sin demasiada dificultad.
- Tiende a ser bastante rápido.
- No hay mucho tiempo de ejecución requerido; se requiere un esfuerzo mínimo para trasladar eso a un nuevo sistema.
- Hay muchos compiladores decentes disponibles que se enfocan en muchas arquitecturas de sistemas y CPU diferentes.
Por el contrario, C ++ es potencialmente un lenguaje muy complejo que implica una gran cantidad de magia para traducir su código OOP de alto nivel en código de máquina. Es más difícil razonar sobre el código de máquina generado, y cuando necesite comenzar a depurar su kernel de pánico o un controlador de dispositivo escamoso, las complejidades de sus abstracciones OOP empezarán a ser extremadamente irritantes ... especialmente si tiene que hacerlo a través del usuario hostil depurar los puertos en el sistema de destino.
Por cierto, Linus no es el único desarrollador de sistemas operativos que tiene opiniones sólidas sobre los lenguajes de programación de sistemas; Theo de Raadt, de OpenBSD, también ha realizado algunas citas sobre el tema.
Si bien hay algo "honesto" acerca de (ANSI) C, también hay algo "honesto", de una manera diferente, acerca de C ++.
El soporte sintáctico de C ++ para abstraer objetos es muy valioso, sin importar el espacio de la aplicación. Cuantas más herramientas estén disponibles para la mitigación de nombres inapropiados, mejores ... y las clases son tales herramientas.
Si alguna parte de un compilador de C ++ existente no funciona bien con realidades de nivel de kernel, entonces aclare una versión modificada del compilador que lo hace de la manera "correcta", y úselo.
En cuanto al calibre del programador y la calidad del código, se puede escribir código horrible o sublime en C o C ++. No creo que sea correcto discriminar a las personas que realmente pueden codificar OOP bien al no permitirlo en el nivel del kernel.
Dicho esto, e incluso como programador experimentado, echo de menos los viejos días de escribir en ensamblador. Me gustan ambos ... C ++ y ASM ... siempre que pueda usar Emacs y los depuradores de nivel de origen (:-).
Uno de los grandes beneficios de C es su legibilidad. Si tienes mucho código, que es más legible:
foo.do_something();
o:
my_class_do_something(&foo);
La versión C es explícita acerca de qué tipo foo es cada vez que se usa foo. En C ++ tienes montones de "magia" ambigua detrás de escena. Por lo tanto, la legibilidad es mucho peor si solo estás viendo un pequeño fragmento de código.