Where are my devices?

UPDATE: Our new base images [https://docs.resin.io/#/pages/runtime/resin-base-images.md] automatically populate /dev correctly- so your devices will be immediately accessible without the steps described here. However- they are still necessary for custom base images and of course it’s always interesting to explore what’s going on under the hood- so sit back- relax- and enjoy 🙂 This is the…

UPDATE: Our new base images automatically populate /dev correctly, so your devices will be immediately accessible without the steps described here. However, they are still necessary for custom base images and of course it’s always interesting to explore what’s going on under the hood, so sit back, relax, and enjoy 🙂

This is the first in a series of blog posts looking at topics drawn from our discussion platform, Resin Talk.

Today’s topic is connecting devices to your application container, inspired by this thread where a user’s device was not being detected no matter which library they used.

Linux Devices

We proudly use GNU/Linux on all of our devices, so before we get into how to access attached devices from your resin.io applications, let’s take a look at how Linux exposes them more generally.

Devices are made available to programs via special files in the /dev directory*. This folder is populated using the Linux facility udev which runs in userspace, monitors device events and creates/removes these files.

When a resin.io application runs on one of your devices, it is running inside of a container, meaning that while it uses the same kernel as the rest of the code running on your device, it is isolated inside its own environment and root filesystem, unaware of any other processes running on the device or the host’s /dev mountpoint.

As a consequence, the /dev directory will be out of sync with the host OS for:

  1. Devices which are connected after the application is started – these will not be added to the /dev directory as udev isn’t even running.
  2. Devices present on startup which require udev rules to generate files in /dev – these will not have been created, as the container didn’t exist when udev ran them in the host OS (though we do copy the original contents of /dev into the container on startup.)

Solution

In order to fix this, we:

  • Ensure /dev is mounted correctly using devtmpfs – failing to do this can result in some device nodes not being correctly populated, naturally we want to see all of our devices.
  • Address issue 1 by running the udev daemon, udevd, this makes sure we pick up any new devices which are connected after the container has started.
  • Address issue 2 by triggering udev rules via the udev admin tool, udevadm, using the trigger command.

The following script performs all of these tasks and should be run immediately after application startup, perhaps as the first steps in a script executed by the CMD in a Dockerfile, or via a start script in a node.js project:

Running this immediately after application startup will ensure /dev is populated correctly, allowing any libraries you are relying on to communicate with your devices as well as any of your code that directly interacts with /dev.

We are working on new images which should eliminate the need for this altogether, however for the time being this is a very handy workaround for this issue.

*Of course /dev isn’t the only means of interacting with attached hardware, but it is arguably the most common!

Have questions, or just want to say hi? Find us on our community chat.


Posted

in

Tags: