 Hello, my name is Ian Webster. I'm an engineering consultant and a instructor for the Linux Foundation. Today we're going to do an excerpt from the LF-411 Embedded Linux course that covers a number of the different options that can be used to build an embedded Linux device without necessarily using an embedded distribution. Let's get started. We're going to talk about the root file system choices. Every embedded system has a root file system that is used to actually provide the functionality on top of the Linux kernel. The very, very first process that started when you enter into user space is called init, and there's a number of different options you can use for init. But init is always the ancestor of all other user space processes, and it always comes up as process ID 1. Now, you can pass in which process is going to be your init process, but if, however, you don't pass one in, it'll actually then try and start some well-known names that are on the root file system. You'll notice at the very end of the list, however, that if it can't find any other initialization process, it will start a root shell, so you can perhaps salvage a system if it's broken. So the big thing about the parent-child relationship when it comes to processes in user space is whenever a child terminates, it signals its parent process, and then the parent has an option to see why the child finished before its resources get reclaimed by the Linux kernel. That happens through having a signal handler that handles the child signal. Now, there are a number of different options when it comes to the initialization process, but we're only going to cover two of them. The first one is something called system5init, and it's something that comes from the old Unix days, and it's based on a file called slashetc slash init tab. It specifies all the configuration as to what happens in different situations. Now, for system5init, all the different systems are built into what's called a run level. Run level zero is halt, in other words, turning your computer off. Run level one is for single user mode. Run level two is for multi-user mode, and so on, up until you get to run level six, which is reboot. For each one of those run levels, there's a directory in the ETC directory called rc-sum-number.d. The .d means it's a directory. And within each one of those directories, there's a link that goes back to the real initialization script that's in the ETC init.d directory. All the links in the run level directory start with either a capital S or a capital K. Then two digits that's best are used for ordering, and then the rest of the name of the initialization link. As you enter a run level, all the S links are executed. As you leave a run level, all the K links are executed. And each script is passed in a parameter of either start or stop. Start signifies that a service needs to start. Stop, obviously, is for stopping a process. Every Linux distribution does things a little bit differently. On some of them, they use a utility called checkconfig in order to administer these links and build them for you. On other systems, they use a system called update-rc.d. It doesn't really matter. In both cases, they do the same thing. They just set up the appropriate link between the rc numbered.directory to the real script in ETC init.d. You'll find, for instance, however, when you look at the actual commands that do the actual halt, shutdown, or power off. For instance, in the case of halt, it's in slash sbin. It's actually a symbolic link back to the real implementation of it, which is slash sbin halt.sysv init. You'll find similar links for shutdown and for power off. The System 5 initialization system was originally designed for much larger enterprise-style computers, even though we still use it for embedded systems. But since it's considerably more complex, I can't cover all the features in this short little tutorial. If you want to learn more about how these things work, there's a number of websites which we list here in the slides as to where you can find out more information. The other option is using busyboxinit. It's a single binary that brings in all the different Unix actions from the command line into a single binary to make it smaller for an embedded system. One of the options, or one of the applets, as they're called, is the initialization process. And you can make it work by basically linking from slash sbin init to busybox itself. And the way that works is whatever the name of the application is when it starts up is what functionality it actually chooses to run internally. Now busybox also uses init tab itself, just like System 5 init, but it uses slightly different syntax. And we have an example of what one of those files looks like here in the slides. You'll see in this particular case that there are startup items that are listed. So instead of being separate scripts, they're actually listed in here as initialization systems. So here you'll see that we're mounting different partitions. We're setting the host name of the system and we bring up networking. At the very end you'll also see that we have the option of running a series of scripts at the very end in the RCS directory. The line's a little bit further along. Start different terminals on different virtual terminals or serial ports. Similar way is how you do it in System 5 init. A little bit further down, you can see that we're logging different kinds of things. And further down from that we specify what happens when you press control delete. In this case we do a reboot. And at the very end you'll see this shutdown things that we do when we want to power things off. So if you look at each one of those lines, the third field in each one of those lines is actually a different word. And that specifies what happens with that particular command, whether something gets restarted, whether it's an initialization command, whether it's a shutdown command and so on and so forth. And to find out more information you can look at the slides here to figure out what each one actually does. The next thing we're going to talk about is dynamic device file creation. Everything is a file in Unix and the same thing happens for device files for device drivers. Now there's a lot of different ways we handled it in the past but to talk about the modern way. When it comes to the dev directory it's usually now a temporary file system upon which we dynamically create device nodes. And that's done by a user space program called Udev, typically on most Linux systems. What Udev does is it listens to the kernel such that when a driver comes up the appropriate device file is made and any scripts that need to do anything more happen thereafter. Now Udev is an all singing, all dancing, do everything kind of system and again it was designed for servers and so on. It does work on embedded systems and it gives you the most functionality. However, since we're on memory constrained systems and so on and so forth, Busybox provides a cut down version of Udev called Mdev. Again it provides enough functionality in order for your embedded system to work well enough. You're going to find that we actually can look at how that is set up in the slides here. We go into a lot more detail in the actual course itself. In order to get Udev and Mdev working there's a certain things that need to be turned on in the kernel. If you look at the kernel configuration file you'll find there's certain things like config hotplug that needs to be set up, things like config net, config unix and so on. These are things that are required in order for Udev to interact with the kernel at a really low level through the file system. Now as I said before, slash dev is where the device files live and it's usually a tempfs which is a RAM based file system. It disappears when you reboot and it's something that's created and populated at boot time during initialization. Now in something like angstrom what it'll do is it'll actually run the script that you see at the top of the slide here. However on something like a build root based root file system it has a script a little bit longer that you'll see further down at the bottom. And again they both do roughly the same sorts of things. They mount a file system, they start up Mdev or Udev, and then they do the appropriate thing to create device files as needed when device drivers are started up. Okay, we've gone through initialization to start up system processes. We've got the system that brings up the device driver node files properly. Now we're into the rest of user space. One of the big decisions you can make at this particular point of time is what C library is going to be used to link your utilities. Again some are bigger, some are smaller. In the server or desktop kind of situation we've got something called Glib-C. Glib-C is the GNU C library and it provides an all singing, all dancing implementation of the C standard and all the different things that come along with a modern unit system. Now C libraries have a tight coupling with the compiler that you're using because the compiler needs to know how to implement certain functionality through the C library. A lot of utilities that are used to build root file systems allow you to choose which C library you want to use. In the case of angstrom it defaults to using Glib-C. Again it gives you the most functionality possible. On something like a build root however it defaults to the Uc-Lib-C library and that's because it comes from the same people who build root and Uc-Lib-C developers are the same people. And again that's because build root is meant for a much smaller, more memory constrained kind of system. So you can actually see on something like an angstrom with Glib-C that in fact the C library is pretty close to five times bigger than Uc-Lib-C. That's a pretty big savings in RAM and Flash that you're using. So whereas Lib-C might be over a megabyte, a Uc-Lib-C library is going to be something like a quarter to a fifth of that size. Now there are more options than just G-Lib-C and Uc-Lib-C. There's also a few others such as E-G-Lib-C, Diet-Lib-C and K-Lib-C. These all have slightly different uses however. Something like K-Lib-C is actually use your initial RAM disk in order to boot your system before you have access to your real C library. E-G-Lib-C is actually a special case. It was a situation where the G-Lib-C libraries were actually taken and optimized by the embedded developers. They felt that G-Lib-C was a little bit too heavy for what they wanted to do on embedded systems. So what they did is they took the source code and they made a number of optimizations, have it take less memory and maybe remove certain things that aren't used very much anymore. The ironic part is a lot of the big Linux distributions, the ones that run on servers, actually looked at this and realized that in fact it made their distributions better themselves. For instance, if you're using something like a Debian or an Ubuntu, for instance, it says it's using G-Lib-C, in fact it's using E-G-Lib-C instead. It's using an embedded C library in order to actually make that system faster and use a little bit less memory. Now, beyond choosing C libraries there's a number of other things you can choose to do and that's things like whether or not you're going to statically link your binaries or whether you're going to use dynamic linking. Static linking leads to bigger binaries, dynamic to smaller. However, when you use dynamically linked libraries, there's a cost at startup time because your program may float into the memory and then it actually has to be linked before it can run at that particular point in time. The nice thing though is that through a careful use of static and dynamic linking you can actually choose which libraries to use for different binaries. In other words, if your system is designed specifically to use UC-Lib-C but you need a couple of utilities that use G-Lib-C, what you can actually do is link those couple of utilities statically and still have the rest of the system use UC-Lib-C. It's as flexible as you need it to be. So hopefully this has given you a taste of LF-411. Of course it takes you from bootloader all the way through up into user space and the decisions that are made around that sort of thing. My name is BN Webster and I hope to see you in class sometime soon.