My Journey with Linux

1. Hi, everyone! I am a programmer who has long been immersed in the Linux world and relies on Linux for a living. Living in a second-tier city with a poor IT environment, as you may know, programmers here are already quite rare, and Linux programmers are even more of a rare species! However, there is an old saying: “The rarer something is, the more valuable it becomes.” Surprisingly, although there are fewer Linux positions here, the salaries are still quite competitive overall. So, I found some time to summarize my Linux learning journey (otherwise, I would have been working overtime to earn a living, haha). However, recently, I have been feeling anxious about one thing. Although I have been living off Linux and have encountered many Linux technologies over the years (both those applicable to work and those I have self-studied out of personal interest), when I think about it, I realize that I don’t have many tangible works to show for my time with Linux. I haven’t documented my learning experiences in writing, and I haven’t established any technical influence in my field. As a technical person, thinking about these things makes me feel quite lost. Therefore, after much contemplation, in order to better learn Linux and to connect with more like-minded individuals, I decided to document my learning process in writing. If these words can bring some benefits to others, I would feel very honored. In fact, recording one’s learning and growth trajectory is a great learning method; these writings will become valuable assets in the future, so when I look back, I won’t regret or feel remorse for being unproductive. Now, let me share some of my experiences and insights.2. I remember the first time I encountered the Linux system was during my junior year in a course on Advanced Linux Programming. Unknowingly, I have been with Linux for nearly eight years now. I vaguely recall the confusion and helplessness I felt when I first started with Linux. Having been accustomed to the “friendly” user interface of Windows, I often found myself struggling with the command-line interface of Linux. Moreover, I remember trying out many different Linux desktop distributions, such as Ubuntu 9.10 (time flies; now it’s already 19.10), Debian, CentOS, SUSE, and so on. Some might wonder why I was so fickle and not loyal! Haha, the reasons are probably twofold: one is that the system kept crashing, so I had to reinstall it, and during the reinstallation, I wanted to try other versions to see if they were better, which was actually due to my lack of skills; the other reason was that I didn’t know how to install software, and for beginners, compiling and installing software on Linux was simply too painful. Back then, I often encountered situations where the system environment did not support certain applications, so I had to manually configure dependency libraries, install new environments, etc., but I didn’t know how (I believe this is also a barrier for many beginners entering Linux). Faced with the need to complete assignments or course designs, I could only keep trying different distributions and searching for solutions from predecessors. Sometimes, when I couldn’t find a solution, I had to give up! This was my painful self-enlightenment phase with Linux. Although this phase was quite painful, I persevered in my Linux learning with determination.Thinking back on it, I still feel a bit comforted.3. Later, I started working and ended my previous non-professional learning and development model. I began to engage in some real projects and truly started learning how to develop based on the Linux system. This was also a phase where my technical abilities grew rapidly. I remember that the first project I developed was a system for network data distribution, with the underlying framework based on ACE (at that time, ACE was the standard framework for network development on Linux). I was responsible for the design and implementation of the SNMP client. It was from that time that I began to understand how to write Linux network programs, how to use GDB to debug core files, and how to use various system calls in the Linux system. During that period, I bought the “Bible” of the UNIX world, “Advanced Programming in the UNIX Environment,” and began to study it. This book is very systematic and covers almost all aspects of UNIX-like system development. The author’s precise explanations of the technology are astonishing. In my work, I could almost find answers to most Linux system development issues within it, making it a great mentor for Linux developers. I believe that if you choose the field of Linux development, this book is a must-read, and it should be read repeatedly because many technical details cannot be understood in just one or two readings. Additionally, I found that this book has a magical quality: as my work experience increases, I gain new insights from it each time I read it. On one hand, this indicates that my understanding of technology is continuously improving; on the other hand, it shows that this book is not just a simple explanation of technical knowledge; the most important thing is that it has thought and soul, which is the fundamental reason why Linux can thrive. My work experience during that time made me understand what the Linux system is, what functions can be realized based on it, and how to implement my ideas based on it. I feel that after that, I had entered the door of Linux. Later, as I delved deeper into my work, I gradually began to understand the underlying working principles of Linux, such as what processes and threads are, how they work, how processes and threads communicate with each other, how Linux manages memory, how the TCP/IP protocol stack in Linux is designed and implemented, and so on.Although these topics are very hardcore and learning them is quite painful, the more I don’t understand, the more mysterious I find them, and the more I want to learn about them. Gradually, I began to enjoy this feeling. In fact, exploring unknown fields and ultimately being able to understand them brings endless satisfaction; it is a wonderful enjoyment.4. After that, due to a job change, I began to engage in embedded Linux development. Embedded Linux development requires a more comprehensive understanding of Linux technology, especially at a lower level, because you often need to solve the challenge of designing a system from scratch. For example, given a hardware platform, you need to build the entire system from scratch, including the BootLoader, Linux kernel, root filesystem, and system tools. This requires not only knowing how to develop applications based on the Linux platform but also understanding foundational knowledge such as compiler principles, Linux kernel porting, filesystem construction methods and principles, driver programming, Make build systems, shell scripting, and so on. During this phase, I gained an understanding of how Linux systems are applied and developed in embedded systems, further enhancing my understanding and cognition of basic computer principles. So, how can one quickly get started with embedded Linux? My method is to read more and learn from industry community practices, then apply the learned technologies to work in a timely manner to internalize my skills. There are many communities related to embedded Linux, such as the famous router firmware OpenWrt, the system build system buildroot, and the cross-toolchain publisher Linaro, etc. We can choose the areas we are interested in and actively participate in them. The community is filled with experts, and we can have close contact with them and learn many advanced technologies, which will greatly benefit our future technical career paths. Finally, let me share my views on learning the Linux kernel. Embedded Linux development will inevitably involve some aspects of the Linux kernel. However, often what we encounter are specific technical points, leading to a feeling of being lost in the forest without seeing the trees. At this point, my personal experience is to step out of fixed technical points and try to understand the “forest” where this point is located, that is, to understand the entire subsystem, focusing on understanding the position and role of the subsystem within the entire system, the framework of the subsystem, the abstract model, and then how to design and develop functional modules based on the model provided by the subsystem. For example, if a certain chip is based on I2C communication, we need to understand the framework and programming model of the I2C subsystem before implementing the design and development of the specific chip driver. Moreover, the design philosophies of various subsystems in the Linux kernel are interconnected; as long as you thoroughly understand a few systems, most other subsystems are similar, allowing you to draw parallels.5. Nowadays, Linux technology is ubiquitous in various fields. For instance, servers in data centers are almost all built on Linux systems, a significant portion of IoT devices are based on embedded Linux systems, and many key components in the currently booming AI field are also built on Linux. It can be said that Linux is everywhere; it has become the foundational core technology of the entire computer world, and I believe that Linux technology will shine brightly in the future. However, the learning path of Linux is quite steep, and it can be very painful at the beginning. So how can we avoid the dilemma of “starting and ending” in the learning journey of Linux? Based on my personal experience, here are some thoughts:

  • Do not aim too high; learning requires a down-to-earth approach. The technology in the Linux world is complex and diverse, with many particularly attractive technologies. Some people, at the beginning, rush into learning the Linux kernel to pursue these cutting-edge technologies. For example, current popular container technologies; before practicing container applications, they start learning the implementation principles of containers in the Linux kernel, diving headfirst into the vast sea of Linux kernel code. Such individuals often end up “drowning” in the ocean of the Linux kernel due to a lack of basic technical understanding. Therefore, for those just starting with Linux, it is essential to learn the most fundamental technologies in a down-to-earth manner. My suggestion is to first discard the habit of operating the computer with a mouse and force yourself to get used to the command-line operation mode of Linux. Start with the simplest commands to understand how the Linux system works and its operating principles. Here, I recommend “The Linux Command Line” by William Shotts; this book can be considered a bible for Linux beginners, providing detailed explanations of various command operations in Linux, serving as an encyclopedia of Linux commands. It can truly help you open the door to Linux. Another piece of advice is that when learning Linux commands, remember that you cannot just talk about theory; every command must be practiced on the machine. Only then can you intuitively and genuinely appreciate the efficiency and value of the commands. This is the first piece of advice.
  • Layered progression, step by step. After gaining some experience in operating the Linux system, you can try to undertake some development projects based on the Linux system. However, the development capabilities of the Linux system are incredibly strong, and there are so many things that can be done that newcomers may feel at a loss. Here, I have three suggestions: First, be guided by your work content, progressing from specific points to the broader picture, step by step. Second, systematically learn Linux environment programming; I recommend reading “Advanced Programming in the UNIX Environment”. Third, choose open-source projects based on Linux, analyze what Linux technologies they use and how they are applied, and then understand how a system is formed and what its framework looks like, etc. In fact, these three points are interrelated: first, the knowledge used in work is often fragmented, and the problems encountered mostly involve specific technical points, which do not form a system. Systematic learning of classic books related to Linux environment development can accelerate the process of turning technical points into a technical system, ultimately systematizing the technology. After that, analyzing and learning from excellent open-source projects can further deepen our overall understanding of the Linux system and enrich our application methods for Linux technology. After several detailed analyses of open-source projects, we can gradually master the essence of Linux system development. Finally, regarding the use of Linux system APIs, it is inevitable that various Linux system APIs will be involved during development, including system calls and glibc functions. How can we correctly use these APIs for development? My suggestion is that when you receive a function API, the first thing to do is to consult the man manual. Why? Because the authors of the man manual are usually the developers or maintainers of the API, and it provides detailed descriptions of the API’s functionality, basic principles, parameter analysis, and return values. More importantly, it will explain the precautions, usage limitations, and existing bugs of the API in detail, which can help you avoid most pitfalls and allow you to write robust programs from the start. Therefore, sticking to using the man manual is a good habit for mastering Linux and is the most effective shortcut for development and learning.
  • Technology knows no bounds; learning must reach new heights. After gaining considerable experience in Linux system development, we may become dissatisfied with merely using Linux for application development. So how can we elevate ourselves further in the Linux field? Actually, I am currently at this stage and do not have much authority to speak. I can only share some of my experiences for reference. I have two pieces of advice:The first: Identify pain points in your work based on your industry characteristics and then program solutions to those pain points. Or, to improve development efficiency, design and implement a development tool library or even a framework. For instance, in the past, when I received a new project, I always had to design and develop various basic tool libraries from scratch, such as logging systems, thread management models, thread synchronization models, string processing models, etc. This greatly reduced development efficiency and wasted development resources. Later, I organized various basic components used in different projects, refactored them, and ultimately integrated them into a foundational development library for applications. The benefits of doing this are (1) significantly improved development efficiency. (2) greatly enhanced system stability. Each use of the foundational library represents a transformation; bugs become fewer, leading to increased system stability.The second: Effectively learn the Linux kernel. I am also a novice in learning the Linux kernel. Although I have previously engaged in some kernel porting and driver development work, I always felt that those were merely application developments based on the Linux kernel, without truly learning the design essence of Linux from the perspective of the operating system. Therefore, I began my journey of learning the kernel. However, I do not recommend that kernel newcomers start by reading those hefty classic kernel books. It is not that their content is not good; on the contrary, they are excellently written, but they are not suitable for beginners. My understanding is that these classics often explain specific technical points very well, but they lack explanations of the overall framework of the kernel and the relationships between various subsystems. This can easily lead one to get lost in specific details without gaining an overall understanding of the system, ultimately expending a lot of energy without truly comprehending the kernel. My approach is to analyze a system without rushing to understand specific details; first, I outline the main processes of the system, identify the key points, and form an overall understanding of the system in my mind. Then, I delve into learning the specific implementation methods. With a general concept in mind, I won’t lose direction while learning. It’s like having a map in an unfamiliar place; no matter how you walk, you won’t easily get lost. Therefore, my method for learning the kernel is to first form a mental map of the kernel and then follow the map to tackle the challenges, ultimately understanding the entire kernel.6. Having said so much, these are some thoughts I have formed along my journey. However, due to my personal technical limitations, there are certainly many misunderstandings, and I hope everyone can be forgiving. I welcome like-minded individuals to come and exchange ideas. Finally, I want to say that technology knows no bounds, and there is no such thing as a universal method. As technical people, we must keep running and actively face changes to remain invincible.

Leave a Comment