8 puntos por GN⁺ 2023-07-24 | 1 comentarios | Compartir por WhatsApp
  • Es la introducción a un proyecto personal de aprendizaje para entender hasta el final qué ocurre realmente cuando se ejecuta un programa en una computadora
  • La pregunta central lleva a si un programa se ejecuta directamente en la CPU, cómo funcionan las llamadas al sistema y cómo se ejecutan varios programas al mismo tiempo
  • Fuera de las clases universitarias, fue difícil encontrar materiales de sistemas completos, por lo que hubo que filtrar directamente materiales de distinta calidad e información contradictoria
  • Tras varias semanas de investigación y casi 40 páginas de notas, llegó a entender mejor el proceso que va desde el arranque de la computadora hasta la ejecución de un programa
  • Dice que incluso los lectores que sienten que ya saben del tema podrían aprender algo nuevo, y recomienda leer primero el capítulo 3 si no tienen tiempo

Punto de partida para entender la ejecución de programas

  • El punto de partida de este texto es qué ocurre exactamente cuando se ejecuta un programa en una computadora
  • Ya tenía cierto conocimiento de bajo nivel, pero le costaba conectar varias piezas en un solo flujo
  • La pregunta se ramifica en tres direcciones
    • Si un programa realmente se ejecuta directamente en la CPU
    • Qué es una llamada al sistema y cómo funciona en la práctica
    • Cómo se ejecutan varios programas al mismo tiempo

Proceso de investigación y orden de lectura

  • Como no hay muchos materiales completos sobre sistemas, tuvo que investigar varias fuentes por su cuenta, y la calidad y el contenido variaban según el material
  • Tras varias semanas de investigación y casi 40 páginas de notas, llegó a entender mejor cómo funciona una computadora desde el proceso de arranque hasta la ejecución de programas
  • El objetivo es crear por cuenta propia ese texto explicativo sólido que quería encontrar
  • A los lectores que sienten que ya conocen el contenido o que no tienen tiempo, les recomienda leer primero el capítulo 3
  • El siguiente texto continúa con el capítulo 1: The “Basics”

