How to create a Linux system that runs a single application?

17

8

I'm trying to run a Linux application and all I want to run is this one application off of boot. I need networking and that's all (no display, peripherals, etc.). I want no other applications running so that the application I run has 100% of the CPU. Is this possible?

dschatz

Posted 2011-08-08T17:27:32.223

Reputation: 271

http://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else – Ciro Santilli 新疆改造中心法轮功六四事件 – 2015-10-25T20:05:35.367

It won't be able to grab 100% of the CPU seeing as your OS still needs some resources. – n0pe – 2011-08-08T17:44:00.943

@MaxMackie Obviously, but I would like the OS to only take over on behalf of the application (for networking purposes for instance). – dschatz – 2011-08-08T17:45:14.030

1You realize that even with a desktop environment loaded, but sitting there idle, it isn't using any cpu time right? And the ram it is using is subject to being swapped out if other applications demand it. – psusi – 2011-08-08T18:28:42.697

@dschatz It would help if you include more details in your question. Like telling us more about what application you want to run, how you want it to perform and what kind of hardware you're using. – N.N. – 2011-08-08T21:17:34.100

If possible, I would like to know why do you want this. From what I understand, you want to remove everything from the OS (console included) just to run your app. The performance gains will be marginal so what is the point of having all that work? – nmat – 2011-08-08T21:22:05.283

Answers

13

Minimal initrd CPIO hello world program step-by-step

enter image description here

Compile a hello world without any dependencies that ends in an infinite loop. init.S:

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

We cannot use sys_exit, or else the kernel panics.

Then:

mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

This creates a filesystem with our hello world at /init, which is the first userland program that the kernel will run. We could also have added more files to d/ and they would be accessible from the /init program when the kernel runs.

Then cd into the Linux kernel tree, build is as usual, and run it in QEMU:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

And you should see a line:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

on the emulator screen! Note that it is not the last line, so you have to look a bit further up.

You can also use C programs if you link them statically:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

with:

gcc -static init.c -o init

You can run on real hardware with a USB on /dev/sdX and:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

Great source on this subject: http://landley.net/writing/rootfs-howto.html It also explains how to use gen_initramfs_list.sh, which is a script from the Linux kernel source tree to help automate the process.

Next step: setup BusyBox so you can interact with the system: https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Tested on Ubuntu 16.10, QEMU 2.6.1.

Ciro Santilli 新疆改造中心法轮功六四事件

Posted 2011-08-08T17:27:32.223

Reputation: 5 621

3

you can start kernel with init=/path/to/myapp parameter defined in your bootloader.

Michał Šrajer

Posted 2011-08-08T17:27:32.223

Reputation: 2 495

2This is a rather extreme solution. Replacing the startup script with the user application will have the application running without networking, without any filesystems other than the rootfs mounted (no sysfs or proc or tmpfs), and possibly some device nodes will not be created. – sawdust – 2011-08-09T15:33:34.297

2@sawdust: Totally agree. But the question was also bit extreme... :-) – Michał Šrajer – 2011-08-09T17:05:13.720

2

It sounds like you are trying to set up a kiosk. Most guides around the Internet focus on a web browser like Firefox as the single application that runs. Take a look at this guide for ideas.

William Jackson

Posted 2011-08-08T17:27:32.223

Reputation: 7 646

2Hmm, I'm really just trying to run a single application with networking. I don't want any X and as few other applications running as possible. I don't see how this restricts all the unnecessary daemons from running. – dschatz – 2011-08-08T17:43:42.453

can the application run without X though? – Journeyman Geek – 2011-12-06T03:37:21.707

2

You can certainly run just one user application after booting the kernel. But it will not have 100% of the CPU because there will be some other kernel-related processes that must exist. This is commonly done in embedded-Linux devices, e.g. wireless routers. I also have first-hand experience doing this for a multi-threaded application.

Once the kernel has booted, an initialization or startup script is run. Read up on Linux runlevels and the init process. There are various startup schemes in use, so it is not possible to be specific. But Linux will allow you to configure exactly which applications and daemons will execute for your situation. Other than a startup file at root, the files that need modifying are in /etc, and in particular /etc/init.d

BTW unless you're somekind of superprogrammer or before you get a remote GDB server running, you're going to need somekind of debug console (either the PC console or a serial port) for your application. This will allow you to be notified of seg faults, bus errors and assertion failures. So plan on having somekind of "peripheral" besides "networking".

sawdust

Posted 2011-08-08T17:27:32.223

Reputation: 14 697

1

There are some system applications which are must be run, besides them, sure, you can dedicate the rest of the computer resources to that application. To have the very minimum you can take a look at really small Linux distros like TinyCore Linux etc.

Also it would depend on application itself too, what services it requires besides the network etc.

I think if you can provide more specific information you would get more detailed response.

Like what kind of app etc.

bakytn

Posted 2011-08-08T17:27:32.223

Reputation: 1 537

