 Grisaf. Fy fyddwch. Mae'r cystafell yn y systeimddi. Rwy'n gwybod bod gwneud am hyn, gwneud y cystafell yn yw'r cystafell. Rwy'n ffordd, rwy'n ddych chi'n mynd i'r llwyddiadau ac rwy'n ddigonol i'r cystafell. Felly, rwy'n gwybod bod yna. Ond mae'n gwybod i'r cystafell, sy'n gwybod i'r cystafell. Bwg. Ydwch. Felly dyma'r ddau methu sy'n meddwl y soedd cyffinionol. Felly mae'n rhaid i'w ddweud cyffinion i'w ddau sy'n meddwl. Felly mae'n rhaid i'n meddwl i'r ddau sydd wedi'i ddweud i'w ddau. Rwyf yn gweithio ar y, oedd yn ymwyfydd yr ysgol, rwyf wedyn yn mynd i ddiwedd yma'n mynd i ddau. David may just stop at some point and you'll have to come back next year for the the red or seasons two as I call it see how it goes so I'm doing some demos. So anything could go wrong and almost certainly will. I've done this, I've talked about system da in the past back in in European and I spoke ICT where we need to talk about systemd, which is really all about identifying boot speed issues. So I'm not gonna cover that this time round. So we're gonna be booting quite slowly in fact. So this is systemd to boot and manage embedded Linux systems with demos. Okay, so concepts. The key idea I think of system B is that if you write down all the things that need to be done during boot and if you put in explicit dependencies between all those components then you end up essentially with a tree structure. Then you can write a demon which can walk through that tree structure heading for a target. Once you reach that target you've started everything that needed to be started. So key concept here then is that we have dependencies, we have targets. The components are called units and the unit is a very simple file format type. i ni'n gweld ei wneud i Gymroedol yn rhan, i ni'n ffyrdd. A ddyn nhw'n mynd i'n gweld ei wneud i'r ddweud i gwaith o gyd, mae'n gwych chi'n gweld ei ddweud i gyd blwyddyn fyddwyr i wneud ei wneud i gweithio'r ddweud. Ond mae'r wneud i'r ddweud i gweithio'r ddweud i wneud i gweithio. Ac yna'r ydyn nhw'n gweld. Ac mae'r ddweud i'r ddweud i gweithio'r ddweud i gweithio'r ddweud. yw'r unig. Yn ymgyrch yn ysgrifennu ac yn y cysyllt, rydyn ni'n gweithio'r dysgu a'r cysyllt a'r ddysgu'n cysyllt y documentaidd ac'r ddifennu mae'r ddifennu. Felly, ymgyrch ar y unig yma ar y bod yn y cysyllt. Yn y unig mae'r unig, mae'r ddifennu'r ddifennu. Felly, ymgyrch ar y cysyllt a'r unig, mae'r unig yn y cysyllt. Yn y cysyllt, mae'r unig yn y cysyllt yma'r unig. Felly, mae'r unig, mae'r unig, mae'r unig, mae'r unig. Mae'r unig mae'r unig, mae'r unig, mae'r unig, mae'r unig ffoall, mae'n tu i gaeli midwarko. Mae'r unig erioed fillus y tu whesolaeth. Mae marrymen a'r unig yn astau cael litres i'w identifier mae'r unig, mae'n gyntaf i wneud gyda'r unig. Oni éch gyda hemau, mae'n dechrau yr mhorod ar nhw. осonwch ar gyhoedd ddifennig cywolfogreid y dechrau'. Mae dros chi angen o'r unigau o'r ddechrau'r cyflig y bydd y pethau'r cwprnwys. Yma'r llysig ar y cyflig sy'n ei wneud o'r ddod, yma'r ddod o'r ddod y gallai'r cyflig. Felly, dweud o'r ddod o'r ddod o'r ddod o'r cyflig o'r ddod o'r ddod. Felly, mae'r ddod o'r ddod o'r ddod, mae'n oed o'r ddod o'r ddod o'r ddod. Yn y gweithio, roedd y proses yw'r ddod o'r ddod o'r ddod o'r ddod, ym mwy o'i ddechrau'r ddweud o'r ddweud yma? Felly, dyma'r ddweud yn ddweud yn oed yn y llif yw'r dweud yw'n ddweud, rwy'n ddweud â ddweud â'r ddweud. Felly yw'r ddweud yn y ddweud? Felly mae'n ddweud yn gweithio'r ddweud, dyn ni'n ddweud yn ei ddweud, mae'n ddweud yn cael y gwaith yn rhaid. Mae'n ddweud yn rhaid yn rhaid, web server until the network is running. So let me illustrate this with a rather crude diagram. So, I want to get across this idea of the difference between dependencies and ordering. There are different concepts within system D. So dependencies, these are created then by things like requires. So here, two units, A, B and C, sorry, three units, A, B and C. When I start A, it's going to start B and C because they are dependencies. So as a result of this, we'll find that if you look at the activation queue, we have those three units there in some arbitrary order. I've written them as A, B, C because that's the most likely order they would end up, but in principle, there can be any order. And when system D comes to execute the activation queue, there is no ordering here, so it can do whatever it likes. And typically what it will really do is run them in parallel. So one of the nice things about system D is it parallelizes everything. So you'll end up that A, B and C on a quad core system. They are each going to start up on a separate core. This may be not what you want. So this is why we have the before and after things. These set the order of things that we're going to process from the activation queue. So here I've put in an after statement which says that unit A must run after unit B. I haven't done anything with unit C. So in this case then, the activation queue will run B then A and C, we don't know, it will run C at any time it likes. But the key thing is we guarantee now that it's going to run B before A. Okay? So question for the audience then, what do you think will happen if I leave out the requires and leave in the after? So supposing between A and B I have an after statement, but no requires. So who thinks that will run unit B? Hands up. Okay, some people will intercommit. So who thinks that unit B will not be started? A few more. Excellent. Well, you are correct. Unit B will, just having an after statement in there will not cause unit B to run at all. If it wasn't already on the activation queue, an after statement will not add it to the activation queue. That's what the requires is for. Okay, so these units, they are stored in various places in the system and this is the search path that system D will go through when it's looking for these units. And there are some others as well. You can change this at compile time if you really want to. But the basic idea then is that the distribution-wide, the default set of units are going to be in lib system D system. But you can override those by putting other versions into either run system D system or ETC system D system. The run stuff you generally don't mess around with because that's volatile and that is handled by system D at runtime. But you can go and put stuff into ETC system D system and this is how you can override the default behaviour without going and hacking around in stuff in the lib system D system directory. So, for example, if you decide that you don't want a particular unit to run at all, you simply need to create a unit with exactly the same name, but in the ETC system D system directory. And that can just be an empty file or if you wish, you can create it as a sim link to dev null or something like that. And that will then mask the default version, the system-wide default version, which is going to be in the lib directory. Okay, so that's got the basis of units out of the way. Let's start doing something useful with them. So we want to start services. So service is a demon. It's something that does something. So for these, we have units that are something.service. And they must have a service section because that's where you say what the service is. So here's a simple example. This is a slightly edited version of the light TTP demon unit. And you can see we've got a service section there. We have an exec start. So that's the command line that is run when we start, in this case, like TTPD. And just for the fun of it, there's also an exec reload statement which says what will happen if we restart it. So quite often demons have a restart function which is different from shutting you down and starting up again. In this case, it's going to send it a seek up to the demon. So a little bit more detail on that. First of all, types of service. So we can have, first of all, simple services. So the majority of services fall into the simple category. Since this is the default, you don't have to actually put anything here. So a simple service is just a program you want to run in the background end of. But it will be restarted. So if that service terminates for some reason, hopefully it won't, but if it did, the system will work. Hopefully it won't, but if it did, the system will automatically restart it. If you don't want that, then you declare it to be a one-shot. So that means we'll start the service once. When it finishes, we just forget about it. So one-shots are handy for things which means running a program and then you're done. So it could be a shell script, it could be a good example of doing that. Something which you just want to do once. For example, a boot time, which does something, then it's done. The third time I've got here is forking services. This is a little bit obscure, I guess, but if you write a service, sorry, if you write a daemon in the traditional Unix way, which you can do using the daemon system call, then that means that when you launch it, then automatically it actually forks and you copy it itself and runs in the background. So it daemonizes. So if you have a service of that sort, then you have to declare it as being a forking daemon because it means that it's going to do the backgrounding within the program itself rather than being backgrounded by system D. A good example is that reload we mentioned. One other random thing, which was from the previous slide, notice down here we have this reference to $mainPID. So $mainPID is actually a environment variable set up by system D, and as you might expect, it is the PID of the service that was started. In this case, we're using that to refer back, so when we send the seek hub, we know where to send it to. There are a whole bunch of other environment variables which I haven't gone into, but if you do a main system D exec, that will tell you. Okay, so that's the basis. I'm not going to go into any more detail at the moment than that. In a moment, I'm going to do a demo. And in order to do that, I'm going to have to interact with system D and I do that using system CTL. So system CTL is a command line interface to system D. And here are some of the useful things you can do with system CTL. So start, stop. Well, I'll go through these bit by bit. Now, for the demo, I'm going to be using Yocto project because what else would I use? First thing then is that by default, for whatever reason, Yocto is going to be using system 5 in it, not system D. So you'll have to go and make a tweak and you need to add init manager system D, for example, to the conf local conf file or into pretty much any other conf file. Okay, so demo part one. So the demo is to start a demon called Boris. So Boris is a completely useless demon. Yeah, I think you've got it, you've got it. So it's built using Yocto. Not exactly the latest version. Apologise for that. I never quite got round to rebuilding the whole thing since I put the original demos together. Anyhow, so it's a version of Kirkstone using system D 250 and it's running on QEMU ARM. So bear with me, this could go wrong, but it may not, you never know. So I do like presentations with demos in. It shows that the presenter has gone through some pain to get to this point. So this is pretty much out of the box. I've only made a couple of small changes to the default config. Right, so I have a little cribsheet over here which I'm going to use to remember what I have to do here. So we should find that Boris is not currently running because I hope I haven't enabled it. Now, okay, it is running. Well okay, imagine it wasn't. So, okay, so I do system CTL status, name of the service Boris and it says it's a useless demon and it's currently active and it's running which I didn't really want it to do, but never mind. Because I wanted to demonstrate that I can start it and stop it. So I can do stop. Don't see why that shouldn't work. Status, yeah. This is how it's meant to be to start with. So it should now say that it is stopping useless demon, stop to useless demon. Yeah, that'll work fine. And then, as you can imagine, I can start it again by using start. So the point is then that I can control this demon. If I can spell start, there we go. And as it runs, you can see it says it's running for, in this case, zero seconds. Yeah, that was basically it. Okay, so that has got over the idea, I think, of services. Services of demons, that's easy. Let's talk a little bit about targets and dependencies. This is, in my opinion, slightly non-intuitive. So a target is another type of unit. It ends in .target. But the targets themselves don't do anything. They are simply a configuration point. And then we can have things depend on those targets so that when we reach a certain target, it will have started a whole bunch of demons. So a good example of this is the multi-user target. So this is the entry for the multi-user target. And you can see it requires basic target. It conflicts with some things. And it should come after the basic target. And after you rescue service and rescue target have been stopped. And so you can see then that there are other targets. In this case we have basic targets being referenced here. And if you were to go and look at basic target, you'll see that depends on some other targets. The slightly confusing thing is that when you start looking at the dependencies of targets, they mostly just depend on each other. At least I got to the point of thinking, I don't know how this works. How does anything start if it's only targets? And the targets don't actually do anything. Come to that in a moment. Oh yes, the default target. So what target are we going to launch at boot time? That is the default target. And that is usually done as a symbolic link to the target you want. So in this case the default target is going to multi-user target as we just saw. And you can just change that symbolic link if you want to start a different default target or you can do essentially the same thing through a system CTL command. Or you can even do it through a kernel command line. So back to these dependencies then. How do these dependencies actually work if they aren't any explicit dependencies on services in these targets? So it turns out there are these things called these things called incoming dependencies. So the things we just looked at just now requires and wants, those are outgoing dependencies. They are from this unit, they are pointing to other units. Incoming dependencies, as you can probably guess, go the other way. And they are expressed through the keyword wanted by. And the wanted by keyword goes into another section called install. I'll explain in a moment why it is called that. So here we see in the install section we have wanted by multi-user target. So that says that when the multi-user target is started this is a dependency of the multi-user target so this will get started. So we have incoming dependencies, we have outgoing dependencies. So this means then that when I start target at the top of the screen here that is going to start up all those units in this case services that have a wanted by link in there. So how does this actually work? So the secret here is the idea of installing or enabling a unit. When you enable a unit systemD will process the install section and it will install the wanted by link. And in actual fact that is done as a symbolic link. So if I enable my simple demon and then if I go looking into systemetc system I find there's a directory called multi-user target.wants. So this is where the wanted by links go. When I install simple demon it puts a link in that directory to my service. And then when we get to the multi-user target it's going to go through all these links and add those onto the activation queue. So that's it. So wanted by is putting a link into me so that when the target usually is started it will add me to the dependency queue and then my program will get to run. So you may wonder why do it in this slightly obscure way. The reason is that if we didn't have this facility then every time I did a new service to my system I would have to go and edit the multi-user target and I would be forever adding things in and taking things away and the whole thing becomes unmanageable. So by not encoding that information into the target unit and by instead encoding it in the system unit that you're installing then it becomes much more modular. So when I install my service it says I am part of the multi-user target. So this symbolic link takes care of that. Okay so in order for that link to be created then you have to run the system and do system CTL enable. That obviously doesn't work so well particularly in the embedded case where nobody's ever going to do that. So you can add an extra couple of lines to your bit-bake class and you just need to add this stuff here basically. There is a BB class called systemD and then you just tell it what the service is that you want to belong to. Simple Demon service. That will then install the unit. The unit has an install section. The install section has a wanted by statement. So that when I build this I'm going to find that this symbolic link to my demon has already been created as part of the Yocto de route affairs build. So now boot it up and in this case Simple Demon will be running. Okay demo enable Boris a boot. Well I've kind of already done this because I screwed up the demo previously so but I can show, where's my crib gone to? Yeah I can do it from here. So yeah if I look into EDC systemD system multi-user once and so now you can see Boris dot service is a symbolic link now to Boris dot service. So that's why it keeps on booting up and I forgot to do essentially a factory reset before I started the demos. Never mind. But you can also see there's a bunch of other things that have been started up using the same mechanism. What else did I want to do? So we can look at dependencies. Okay there's pretty much quite a large list. So these are, when I run list dependencies as I just did by default it's going to give you the dependencies of the default target so that's why default target is up here at the start and then you see all the things that depend on that and the dependencies of those and so on down the tree. And somewhere, yeah there it is somewhere we can see here is Boris in that list. Good old Boris. Nothing's as slightly interesting I think to do is if I do that. So I would just crudly just look at the targets in my dependency tree. These are, here you can see the hierarchy of the various targets. So here's the default target. That depends on basic target. You know that because it was in the slide. Hope you remember this from about five minutes ago. Basic target then depends on some other stuff and then some others and some others. So you can see the hierarchy of the various targets and I could if I wanted to go into more detail about this but I don't have the time but you can see that the most basic targets are local FS target which is going to mount the local file systems swap target which is going to mount the swap. Sysynet is going to start anything that needs to be started as a result of that and so on and so on. Okay right. So that was, that's the 101. I don't know. Probably good if I do. Does anybody have any questions at this point? Now would be a suitable time to take questions so far. Okay so the question is somewhere, yeah I should, serves me right for leaving this bit. I should have deleted this bit of the slide. So here we have, this is the multi-user target. A conflict with the rescue service and rescue targets. This is when you boot up in rescue mode if there is such a thing. Typically a RAM disk or something. But after basic target which makes sense because that's in the boot up sequence but also it has after rescue service and rescue target which are these two things here which is kind of slightly weird. What it means is, counting intuitively maybe after they have been stopped. So if they were to be started we would have to, I'm not sure this actually could happen actually in practice. But yeah it just means that we need to make sure that they have finished stopping before we can start this service. Sorry I'm, this is wonderful. Oops gone the wrong way. Yeah you're going. Sorry I'm doing the wrong thing here. Let's go back. Yeah this bit here. Found it. What happens if unity is terminated? The simplest configuration is, as we're going through here, the simplest configuration is that if unit B stops then that's fine. You can put additional statements in here that say that if unit B stops we should do things with unit A for example. But by default that's not what's going to happen. So if unit B stops, that's fine. You can configure that and that's not a case that I'm going to go into. But yeah. Okay one more question then I'll move on. Yes sir. Will the dependencies also matter if you disable a service? Yeah. So that is orthogonal in that if I disable unit B, well typically unit B would be disabled anyhow because it's going to get started as a result of this requires link here. So you would have a wanted by link to unit A and then as a result of that being activated that will then follow the outgoing dependencies from that and so it will start at these. So usually units B and C in this case would not be activated by a wanted by. They will be activated at arms length if you like because of the required statement here for unit A. So you have, unit A is dependent on the target. When unit A gets started we also want to start units B and C because they are in some way related to each other. Okay. Need to move on because time moves on. So what time do we finish? We finish at, can somebody tell me what the end time obviously is? I forgot to make a note of it. Okay, thanks. Yeah. So I'm going to have to go through the next bits fairly quickly. I might go into Steve Rostat mode. If you know Steve Rostat you know what I'm talking about. But I'll try not to be too... So next thing then. As I've described it so far that's a great for a kind of static system where you know exactly what you need, a boot time and every time you boot it up you want to do the same thing. Sometimes that's not what you want. You want something a bit more dynamic. So we'd like to be able to load services on demand. And we can do this through these things called sockets. So socket is another type of unit. And it is essentially a trigger to system D. So when the conditions of the socket are met then system D will do something. It will start a service typically. So for example, here I have a socket unit called foo.socket. It has a socket section and it says listen stream 1, 2, 3, 4. Except no, come to that in a moment. And it's got a wanted by on the sockets target. So this means then that as a result of this system D will be listening on TCP socket 1, 2, 3, 4. When we get an incoming connection on socket 1, 2, 3, 4, it's going to start. What's it going to start? It's actually going to start foo.service. Come to that in a moment. So sockets are the way that we can trigger events and then have system D run other units for us. The most obvious example of this would be regular sockets. So we can have TCP sockets. We can have local sockets. But we can also have a bunch of other things which aren't really sockets at all. So we can have five foes, device nodes. Okay, that is a socket. Messages and USB function FS endpoints. So all of these things you can arrange the system system D to launch something when there is an event on one of those things. By default then it's going to launch a service with the same name as the socket. So my foo socket is going to launch a foo service. If you don't want that, then you can override that within the socket section. You can put a service and you can give it a different service name and that will be run. As well as sockets you can listen on files. So in this case listen special dev RF kill. When we get any kind of input on dev RF kill that's going to trigger this socket and that will then run the RF kill service. Okay, so there's no filtering here. Basically it's just going to open that file and do a read. Actually it's going to do an e-poll on that. When we get some data arriving on that file that then is going to trigger this thing. So it's in place. I'm going to have to skip this because as I expected we're running out of time. So I just skip that stuff. And I'm also going to skip the demo but I was going to do a demo of launching SSH. So if you were to look at the implementation it is by default not running an SSH demon but when I make a connection to it there is a socket for port 22 that will then launch in this case drop bear. Similar concept with timers. So this is another type of unit. Something.timer. It's a similar concept in that this is an event but now it's a time-based event. So I can say after something so delay for some number of minutes before we run a service or we can do it on a regular basis like a cron job or whatever. Restarting services. Again going through this fairly quickly now. Resilience. So when your service terminates what do you want to do about it? Well you can do this with the restart option. So we have... I'm going to go through this fairly quickly so onFailure is the most useful one. So that says if my service fails or if the program fails then I want to restart. Of course this may not always give you the result that you want. You can end up where you keep on restarting and it keeps on going which is going to crash again. What else is it going to do? So you can put rate limiting on this as shown here. So this says if it terminates twice in 30 seconds then give up. We're no longer going to try restarting this thing. You can also do other things. You can get it to run a program. So onFailure we can actually get it to run another service which could do some kind of remedial stuff. And you can take it to the extreme and actually put onFailure action reboot. So that when my service fails or when it's failed two times in 30 seconds I'm going to reboot the system. Maybe that'll fix it. A bit about Watch Dogs. So with a Watch Dog we can have a service that is going to ping system D on a regular basis. If the pings are timed out then we want to go into a failure state and then we can recover in the various ways we just talked about. So we do this by putting Watch Dogs sec 30 and then restart on Watch Dogs when Watch Dogs times out we're going to restart this service. To make this work you need to put a bit of code into your program. Just denodify with that string. You can also have system D itself protected by a hardware Watch Dog. You just put a bit of code into the system.conf and this says that system D when it starts up is going to use the hardware Watch Dog if it's available. So in this seconds section here you give the time out say 30 seconds or a minute or something. Results limits. We're going to have to go through this pretty quickly. We can put limits on things so that we can put limits on CPU usage on memory usage and that's it. There we go. Thank you.