1 comentarios

 
GN⁺ 2023-07-24
Opiniones de Hacker News
  • Soy la persona que hizo esto. Gracias por leerlo y por señalar varias correcciones, muy al estilo de Hacker News. Putting the "You" in CPU todavía está en pleno desarrollo; originalmente pensaba pulirlo más, agregar contenido y publicarlo en HN más o menos la próxima semana.
    Tengo 17 años y hace un año dejé la secundaria para empezar a trabajar de tiempo completo en Hack Club(https://hackclub.com/). He programado desde que tengo memoria y, hace unos 6 años, empecé educación en casa para concentrarme más en la programación y otros intereses.
    Todo lo aprendí por mi cuenta, así que nunca tomé una clase universitaria de sistemas, y no me gustaba mi propia respuesta a “qué pasa cuando ejecutas algo”. Por eso le dediqué muchísimo tiempo a aprenderlo con la mayor profundidad posible y, en el proceso, descubrí que los sistemas operativos y el hardware son realmente divertidos de aprender, pero que los recursos en línea sobre el tema muchas veces son pésimos.
    Al investigar, a menudo terminaba en PDFs de diapositivas de clases de 2014 o en respuestas de StackOverflow que en realidad estaban equivocadas o simplificaban demasiado. Así que escribí Putting the "You" in CPU con la esperanza de que fuera un mejor recurso para quienes quieran aprender esta área por su cuenta. Todavía no está perfecto, porque me faltan escribir algunos párrafos más sobre SMP, pero creo que es mucho mejor que la mayoría de los recursos que he visto. También fue la primera vez que hice dibujos y diagramas; mejoraron conforme avanzaban los capítulos, y estoy bastante orgulloso de algunas ilustraciones de la parte final.
    Todo está publicado como open source en GitHub: https://github.com/hackclub/putting-the-you-in-cpu

    • Últimamente yo también pienso seguido que “estos recursos en línea son demasiado malos”. Me pasa especialmente cuando busco cosas como diagramas de bloques detallados del kernel de Linux, cómo funcionan las tablas de páginas, comparaciones entre ABIs de llamadas a funciones según la plataforma, detalles de protocolos de red de bajo nivel o números PID reservados de Linux.
      A veces encuentro respuestas en hilos de Reddit, pero normalmente vienen con mucho ruido, y también dudo de que Reddit sea un lugar confiable para almacenar conocimiento. StackOverflow ayuda especialmente poco porque está centrado en preguntas para resolver tareas concretas, así que las respuestas inevitablemente son breves.
      Para conocimiento general, ahora me salto la búsqueda rota de Google y voy directo a Wikipedia, pero Wikipedia también tiene límites sobre hasta qué profundidad cubre temas técnicos. Siento que hace falta una wiki que reúna de forma integral los detalles de la estructura interna de las computadoras. Hay mucho material disperso, pero sería buenísimo tenerlo en un solo lugar.
    • Yo tenía preguntas parecidas más o menos a esa edad, y encontré muchas respuestas interesantes en el código fuente de Linux. Claro que en ese entonces era mucho más simple. En particular, la comunidad osdev y la documentación de arquitectura de sistemas de Intel fueron un gran disparador; si mal no recuerdo, las partes 3a o 3b tenían mucha sustancia.
      Esa documentación te enseña mucho más sobre cómo podría ser el mundo que sobre cómo es ahora. Al hacer OSDEV aprendes muchas cosas curiosas, como la forma en que los procesadores de 32 bits usaban PAE para direccionamiento de 36 bits, o cómo los procesadores de 64 bits usaban direccionamiento de 52 bits para sacarte más dinero.
      También entiendes por qué una computadora tiene que hacer acrobacias de ensamblador a nivel de sistema para pasar de arrancar en modo de 16 bits hasta long mode, o por qué sigue existiendo el modo de 8 bits. Si te gustó aprender sobre la carga de binarios, todavía hay muchas cosas que te pueden sorprender. Por ejemplo, la segmentación de memoria sigue existiendo incluso en modo de 64 bits, pero en long mode se fuerza a un mapeo plano.
    • Excelente trabajo. Es un buen material para iniciarse en el desarrollo de sistemas operativos; tiene muchos detalles, pero es fácil de digerir. Conviene ajustar un poco la parte final de la nota #2 del capítulo 2. Debería reflejar que el paradigma asíncrono de algunos lenguajes de programación es multitarea cooperativa. Dentro de un proceso, usar multitarea cooperativa suele considerarse seguro, pero otra cosa es si resulta deseable. Tengo entendido que Erlang mantiene la planificación preventiva por robustez.
  • Me encantan este tipo de recursos. Últimamente me estoy metiendo en el mundo de RISC-V, y parece claro que quienes quieran impulsar el software libre y de código abierto van a necesitar este conocimiento para lograr que el software funcione bien en las nuevas computadoras de placa única que están apareciendo.

    • Como referencia, la codificación de instrucciones de RISC-V es bastante rara entre las cosas que uno puede explorar, quizá con la excepción de Thumb-2. Hubo buenas razones para diseñarla así, pero si piensas leer volcados hexadecimales, RISC-V no te lo va a poner fácil. Aunque desde la mayoría de los otros puntos de vista sea simple.
    • Si estudiaste una licenciatura o más, creo que en general un programador ya debería saber estas cosas. Al menos si no se saltó las clases de arquitectura de computadores y sistemas operativos.
      En mi caso, al aprender cómo funciona una computadora era común definir una arquitectura de conjunto de instrucciones, implementar un simulador y un ensamblador, y escribir ensamblador a mano. Los más entusiastas incluso la implementaban en FPGA o escribían un backend de LLVM.
      Con sistemas operativos pasa lo mismo. Aprender implementando un kernel propio o, como mínimo, modificando un kernel existente, es un proceso bastante común.
  • Si quieres saber más sobre cómo funciona una computadora a un nivel muy básico, recomiendo mucho el libro Code de Charles Petzold. Empieza desde primeros principios y llega hasta un nivel bastante alto.

    • Si prefieres aprender construyendo cosas por tu cuenta, Nandgame https://nandgame.com también es bueno.
  • Una de las cosas que este material hace bien es señalar las expectativas y los resultados reales del aprendizaje durante el proceso de reunir información. Algo como: “esperaba que fuera x por y, ¡pero en realidad era a por b!”.
    Deshacer malentendidos suele ser una etapa clave para formar nuevo conocimiento, y ayuda que quien escribe reconozca que la persona que lee debe procesar la información y superar sus propios malentendidos. Es mucho más amigable para el lector que una actitud de “esta es la respuesta correcta, y si pensabas otra cosa eres tonto”.

  • En el capítulo 6, la explicación del valor de retorno de fork() está mal. Al contrario de lo que dice, en el padre debería devolverse el PID del hijo, y en el hijo debería devolverse 0. Abrí un pull request para esta parte.

    • Muchísimas gracias, fue un error mío. Corregí el ejemplo de código y lo fusioné.
  • En la explicación de que add eax, 512 se traduce como 05 00 02 00 00, se dice que el primer byte 05 es el opcode que suma un número de 16 bits al registro EAX, y que los demás bytes son 512 (0x200) en little endian.
    Pero esa explicación solo cubre los primeros 3 bytes de una instrucción de 5 bytes. Me pregunto qué son los 00 restantes. Quizás querían decir que el opcode suma un número de 32 bits a EAX

    • No es “he”, sino “she”, y sí. Creo que en esa parte debería haber dicho 32 bits. Bien visto
    • Si hablamos de x86, es correcto. El registro eax tiene 32 bits de ancho, y los 16 bits inferiores del mismo registro se llaman ax
  • Buen artículo. Como desarrollador web autodidacta, siento que este tipo de material es muy valioso. Ayuda a salirse de varias abstracciones y a entender de forma más concreta cómo funcionan realmente las cosas

  • Parece un buen recurso, va bastante rápido al grano y además tiene algo de humor. No se siente tan “tutorial de mónadas” como esperaba. Pienso seguir leyéndolo

    • Me alegra que te haya gustado. Si tienes feedback más adelante, me encantaría saberlo
  • Buen material. Pero me queda una duda sobre el kernel. En [0] se explica que el shebang lo procesa el kernel y que, como lo toma de buf sin cargar el archivo completo, siempre queda truncado al largo de buf
    Hace 4 años, alguien se molestó porque el kernel truncaba rutas de más de 128 caracteres, así que duplicó el tamaño del búfer y duplicó el punto de truncamiento. Por eso, hoy en Linux, si una línea shebang supera los 256 caracteres, todo lo que viene después de los 256 desaparece por completo
    No entiendo por qué se truncaría silenciosamente la ruta de archivo de alguien. Y menos que lo haga el kernel. Una ruta de archivo de 256 bytes puede no tener mucho sentido, pero una cadena de ruta+argumentos de 256 bytes casi seguro aparecerá en algún momento. Romper scripts en silencio está mal
    [0]: https://cpu.land/how-to-run-a-program

    • Como autora, estoy muy de acuerdo. No debería hacer falta entender la lógica de ejecución del kernel para comprender las limitaciones del shebang. Es un diseño tonto, y quizá debí haber enfatizado más ese punto
      Hace algunos años, alguien intentó parchear el kernel para que, al menos, con shebangs demasiado largos fallara de forma clara en vez de hacerlo silenciosamente. Pero eso causó problemas en NixOS. Muy al estilo de Nix, ya usaban shebangs excesivamente largos con muchas rutas largas de nix-store. Antes se truncaban silenciosamente pero aun así funcionaban; de pronto todos esos scripts empezaron a fallar y se rompió la compatibilidad hacia atrás. Así que hubo que revertir el parche, y desde entonces no han aparecido cambios similares
      Para más detalles, ver https://lwn.net/Articles/779997/
    • No deberías poner argumentos complejos en un shebang. El shebang sirve para indicar la ubicación del intérprete del archivo actual
      Por sí solo, el shebang ni siquiera maneja bien más de un argumento. Si escribes #!/bin/program -args somescript, se divide como ['/bin/program','-args somescript'], que casi nunca es lo que querías. Esto es específico de Linux, y el shebang tampoco es universalmente portable en todos los Unix
      Si quieres hacer algo complejo, conviene dejar #!/bin/sh y hacer exec desde el archivo actual con los argumentos necesarios
      Un punto que falta en el enlace es que puedes usar env para encontrar el intérprete en la ruta actual. Por ejemplo, #!/usr/bin/env python3 encuentra el python3 que usa el usuario sin tener que saber su ubicación
      Esto puede ser útil para scripts que se ejecutarán en entornos virtuales, donde funciona sobrescribiendo el PATH del intérprete de Python. Pero no deberías hacerlo así para programas instalados. Un programa instalado no debería dejar que el usuario controle qué intérprete se va a usar; debería usar una ruta absoluta
      env tiene una opción -S que permite parsear la línea de comandos desde una sola cadena para lidiar con esta limitación. Aun así, desde la perspectiva de alguien que durante años ha evitado trucos en la línea shebang, como mínimo parece una práctica dudosa
    • Me sorprende más que el búfer no esté configurado igual que el tamaño de bloque del disco. Normalmente es de 512 bytes, pero no siempre