My application uses the pthread library to run some mulithreaded workload (arithmetic operations) and can be instructed to do different calculations based on input from tcp/ip. Looking at TinyCore Linux, it boots into a full desktop environment, which I don't want. – dschatz – 2011-08-08T17:36:15.210

TinyCore has a smaller brother called MicroCore. No GUI, check it out. – n0pe – 2011-08-08T17:45:25.607

Another option could be Gentoo or Debian's net install. I think you have the option of not having a GUI. Either way you'll end up having to modify some run level files to make sure only certain things start up. – n0pe – 2011-08-08T17:47:03.373

@MaxMackie Thats the real part I need help with. I can easily install a headless server, the question is what do I modify to minimize whats running – dschatz – 2011-08-08T17:48:54.370

@dschatz I'm not sure where you'd start either. However, you said that you wanted the application "up and running"? If we remove the need for a GUI what exactly do you mean? I'm assuming its an application which can be completely controlled by the CLI so maybe simply editing bash's configuration file to 'run' your application at boot could be a good option? – n0pe – 2011-08-08T17:52:18.310

@dschatz yes, TinyCore contains basic GUI, and yes try MicroCore. You can also try Ubuntu Minimal (about 20mb of iso) https://help.ubuntu.com/community/Installation/MinimalCD

– bakytn – 2011-08-08T17:55:03.693

1@MaxMackie I actually want no interface on the machine itself outside of the tcp/ip stack. The application can block on a port and can be controlled via tcp packets sent to that port. – dschatz – 2011-08-08T17:55:56.577

You could try Linux From Scratch :D Which is probably the best of the best possible options in your case. You would need to spend some time to learn it though. – bakytn – 2011-08-08T17:56:15.813

I don't need suggestions of Linux distributions. I need an explanation of what files must be modified to boot into this single application with networking and as little else – dschatz – 2011-08-08T17:58:35.623

@dschatz wow that's a pretty cool idea. However, not having ANY interface goes against most "regular" people's needs. Your OS needs to start up to something, the lowest possible denominator being a console window. You could give Linux From Scratch a try, but I think what you're looking for is something akin to a custom machine not custom os or software. You could always just not give the machine a graphics card and no video output and do all your maintenance across a network (but you'd still be using bash or something like it). – n0pe – 2011-08-08T18:00:04.477

1

I'd recommend an environment with little services running (check this out http://linuxhelp.blogspot.com/2006/04/enabling-and-disabling-services-during_01.html) and hardly anything other than your application and it's dependencies installed.

– n0pe – 2011-08-08T18:01:43.583

1@dschatz well, then you need to hack kernel, remove everything else and compile your app into it. no bash no anything else. just your app..lol. – bakytn – 2011-08-08T18:33:41.833

1

If you really want nothing but the Linux kernel, networking, and your application, the only way to do it is this:

  • You will need to make your application a kernel module - make sure it is debugged and well tested. This kernel module would have to initialize things typically done via userspace such as set interface IP addresses and all that good stuff.
  • You will need to download and configure (make menuconfig) your own custom kernel and remove all features that are not related to running the system and networking. You will want to disable to block layer, I don't know how to do this on recent kernels through make menuconfig.
  • You then need to include your module into the kernel so it is included as part of the kernel and not a loadable module. You would likely disable loadable modules in the step above. If you know enough C/C++ to create a kernel module this should be easy for you.
  • You need to modify whatever part of the kernel that panics if init fails to not do that, or be prepared to live with 1 extra user-space process.

I know it's possible for kernel modules to create processes - a simple ps aux would show many on a typical system (they are all in brackets). You probably want your module to create a kernel process. To get rid of all kernel-created processes besides yours, you'll need to disable threads [kthreadd], power management [pm], the event layer [events], and others.


If you want a more practical setup of the kernel + 1 user space process, that's possible.

Linux has a kernel command line option called init= - this is what the kernel will start when it's done loading. The program must be on the root device that is specified with root= or in the initrd (loaded by your bootloader).

If this program exits, Linux will panic, so make sure it doesn't ever exit.

Many modern distributions of Linux have it setup so an init program in the initrd does some additional user-space initialization, before starting /sbin/init or /sbin/systemd. You'll have to find out what your distro does here (info for Debian is here) and find where you can specify the final "handoff" program, and from there you can tell it to start your application instead of init or systemd.

systemd manages a lot of basic functionality, like building /dev, setting hostname, and other things, so if you are flexible you may want to instead look into configuring systemd to spawn a single process, and optionally restart it if it fails. If I am not mistaken it basically does this for single-user or recovery mode - it starts a shell.

You'll have 2 processes running (systemd and your program) but the system won't panic if your program exits or crashes.

Consider also simply a lightweight install of Debian - a "netinst" install doesn't have much running other than the kernel, a shell, and a couple services - or consider OpenWRT/LEDE - it has a webserver for Luci running by default and a couple other services but is easily disabled.

LawrenceC

Posted 2011-08-08T17:27:32.223

Reputation: 63 487