Summary Unavailable
This book is not suitable for a summary (it may be a textbook, workbook, cookbook, reference book, or collection). However, you can still explore the FAQs, about author, and other metadata below!
Ideas clave
1. El núcleo: el corazón de la programación de sistemas
El sistema operativo central: el núcleo.
El papel del núcleo. El núcleo es el corazón del sistema operativo; se encarga de gestionar los recursos de la computadora, como la CPU, la memoria y los dispositivos. Actúa como intermediario entre las aplicaciones y el hardware, proporcionando una interfaz coherente para que los programas realicen sus tareas. El núcleo es responsable de la planificación de procesos, la gestión de memoria, el acceso al sistema de archivos y la interacción con los dispositivos.
Modo usuario frente a modo núcleo. El núcleo opera en un modo privilegiado, lo que le permite acceder a todos los recursos de memoria y hardware. Los programas de usuario se ejecutan en un modo restringido, lo que les impide acceder directamente a la memoria del núcleo o realizar operaciones privilegiadas. Esta separación garantiza la estabilidad y la seguridad del sistema.
Llamadas al sistema. Los programas de usuario interactúan con el núcleo a través de llamadas al sistema, que son puntos de entrada controlados al propio núcleo. Estas llamadas permiten a los programas solicitar servicios al núcleo, tales como operaciones de E/S de archivos, creación de procesos y comunicación de red. La API de llamadas al sistema de Linux es el tema central de este libro.
2. E/S de archivos: la interfaz universal
Universalidad de la E/S.
Modelo de E/S universal. Los sistemas UNIX, incluido Linux, emplean un modelo de E/S universal, en el que se utilizan las mismas llamadas al sistema (open(), read(), write(), close(), etc.) para realizar operaciones de E/S en todo tipo de archivos, incluidos archivos regulares, dispositivos, tuberías y sockets. Esta abstracción simplifica la programación y fomenta la reutilización del código.
Descriptores de archivo. Los archivos abiertos se identifican mediante descriptores de archivo, que son números enteros pequeños. Un proceso hereda tres descriptores de archivo estándar: 0 (entrada estándar), 1 (salida estándar) y 2 (error estándar). Estos descriptores se pueden redireccionar a otros archivos o dispositivos.
Almacenamiento en búfer. Tanto el núcleo como la biblioteca stdio realizan un almacenamiento en búfer de la E/S de archivos para mejorar el rendimiento. El núcleo utiliza un búfer caché para almacenar datos en la memoria, reduciendo así el número de accesos al disco. La biblioteca stdio también utiliza búferes para reducir la cantidad de llamadas al sistema. Comprender el funcionamiento del almacenamiento en búfer es crucial para escribir programas eficientes y confiables.
3. Procesos: la base de la ejecución
Procesos y programas.
Procesos frente a programas. Un programa es un archivo que contiene instrucciones y datos, mientras que un proceso es una instancia de un programa en ejecución. El núcleo gestiona los procesos asignando recursos como el tiempo de CPU, la memoria y los descriptores de archivo. Cada proceso tiene un identificador de proceso único (PID) y un identificador de proceso padre (PPID).
Distribución de la memoria. La memoria virtual de un proceso se divide en segmentos: texto (instrucciones del programa), datos (variables globales inicializadas), heap o montículo (memoria asignada dinámicamente) y stack o pila (información de llamadas a funciones). El núcleo gestiona la memoria virtual, proporcionando a cada proceso su propio espacio de direcciones aislado.
Creación y finalización de procesos. Se crea un nuevo proceso utilizando fork(), que duplica el proceso padre. El proceso hijo puede entonces utilizar execve() para cargar y ejecutar un nuevo programa. Un proceso finaliza mediante _exit() o exit(), y su padre puede obtener su estado de finalización utilizando wait().
4. Gestión de memoria: el arte de la asignación
Asignación de memoria en el heap.
Asignación en el heap. Los procesos pueden asignar memoria dinámicamente en el heap utilizando funciones como malloc() y free(). El heap es una región de memoria que crece y se reduce a medida que se asigna y libera memoria. El núcleo gestiona el heap ajustando el límite del programa (program break).
Asignación en el stack. El stack es una región de memoria que se utiliza para almacenar variables locales e información sobre las llamadas a funciones. La función alloca() asigna memoria en el stack, pero esta memoria se libera automáticamente cuando la función retorna.
Mapeos de memoria. La llamada al sistema mmap() crea un mapeo de memoria, que puede utilizarse para mapear un archivo en memoria o para crear una región de memoria anónima. Los mapeos de memoria se pueden compartir entre procesos, lo que proporciona un método rápido de comunicación entre procesos (IPC).
5. Tiempo y planificación: controlando el flujo
El tiempo.
Conceptos de tiempo. Los sistemas UNIX utilizan el tiempo de calendario (segundos transcurridos desde la Época) y el tiempo de proceso (tiempo de CPU utilizado por un proceso). El núcleo mantiene un reloj de software que mide el tiempo en unidades llamadas jiffies.
Temporizadores. Las llamadas al sistema setitimer() y alarm() establecen temporizadores de intervalo que generan señales cuando expiran. Estos temporizadores se pueden utilizar para establecer tiempos de espera (timeouts) en operaciones bloqueantes.
Suspensión. Las funciones sleep() y nanosleep() suspenden la ejecución de un proceso durante un intervalo específico. La función POSIX clock_nanosleep() proporciona un método de suspensión más preciso, utilizando un reloj específico.
Planificación de procesos. El planificador del núcleo determina qué procesos tienen acceso a la CPU. Los procesos tienen un valor de prioridad (nice) que influye en su importancia. Las políticas de planificación en tiempo real (SCHED_RR y SCHED_FIFO) proporcionan un control más preciso sobre la planificación de los procesos.
6. Señales: comunicación asíncrona
Señales: conceptos fundamentales.
Mecanismo de señales. Las señales son una forma de notificación asíncrona a un proceso de que ha ocurrido un evento. Las señales pueden ser generadas por el núcleo (por ejemplo, por excepciones de hardware o entrada de terminal), por otro proceso o por el propio proceso.
Manejo de señales. Un proceso puede optar por ignorar una señal, aceptar su acción predeterminada (por ejemplo, la finalización) o establecer un manejador de señales, que es una función que se invoca cuando se entrega la señal.
Enmascaramiento de señales. Un proceso puede bloquear la entrega de ciertas señales añadiéndolas a su máscara de señales. Las señales bloqueadas permanecen pendientes hasta que se desbloquean. Las señales no se acumulan en una cola; si una misma señal se genera varias veces mientras está bloqueada, se entrega una sola vez.
APIs de señales. La función signal() es la API más antigua para establecer manejadores de señales, pero no es portable. La función sigaction() es el método preferido para establecer manejadores de señales, ya que proporciona un mayor control y es más portable.
7. Hilos: ejecución concurrente
Hilos: introducción.
Hilos frente a procesos. Los hilos son un mecanismo para la ejecución concurrente dentro de un mismo proceso. Los hilos comparten la misma memoria virtual, los descriptores de archivo y las disposiciones de señales, pero cada hilo tiene su propio stack e identificador de hilo.
API Pthreads. La API Pthreads proporciona un conjunto estándar de funciones para crear, finalizar y sincronizar hilos. La función pthread_create() crea un nuevo hilo y pthread_exit() finaliza un hilo. La función pthread_join() espera a que un hilo finalice.
Sincronización de hilos. Los hilos utilizan mutexes y variables de condición para sincronizar el acceso a los recursos compartidos. Los mutexes proporcionan acceso exclusivo a una variable compartida, mientras que las variables de condición permiten que los hilos esperen a que se produzcan cambios en el estado de una variable compartida.
Seguridad para hilos (Thread Safety). Las funciones seguras para hilos se pueden llamar de forma segura desde múltiples hilos al mismo tiempo. Deben evitarse las funciones que no sean seguras para hilos en programas multihilo. Los datos específicos de hilo y el almacenamiento local de hilo proporcionan mecanismos para hacer que las funciones que no son seguras para hilos lo sean, sin necesidad de modificar sus interfaces.
8. Comunicación entre procesos: compartir datos y sincronización
Descripción general de la comunicación entre procesos.
Mecanismos de IPC. Los sistemas UNIX proporcionan una variedad de mecanismos para la comunicación entre procesos (IPC), que incluyen tuberías, FIFOs, colas de mensajes, semáforos, memoria compartida y sockets. Estos mecanismos se pueden utilizar para intercambiar datos y sincronizar las acciones de los procesos.
Transferencia de datos frente a memoria compartida. Los mecanismos de transferencia de datos (tuberías, FIFOs, colas de mensajes, sockets) implican copiar datos entre procesos, mientras que la memoria compartida permite a los procesos acceder directamente a la misma región de memoria. La memoria compartida es más rápida, pero requiere una sincronización explícita.
IPC de System V frente a POSIX. Los mecanismos de IPC de System V (colas de mensajes, semáforos, memoria compartida) son más antiguos y están más ampliamente disponibles, pero sus APIs son más complejas y menos coherentes con el modelo de E/S tradicional de UNIX. Los mecanismos de IPC de POSIX proporcionan una API más simple y coherente, pero no están disponibles en todas las implementaciones de UNIX.
9. Sockets: conectando a través de redes
Sockets: introducción.
Sockets como IPC. Sockets es un mecanismo de IPC muy versátil que se puede utilizar para la comunicación entre procesos en el mismo host (sockets de dominio UNIX) o entre procesos en diferentes hosts conectados a través de una red (sockets de dominio de Internet).
Tipos de sockets. Los sockets se dividen en dos tipos principales: sockets de flujo (SOCK_STREAM), que proporcionan un canal de comunicación de flujo de bytes bidireccional y confiable, y sockets de datagramas (SOCK_DGRAM), que proporcionan una comunicación orientada a mensajes, no confiable y sin conexión.
Operaciones con sockets. Las llamadas al sistema clave para sockets son socket() (crear un socket), bind() (asociar un socket a una dirección), listen() (marcar un socket de flujo como pasivo), accept() (aceptar una conexión en un socket de flujo de escucha) y connect() (conectarse a un socket par).
Sockets de dominio de Internet. Los sockets de dominio de Internet utilizan direcciones IP y números de puerto para identificar los puntos finales de la comunicación. Las funciones getaddrinfo() y getnameinfo() se utilizan para realizar la conversión entre nombres de host y de servicio y sus representaciones numéricas correspondientes.
10. Terminales y pseudoterminales: interactuando con el usuario
Terminales.
Atributos de la terminal. Las terminales tienen una serie de atributos que controlan su funcionamiento, incluyendo caracteres especiales, banderas y modos de E/S. Estos atributos se pueden recuperar y modificar utilizando las funciones tcgetattr() y tcsetattr().
Modos de E/S de la terminal. Las terminales pueden operar en modo canónico (entrada línea a línea) o en modo no canónico (entrada carácter a carácter). El modo de E/S de la terminal se controla mediante las banderas de la terminal.
Pseudoterminales. Las pseudoterminales (ptys) son un par de dispositivos virtuales conectados: un maestro y un esclavo. El dispositivo esclavo proporciona una interfaz que se comporta como una terminal, mientras que el dispositivo maestro proporciona un medio para controlar al esclavo. Las pseudoterminales se utilizan en una variedad de aplicaciones, incluyendo ventanas de terminal y servicios de inicio de sesión de red.
Control de terminales. La llamada al sistema ioctl() se utiliza para realizar una serie de operaciones de control en las terminales, incluyendo la configuración de los atributos de la terminal, el control de la línea de la terminal y la obtención del tamaño de la ventana de la terminal.
11. Seguridad y capacidades: protegiendo el sistema
Escritura de programas privilegiados seguros.
Programas privilegiados. Los programas privilegiados tienen acceso a recursos del sistema que no están disponibles para los usuarios comunes. Dichos programas deben escribirse con sumo cuidado para evitar vulnerabilidades de seguridad.
Mínimo privilegio. Los programas privilegiados deben operar con el mínimo privilegio requerido para realizar sus tareas. Esto significa liberar privilegios cuando no se necesitan y liberarlos de forma permanente cuando ya no se requieran en absoluto.
Validación de entradas. Los programas privilegiados deben validar cuidadosamente todas las entradas provenientes de fuentes no confiables, incluidos los argumentos de la línea de comandos, las variables de entorno y los datos de archivos y conexiones de red.
Capacidades. El esquema de capacidades de Linux divide el tradicional privilegio absoluto del superusuario en unidades distintas llamadas capacidades. Esto permite otorgar a un proceso únicamente los privilegios que requiere, reduciendo así la posibilidad de daños en caso de que el programa se vea comprometido.
12. Bibliotecas compartidas: reutilización de código y eficiencia
Fundamentos de las bibliotecas compartidas.
Bibliotecas de objetos. Las bibliotecas de objetos son archivos que contienen código de objeto compilado para un conjunto de funciones. Las bibliotecas estáticas se enlazan en un ejecutable en el momento de la compilación, mientras que las bibliotecas compartidas se cargan en tiempo de ejecución.
Bibliotecas compartidas. Las bibliotecas compartidas permiten que múltiples procesos compartan la misma copia del código de la biblioteca en la memoria, ahorrando así espacio en disco y memoria RAM. Las bibliotecas compartidas también permiten aplicar actualizaciones de la biblioteca sin necesidad de volver a enlazar los programas.
Código independiente de la posición. Las bibliotecas compartidas deben compilarse utilizando código independiente de la posición (PIC), lo que permite que el código de la biblioteca se cargue en cualquier dirección de memoria.
Enlace dinámico. El enlazador dinámico es responsable de cargar las bibliotecas compartidas en tiempo de ejecución y de resolver las referencias a símbolos. La variable de entorno LD_LIBRARY_PATH se puede utilizar para especificar directorios adicionales en los que el enlazador dinámico debe buscar bibliotecas compartidas.
Visibilidad de símbolos. Las bibliotecas compartidas deben exportar únicamente aquellos símbolos que formen parte de su API pública. Se pueden utilizar scripts de versión para controlar la visibilidad de los símbolos y para crear símbolos con versión.
Characters
Plot Devices
Analysis
Última actualización:
Report IssueResumen de reseñas
The Linux Programming Interface recibe críticas abrumadoramente positivas; los lectores elogian su cobertura exhaustiva de la programación de sistemas Linux. Muchos lo describen como una referencia definitiva, destacando sus explicaciones claras, ejemplos prácticos y contexto histórico. Los lectores aprecian la profundidad del libro, su organización y su legibilidad, a pesar de su considerable extensión. Se le alaba por tender un puente entre los conceptos teóricos y las aplicaciones prácticas, lo que lo hace valioso tanto para el aprendizaje como para la consulta. Muchos reseñantes dedicaron un tiempo considerable al libro, considerándolo de gran utilidad para comprender el funcionamiento interno de Linux y las llamadas al sistema.
También leyeron
Preguntas frecuentes
What's The Linux Programming Interface about?
- Comprehensive Guide: The Linux Programming Interface by Michael Kerrisk is a detailed handbook on Linux and UNIX system programming, covering system calls, library functions, and the programming interface used by nearly every application on these systems.
- Focus on Standards: The book emphasizes UNIX standards (POSIX.1-2001/SUSv3 and POSIX.1-2008/SUSv4), making it valuable for programmers working on various UNIX platforms.
- Practical Examples: It includes over 200 example programs, 88 tables, and 115 diagrams to illustrate concepts, making it easier for readers to grasp complex topics.
Why should I read The Linux Programming Interface?
- Authoritative Resource: Written by Michael Kerrisk, a recognized expert in Linux programming, this book is considered the definitive guide in the field. It is praised for its clarity and depth.
- Skill Development: The book is designed for programmers and software designers looking to build applications for Linux or other UNIX systems, enhancing their system programming skills.
- Comprehensive Coverage: It covers a wide range of topics, from basic file I/O to advanced features like multithreading and interprocess communication, making it suitable for both beginners and experienced developers.
What are the key takeaways of The Linux Programming Interface?
- Understanding System Calls: Readers will learn how to effectively use system calls and library functions, which are crucial for interacting with the Linux kernel.
- File I/O Model: The book introduces the universal I/O model, explaining how the same system calls are used for all types of files, including devices and sockets.
- Error Handling: It emphasizes the importance of checking return values from system calls and library functions, teaching readers how to handle errors effectively.
What are the best quotes from The Linux Programming Interface and what do they mean?
- Comprehensive Coverage: “The Linux Programming Interface is the most comprehensive single-volume work on the Linux and UNIX programming interface.” This highlights the book's extensive coverage and authority in the field.
- Depth of Content: “You’ll find descriptions of over 500 system calls and library functions.” This emphasizes the book's depth, indicating a thorough exploration of the programming interface.
- Transferable Knowledge: “The emphasis on UNIX standards makes it equally valuable to programmers working on other UNIX platforms.” This suggests that the knowledge gained is applicable across different UNIX systems.
How does The Linux Programming Interface explain system calls?
- Definition of System Calls: System calls are controlled entry points into the kernel that allow processes to request services, such as file operations or process management.
- Kernel Interaction: They enable user programs to interact with the kernel, which manages system resources and enforces security and access controls.
- Performance Overhead: Understanding the overhead associated with system calls is crucial for writing efficient programs, as they involve switching from user mode to kernel mode.
What is the universal I/O model discussed in The Linux Programming Interface?
- Unified System Calls: The universal I/O model states that the same system calls (open(), read(), write(), close()) are used for all types of files, including regular files, pipes, and sockets.
- Simplified Programming: This model simplifies the programming model, allowing developers to write code that works across different file types without needing to handle each type differently.
- Practical Examples: The book provides examples that illustrate how to use these system calls effectively, reinforcing the concept of universality in file I/O.
How does The Linux Programming Interface address error handling?
- Importance of Error Checking: The book stresses that every system call and library function should have its return value checked to ensure successful execution.
- Using errno: It explains how to use the global variable
errnoto diagnose errors, providing functions likeperror()andstrerror()for user-friendly error messages. - Example Implementation: The book includes practical examples demonstrating how to handle errors effectively, which is essential for robust programming.
What are the differences between static and shared libraries as explained in The Linux Programming Interface?
- Static Libraries: These are archives of object code that are linked into an executable at compile time, resulting in larger binaries and requiring recompilation for updates.
- Shared Libraries: These are linked at runtime, allowing multiple programs to share a single copy of the library in memory, which saves space and simplifies updates.
- Advantages of Shared Libraries: The book discusses how shared libraries facilitate easier updates and reduce memory usage, making them preferable in many scenarios.
How does The Linux Programming Interface explain process management?
- Definition of a Process: A process is defined as an instance of an executing program, with its own memory space and resources managed by the kernel.
- Process Creation: The book details how processes are created using the fork() system call, which duplicates the parent process, and how they can execute new programs using execve().
- Process Management: It covers how the kernel manages processes, including scheduling, resource allocation, and termination, providing a comprehensive understanding of process behavior.
What is the significance of the /proc file system in The Linux Programming Interface?
- Virtual File System: The /proc file system is a virtual file system that provides an interface to kernel data structures, allowing users to view and modify system attributes.
- Process Information: It contains directories for each running process, providing insights into process states and resource usage, which is invaluable for debugging and monitoring.
- Kernel Interaction: The book explains how to interact with /proc files to gather system information, making it a practical tool for system programmers.
How does The Linux Programming Interface explain interprocess communication (IPC)?
- Diverse IPC Methods: The book covers various IPC methods, including pipes, message queues, and shared memory. Each method is explained with examples, allowing readers to understand their use cases and implementation.
- Synchronization Techniques: It also discusses synchronization mechanisms, such as semaphores and mutexes, which are crucial for coordinating access to shared resources.
- Practical Examples: The author provides practical examples of IPC in action, demonstrating how to implement these techniques in real-world applications.
What are the threading concepts discussed in The Linux Programming Interface?
- POSIX Threads: The book provides a comprehensive overview of POSIX threads, including thread creation, termination, and synchronization. This is essential for developing multithreaded applications in Linux.
- Thread Safety: It emphasizes the importance of writing thread-safe code, discussing techniques to manage shared resources and avoid race conditions.
- Cancellation and Cleanup: The book covers thread cancellation and the use of cleanup handlers, which are important for managing resources in multithreaded programs.
Sobre el autor
Michael Kerrisk es el autor de "The Linux Programming Interface" y ha sido el mantenedor del proyecto Linux man-pages desde 2004. Su amplia experiencia con los sistemas Linux es evidente en el carácter exhaustivo y autoritario del libro. El estilo de escritura de Kerrisk es elogiado por ser claro, conciso y bien organizado, lo que hace que los temas complejos sean accesibles para los lectores. Su dedicación al tema es aparente en la cobertura minuciosa del libro y en los años de trabajo que se dedicaron a su creación. El papel de Kerrisk en el mantenimiento de la documentación de Linux probablemente ha contribuido a su profundo conocimiento del sistema, el cual comparte eficazmente a través de su escritura.
Descargar PDF
Descargar EPUB
.epub digital book format is ideal for reading ebooks on phones, tablets, and e-readers.