For udev device entries, what is the technical difference between a "property" and an "attribute"? How are they customarily created (generated?) and used? Which one is the better source of truth?

I'm asking in the context of a Raspberrypi Python application that should detect any hot-plugged serial port adapters and display the "relevant" device information (whatever that is) to the user, to enable them recognise their devices. In particular, I use the pyudev library to interface with libudev, and my plan is to search for devices from the tty subsystem that are provided by a usb-serial subsystem device. I've looked through the properties and attributes by some test devices I had lying around, to see what values they provide and where. So far, they all have in common that there is a subsystem: tty->(subsystem: usb-serial->)subsystem: usb, device_type: usb_interface->subsystem: usb, device_type: usb_device device ancestor chain (below the USB hub) that relates to the adapter, and the values like vendor, model and serial number are duplicated in various properties and attributes all over the four devices (or sometimes three, ACM* tty devices have no usb-serial). So which one should I access? Is there any (written) convention which attributes/properties such devices bring with them, and where can I find it?

I've read (or at least skimmed over) various documentation pages, but they mostly describe how to write your own udev rules, which is not what I'm after. I understood from the udev manual ([1], [2]) that ATTR is used for values stored in sysfs attributes of the device, and ENV is used for "device properties", but both can be matched and also written. I suppose there are some default rules that inherit values from a parent device to a child device, but that's happening for both properties and attributes alike?

This answer says "If both ENV and ATTR contain the same information - you can use any of them, there is no any difference.", which doesn't leave me any wiser.

1 Answer 1


Properties are set by udev rules and can be modified by other rules.

Attributes are read by udev from sysfs nodes. Assigning a value to attribute in udev rule causes write this value to sysfs node and affects device behavior.

You can consider properties as simple variables. But attributes have getters and setters, you can consider reading attribute e.g. as $(cat /sys/devpath/name) and assignment a value to attribute as echo value > /sys/devpath/name

  • Ah, that makes sense - the sysfs nodes are not just virtual descriptors, they're really device/driver data and configuration. So for display/identification purposes, I should then use the device properties that some (unknown but beneficial) udev rules generated?
    – Bergi
    Sep 2, 2022 at 0:36
  • @Bergi I'm not very familiar with Raspberry Pi OS and have no RPi running nearby, so can't check what default udev rules are provided there. You can check /usr/lib/udev/rules.d/ for files with rules related to usb-serial, find what package provides them and mention that package as dependency to your application. For example, in Arch Linux there is 60-serial.rules provided by systemd with line SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb", so some properties are set by udev's builtin functions.
    – dimich
    Sep 2, 2022 at 1:29
  • Ah, perfect, that should answer all my questions regarding how the properties are built! /lib/udev/rules.d/60-serial.rules exists and is probably not different from your version.
    – Bergi
    Sep 2, 2022 at 1:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .