Lo siento mucho si esto suena un poco tonto. Acabo de terminar de leer K&R y trabajé en algunos de los ejercicios. Este verano, para mi proyecto, estoy pensando en volver a implementar una utilidad de Linux para expandir aún más mi comprensión de C, así que descargué el código fuente de GNU tar y sed, ya que ambos parecen interesantes. Sin embargo, tengo problemas para entender dónde comienza, dónde está la implementación principal, de dónde provienen todas las macros extrañas, etc.
Tengo mucho tiempo, así que eso no es realmente un problema. ¿Se supone que primero debo familiarizarme con la cadena de herramientas GNU (es decir, make, binutils, ..) para comprender los programas? ¿O tal vez debería comenzar con algo un poco más pequeño (si existe tal cosa)?
Tengo poca experiencia con Java, C++ y python si eso importa.
¡Gracias!
Los programas GNU son grandes y complicados. La talla de GNU Hola Mundo muestra que incluso el proyecto GNU más simple necesita mucho código y configuración a su alrededor.
Las herramientas automáticas son difíciles de entender para un principiante, pero no es necesario que las entienda para leer el código. Incluso si modifica el código, la mayoría de las veces simplemente puede ejecutar make para compilar sus cambios.
Para leer código, necesita un buen editor (VIM, Emacs) o IDE (Eclipse) y algunas herramientas para navegar por la fuente. El proyecto tar contiene un directorio src, que es un buen lugar para comenzar. Un programa siempre comienza con la función principal, así que
grep main *.c
o use su IDE para buscar esta función. Está en tar.c. Ahora, omita todas las cosas de inicialización, hasta que
/* Main command execution. */
Allí, verá un interruptor para los subcomandos. Si pasa -x hace esto, si pasa -c hace eso, etc. Esta es la estructura de bifurcación para esos comandos. Si quieres saber cuáles son estas macros, ejecuta
grep EXTRACT_SUBCOMMAND *.h
allí se puede ver que están listados en común.h.
Debajo de EXTRACT_SUBCOMMAND ves algo divertido:
read_and (extract_archive);
La definición de read_and() (nuevamente obtenida con grep):
read_and (void (*do_something) (void))
El único parámetro es un puntero de función como una devolución de llamada, entonces read_and supuestamente leerá algo y luego llamará a la función extract_archive
. Nuevamente, haz grep y verás esto:
if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
{
if (fun && (*fun) (current_stat_info.file_name, typeflag)
&& backup_option)
undo_last_backup ();
}
else
skip_member ();
Tenga en cuenta que el verdadero trabajo ocurre cuando se llama fun
. fun
es nuevamente un puntero de función, que se establece en prepare_to_extract. fun
puede apuntar a extract_file
que hace la escritura real.
Espero haberte guiado mucho a través de esto y haberte mostrado cómo navego a través del código fuente. No dude en ponerse en contacto conmigo si tiene preguntas relacionadas.
-
+1 para un ejemplo detallado. Por cierto, este también es un ejemplo de cómo las cosas simples pueden complicarse. Por alguna razón, algunas personas piensan que es divertido :-/
– PauliL
16 de junio de 2010 a las 7:53
El problema con programas como tar
y sed
es doble (¡esta es solo mi opinión, por supuesto!). En primer lugar, ambos son realmente viejo. Eso significa que varias personas los han mantenido a lo largo de los años, con diferentes estilos de codificación y diferentes personalidades. Para las utilidades de GNU, por lo general es bastante bueno, porque generalmente aplican un estilo de codificación razonablemente consistente, pero sigue siendo un problema. El otro problema es que son increíblemente portátil. Por lo general, la “portabilidad” se ve como algo bueno, pero cuando se lleva a los extremos, significa que su base de código termina llena de pequeños trucos para solucionar errores oscuros y casos de esquina en piezas particulares de hardware y sistemas. Y para programas tan ampliamente portados como tar
y sed
eso significa que hay un lote de casos de esquina y hardware/compiladores/OS oscuros a tener en cuenta.
Si desea aprender C, diría que el mejor lugar para comenzar es no tratar de estudiar el código que otros han escrito. Más bien, trata de escribir código usted mismo. Si realmente desea comenzar con un código base existente, elija uno que se mantenga activamente donde pueda ver los cambios que otras personas están haciendo. como los hacensiga las discusiones en las listas de correo, etc.
Con programas bien establecidos como tar
y sed
ves el resultado de las discusiones que habrían tenido lugar, pero no puede ver cómo se toman las decisiones y los cambios de diseño de software en tiempo real. Eso solo puede suceder con software mantenido activamente.
Esa es solo mi opinión, por supuesto, y puedes tomarla con pinzas si quieres 🙂
-
Estoy de acuerdo en que la mejor manera de aprender C es mediante la programación. Sin embargo, una vez que haya dominado la sintaxis y los matices del lenguaje, siempre ayuda caminar a través de un código bien escrito, lo que le dará una idea de nuevas formas en las que puede aplicar prácticamente la sintaxis/estructuras de datos del lenguaje.
– itisravi
16 de junio de 2010 a las 7:05
-
@itisravi: Sigo creyendo que es mejor aprender eso observando el desarrollo a medida que sucede, en lugar de después del hecho. Por ejemplo, si ve un fragmento de código y se pregunta “¿por qué lo hicieron así, por qué no lo hicieron de esta (otra) manera?” Si puede publicar un mensaje en una lista de correo y preguntar entonces vas a aprender mucho más que si simplemente aceptas lo que está escrito.
– Decano Harding
16 de junio de 2010 a las 7:25
¿Por qué no descargar el código fuente de coreutils (http://ftp.gnu.org/gnu/coreutils/) y echa un vistazo a herramientas como yes
? Menos de 100 líneas de código C y una pieza de software GNU completamente funcional, útil y realmente básica.
GNU hola es probablemente el programa GNU más pequeño y simple y es fácil de entender.
Sé que a veces es complicado navegar por el código C, especialmente si no estás familiarizado con él. Te sugiero que uses un herramienta eso lo ayudará a navegar a través de las funciones, símbolos, macros, etc. Luego busque la función main().
Por supuesto, debe familiarizarse con las herramientas, pero no necesita convertirse en un experto.
-
+1 Estoy muy contento de que Source Navigator tenga una nueva versión. Lo usé en 2006 y parecía un proyecto inactivo. De todos modos, es una muy buena herramienta.
– EN S
16 de junio de 2010 a las 10:20
jeje
Aprende cómo usar grep si aún no lo conoces y utilízalo para buscar el principal función y todo lo demás que le interese. También es posible que desee utilizar herramientas de exploración de código como etiquetas o cscope que también puede integrarse con vim y emacs o usar un IDE si lo prefiere.
-
+1 Estoy muy contento de que Source Navigator tenga una nueva versión. Lo usé en 2006 y parecía un proyecto inactivo. De todos modos, es una muy buena herramienta.
– EN S
16 de junio de 2010 a las 10:20
EN S
sugiero usar etiquetas o cscope para navegar Puedes usarlos con empuje/emacs. Son ampliamente utilizados en el mundo del código abierto.
Deben estar en el repositorio de todas las principales distribuciones de Linux.