Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX UDEV 2026

udev
Cihaz Yönetimi ve Hotplug Kuralları

Linux'ta cihaz olaylarını yakala, kalıcı isimler ata, script'ler tetikle — USB seri porttan CAN arayüzüne, özel donanımdan otomatik servise kadar.

00 udev nedir: kernel'dan udevd'ye akış

udev, Linux çekirdeğinin ürettiği cihaz olaylarını yakalayan, /dev dosya sistemini yöneten ve kullanıcı alanı kurallarını çalıştıran dinamik cihaz yöneticisidir.

Genel bakış

Linux'ta her donanım bileşeni çekirdek tarafından soyutlanır ve bir cihaz dosyasıyla temsil edilir. Tarihsel olarak /dev dizini statik bir dosya kümesiydi; her olası cihaz için önceden oluşturulmuş dosyalar içeriyordu. udev bu yaklaşımı değiştirdi: cihazlar fiziksel olarak bağlandığında /dev'de yaratılır, çıkarıldığında silinir.

kernel → netlink → udevd → rules akışı

Bir USB cihazı takıldığında çekirdek önce cihazı tanır, gerekli driver'ı yükler ve ardından netlink soketi üzerinden bir "uevent" mesajı yayar. udevd (veya modern systemd altında systemd-udevd) bu mesajı dinler. Uevent'i aldığında kural dosyalarını tarar, eşleşen kuralları sırayla uygular ve son olarak /dev'de cihaz dosyasını oluşturur.

Donanım takıl → kernel driver probe → uevent (netlink) → udevd → kural eşleşmesi → /dev/cihaz oluştur + RUN çalıştır
bash — udev olaylarını izle
# Kernel ve udev olaylarını eş zamanlı izle
udevadm monitor

# Yalnızca kernel olayları
udevadm monitor --kernel

# Yalnızca udev olayları (kurallar uygulandıktan sonra)
udevadm monitor --udev

# Örnek çıktı (USB cihaz takıldığında):
# KERNEL[12345.678] add    /devices/pci.../usb1/1-1 (usb)
# KERNEL[12345.680] add    /devices/pci.../usb1/1-1/1-1:1.0 (usb)
# UDEV  [12345.720] add    /devices/pci.../usb1/1-1 (usb)
# UDEV  [12345.730] add    /devices/pci.../ttyUSB0 (tty)

/dev sanal dosya sistemi

Modern Linux sistemlerinde /dev, devtmpfs sanal dosya sistemiyle bağlanır. Çekirdek, driver probe başarılı olduğunda devtmpfs'e cihaz node'u oluşturur; udevd ardından izinleri, sahipliği ve sembolik linkleri ayarlar.

Dosya SistemiKim yönetirNe zaman
devtmpfsKernelDriver probe'da node oluşturur
udevd kurallarıUserspace (udevd)Uevent'ten sonra izin/symlink/script
/run/udev/udevdCihaz metadata önbelleği

udev kural dosyalarının konumu

/lib/udev/rules.d/Dağıtım tarafından sağlanan kurallar (örn. bluetooth, optical drive)
/usr/lib/udev/rules.d/Paket yöneticisi tarafından kurulan kurallar
/etc/udev/rules.d/Sistem yöneticisi/geliştirici kuralları — bunlar önceliklidir
/run/udev/rules.d/Geçici çalışma zamanı kuralları
NOT

Kural dosyaları alfabetik/numerik sırayla işlenir. 99-custom.rules gibi yüksek numaralı dosyalar dağıtım kurallarının üzerine yazabilir. Özel kurallar için /etc/udev/rules.d/ kullanın ve dosyaya 50- ile 99- arasında bir önek verin.

Bu bölümde

  • udev: dinamik /dev yönetimi; cihaz takılınca oluştur, çıkarılınca sil
  • Akış: kernel uevent → netlink → udevd → kural eşleşmesi → node + symlink + script
  • udevadm monitor: kernel ve udev olaylarını eş zamanlı izler
  • Kural önceliği: /etc/udev/rules.d/ > /usr/lib/udev/rules.d/ > /lib/udev/rules.d/

01 udevadm ile cihaz keşfi

udevadm, udev sistemini incelemek ve test etmek için temel araçtır. Cihaz özelliklerini sorgulama, olay izleme ve kural testi için kullanılır.

udevadm info: cihaz özelliklerini sorgulama

bash — cihaz bilgisi sorgulama
# Tüm özellikleri sorgula (kural yazmak için hangi ATTRS kullanılacağını göster)
udevadm info --query=all --name=/dev/ttyUSB0

# Örnek çıktı:
# P: /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0
# N: ttyUSB0
# S: serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_...-if00-port0
# E: DEVLINKS=/dev/serial/by-id/usb-Silicon_Labs_... /dev/serial/by-path/...
# E: DEVNAME=/dev/ttyUSB0
# E: ID_VENDOR_ID=10c4
# E: ID_MODEL_ID=ea60
# E: ID_SERIAL=Silicon_Labs_CP2102_...

# Üst cihazlarla birlikte özellik zincirini göster (ATTRS için kritik)
udevadm info --attribute-walk --name=/dev/ttyUSB0

# Kısaltılmış çıktı: yalnızca özellikler
udevadm info -q property -n /dev/ttyUSB0

attribute-walk çıktısını okuma

Kural yazarken hangi ATTRS{} anahtarlarını kullanabileceğinizi öğrenmek için --attribute-walk çıktısını dikkatli okuyun. Çıktı hiyerarşik yapıdadır: en alttaki blok cihazın kendisi, üsttekiler ana cihazlardır.

bash — attribute-walk örnek çıktı
udevadm info --attribute-walk --name=/dev/ttyUSB0

# Udevadm info starts with the device specified by the devpath and then
# walks up the chain of parent devices...

# --- Cihazın kendisi (ttyUSB0) ---
#   looking at device '/devices/.../ttyUSB0/tty/ttyUSB0':
#     KERNEL=="ttyUSB0"
#     SUBSYSTEM=="tty"
#     DRIVER==""

# --- Üst USB interface ---
#   looking at parent device '/devices/.../1-2:1.0':
#     ATTRS{bInterfaceClass}=="ff"
#     ATTRS{bInterfaceNumber}=="00"
#     ATTRS{bInterfaceProtocol}=="00"

# --- USB cihaz kökü ---
#   looking at parent device '/devices/.../1-2':
#     ATTRS{idVendor}=="10c4"
#     ATTRS{idProduct}=="ea60"
#     ATTRS{manufacturer}=="Silicon Labs"
#     ATTRS{product}=="CP2102 USB to UART Bridge Controller"
#     ATTRS{serial}=="0001"

udevadm monitor: canlı olay izleme

bash — canlı olay izleme
# Tüm olayları izle (USB tak/çıkar denerken)
udevadm monitor --property

# Yalnızca belirli subsystem
udevadm monitor --subsystem-match=tty
udevadm monitor --subsystem-match=usb
udevadm monitor --subsystem-match=net

# Örnek çıktı (USB seri cihaz takıldığında):
# KERNEL[...] add /devices/.../ttyUSB0 (tty)
# ACTION=add
# DEVNAME=/dev/ttyUSB0
# SUBSYSTEM=tty
# ID_VENDOR_ID=10c4
# ID_MODEL_ID=ea60

Sysfs üzerinden doğrudan erişim

bash — sysfs sorguları
# USB cihazların vendor/product ID'lerini bul
cat /sys/bus/usb/devices/1-2/idVendor
cat /sys/bus/usb/devices/1-2/idProduct
cat /sys/bus/usb/devices/1-2/manufacturer

# tty subsystem cihazlarını listele
ls /sys/class/tty/ | grep USB

# Net arayüzleri
ls /sys/class/net/

# Belirli bir cihazın sysfs yolunu bul
udevadm info -q path -n /dev/ttyUSB0
# /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0

Bu bölümde

  • udevadm info --query=all --name=/dev/X: ENV değişkenleri ve sembolik link bilgisi
  • udevadm info --attribute-walk: kural yazmak için ATTRS{} anahtarlarını keşfet
  • udevadm monitor --property: canlı olay akışını izle; kural test için olmazmazı
  • Sysfs: /sys/bus/usb/devices/ ve /sys/class/ üzerinden doğrudan özellik okuma

02 Kural dosyası anatomisi

udev kural dosyaları, eşleştirme anahtarları (match keys) ve atama anahtarları (assignment keys) içeren satırlardan oluşur. Bir satırdaki tüm eşleştirmeler doğru olduğunda atamalar uygulanır.

Kural satırı yapısı

Her kural satırı virgülle ayrılmış anahtar=değer çiftlerinden oluşur. Eşleştirme anahtarları (== veya !=) cihazın özelliklerini sorgular; atama anahtarları (=, +=, :=) işlemleri tanımlar.

OperatörTürAnlamı
==EşleştirmeDeğer eşitse kural geçerli
!=EşleştirmeDeğer eşit değilse kural geçerli
=AtamaDeğeri ata (önceki değerleri sil)
+=AtamaDeğeri listeye ekle (SYMLINK için)
:=AtamaDeğeri ata ve sonraki kuralların değiştirmesini engelle

Temel eşleştirme anahtarları

udev rule — eşleştirme anahtarları
# SUBSYSTEM: cihaz alt sistemi
SUBSYSTEM=="tty"          # TTY cihazları
SUBSYSTEM=="usb"          # USB cihazları
SUBSYSTEM=="net"          # Ağ arayüzleri
SUBSYSTEM=="block"        # Blok cihazlar (disk, SD kart)

# ACTION: cihaz olayı türü
ACTION=="add"             # Cihaz takıldı / driver yüklendi
ACTION=="remove"          # Cihaz çıkarıldı
ACTION=="change"          # Cihaz durumu değişti
ACTION=="bind"            # Driver cihaza bağlandı
ACTION=="unbind"          # Driver cihazdan ayrıldı

# KERNEL: /dev'deki cihaz adı kalıbı
KERNEL=="ttyUSB*"         # ttyUSB0, ttyUSB1, ...
KERNEL=="sd[a-z]"         # sda, sdb, ... (disk)
KERNEL=="video[0-9]*"     # video0, video1, ...

# ATTRS{}: üst cihaz özelliği (attribute-walk ile keşfedilir)
ATTRS{idVendor}=="10c4"   # Silicon Labs USB vendor ID
ATTRS{idProduct}=="ea60"  # CP2102 product ID
ATTRS{manufacturer}=="Silicon Labs"
ATTRS{serial}=="AB12CD34"

# ENV{}: ortam değişkeni
ENV{ID_VENDOR_ID}=="10c4"
ENV{ID_BUS}=="usb"

# DEVPATH: sysfs yolu
DEVPATH=="/devices/pci*/usb[0-9]*/1-1/*"

Temel atama anahtarları

udev rule — atama anahtarları
# NAME: /dev'deki cihaz adını değiştir
NAME="myuart"             # /dev/myuart olarak oluşturulur

# SYMLINK: sembolik link ekle
SYMLINK+="sensor_uart"    # /dev/sensor_uart → /dev/ttyUSB0

# MODE: dosya izinleri
MODE="0666"               # Herkes okuyup yazabilir
MODE="0660"               # Sahip ve grup okuyup yazabilir

# OWNER/GROUP: sahip ve grup
OWNER="root"
GROUP="dialout"

# RUN: shell komutu veya script çalıştır
RUN+="/usr/local/bin/hotplug.sh"
RUN+="/bin/sh -c 'echo connected > /tmp/device_status'"

# ENV{}: ortam değişkeni ata
ENV{MY_DEVICE_TYPE}="sensor"

# LABEL/GOTO: kural akışı kontrolü
LABEL="end"
GOTO="end"

Joker karakterler ve değişkenler

udev rule — joker ve değişkenler
# Joker karakterler
# *  — sıfır veya daha fazla karakter
# ?  — tam olarak bir karakter
# [] — karakter kümesi
KERNEL=="ttyUSB*"         # ttyUSB0..ttyUSB9...
KERNEL=="ttyS?"           # ttyS0..ttyS9 (tek haneli)
KERNEL=="sd[a-d][0-9]"   # sda1, sdb3, vb.

# Yerleşik değişkenler (NAME/SYMLINK/RUN içinde)
# %k  — KERNEL adı (örn. ttyUSB0)
# %n  — cihaz numarası (örn. 0)
# %p  — DEVPATH
# %E{ENV_VAR} — ortam değişkeni değeri
# %s{attr}    — sysfs özelliği
SYMLINK+="serial-%k"      # serial-ttyUSB0
RUN+="/bin/sh -c 'logger udev: %k bağlandı'"

Bu bölümde

  • == eşleştirme, = atama, += listeye ekleme, := sabitleyerek atama
  • SUBSYSTEM, ACTION, KERNEL, ATTRS{}, ENV{}: temel eşleştirme anahtarları
  • NAME, SYMLINK, MODE, OWNER, GROUP, RUN: temel atama anahtarları
  • %k, %n, %p, %E{}: kural içi değişkenler; dinamik sembol oluşturmak için

03 Kalıcı isimler ve sembolik linkler

USB cihazlarının sırası değişebilir: bugün ttyUSB0 olan yarın ttyUSB1 olabilir. Vendor/Product ID veya seri numarasına dayalı kalıcı isimler bu sorunu çözer.

Neden kalıcı isimler gerekir

Linux, USB cihazlara sıralı isimler atar; ama bu sıra takma/çıkarma sırasına göre değişir. Bir üretim ortamında iki USB seri dönüştürücü kullanıyorsanız hangisinin /dev/ttyUSB0, hangisinin /dev/ttyUSB1 olduğunu bilemezsiniz. Seri numarası veya USB port konum bilgisi (DEVPATH) kullanarak her zaman aynı cihazın aynı isimle görünmesi sağlanır.

/etc/udev/rules.d/99-serial.rules — kalıcı isimler
# Seri numarasına göre kalıcı symlink
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  ATTRS{serial}=="AB12CD34", SYMLINK+="sensor_a"

# Farklı seri numarası, farklı cihaz
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  ATTRS{serial}=="EF56GH78", SYMLINK+="sensor_b"

# USB port konumuna göre (seri numarası yoksa)
# usb1/1-1.1 = ilk hub, port 1
SUBSYSTEM=="tty", KERNELS=="1-1.1:1.0", SYMLINK+="gps_uart"

# Birden fazla sembolik link
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  SYMLINK+="ftdi_uart serial/ftdi-%k"

NAME direktifi ile cihaz adını değiştirme

SYMLINK yalnızca ek link oluşturur; asıl /dev/ttyUSBX dosyası da varlığını sürdürür. NAME ise asıl adı değiştirir. Ancak NAME değiştirmek bazı araçlarla (örn. ModemManager) uyumsuzluk yaratabilir; SYMLINK tercih edilir.

udev rule — NAME kullanımı
# Asıl cihaz adını değiştir (dikkatli kullan)
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  NAME="custom_uart0"

# Kullanımdan sonra: /dev/custom_uart0 (ttyUSB0 artık yok)
ls -la /dev/custom_uart0
# crw-rw---- 1 root dialout 188, 0 /dev/custom_uart0

Ağ arayüzleri için kalıcı isimler

Ağ arayüzlerinde de benzer sorun yaşanır: eth0/eth1 sırası değişebilir. systemd-udevd bunu /lib/udev/rules.d/80-net-setup-link.rules ile MAC adresine göre çözer. Özel kurallar da yazılabilir.

/etc/udev/rules.d/70-net.rules — kalıcı ağ adı
# MAC adresine göre sabit isim
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="aa:bb:cc:dd:ee:ff", \
  NAME="eth_mgmt"

# USB ağ adaptörü için
SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="0b95", \
  ATTRS{idProduct}=="1790", NAME="usb_eth0"

# Belirli PCI slotundaki kart
SUBSYSTEM=="net", ACTION=="add", KERNELS=="0000:01:00.0", \
  NAME="wan0"

Mevcut sembolik linkleri görme

bash — mevcut kalıcı linkler
# Seri cihazlar için udev tarafından oluşturulan kalıcı linkler
ls -la /dev/serial/by-id/
# lrwxrwxrwx ... usb-Silicon_Labs_CP2102_...-if00-port0 -> ../../ttyUSB0

ls -la /dev/serial/by-path/
# lrwxrwxrwx ... pci-0000:00:14.0-usb-0:2:1.0-port0 -> ../../ttyUSB0

# Kendi tanımladığımız linkler
ls -la /dev/sensor_a /dev/sensor_b

Bu bölümde

  • SYMLINK+=: kalıcı sembolik link oluşturur; asıl ttyUSBX dosyası korunur
  • ATTRS{serial} veya KERNELS (USB port konum): cihazı benzersiz olarak tanımlar
  • NAME=: asıl cihaz adını değiştirir; dikkatli kullanılmalı, SYMLINK genellikle yeterli
  • /dev/serial/by-id/ ve /dev/serial/by-path/: udev'in varsayılan kalıcı link dizinleri

04 Script tetikleme ve ortam değişkenleri

RUN+ direktifi ile cihaz takıldığında veya çıkarıldığında otomatik olarak script veya komut çalıştırılır. Ortam değişkenleri ile bağlam bilgisi script'e aktarılır.

RUN direktifi

RUN, kural eşleştiğinde çalıştırılacak programı belirtir. Program, udevd tarafından arka planda yürütülür. Dikkat: udevd zaman aşımına duyarlıdır; uzun süren işlemler için systemd service başlatılmalıdır.

/etc/udev/rules.d/90-hotplug.rules — RUN örnekleri
# Basit komut çalıştırma
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ACTION=="add", \
  RUN+="/usr/local/bin/sensor_connect.sh"

# Shell komutları (sh -c ile)
SUBSYSTEM=="tty", ACTION=="add", KERNEL=="ttyUSB*", \
  RUN+="/bin/sh -c 'echo %k >> /tmp/plugged_devices'"

# Cihaz çıkarılınca farklı script
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ACTION=="remove", \
  RUN+="/usr/local/bin/sensor_disconnect.sh"

# systemd servisi başlat (uzun işlemler için)
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ACTION=="add", \
  RUN+="/bin/systemctl start sensor-daemon.service"

# Birden fazla komut
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="1234", \
  RUN+="/usr/local/bin/init_device.sh", \
  RUN+="/bin/logger 'Custom USB device connected'"

Ortam değişkenleri: script'e bağlam aktarma

udevd, RUN script'ini çalıştırırken uevent özelliklerini ortam değişkeni olarak aktarır. Script içinde $ACTION, $DEVNAME, $ID_VENDOR_ID gibi değişkenler kullanılabilir.

udev rule — ENV koyma/okuma
# Kural içinde ENV set et — script'ten erişilir
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", \
  ENV{DEVICE_TYPE}="cp2102_uart", \
  ENV{BAUD_RATE}="115200", \
  RUN+="/usr/local/bin/configure_uart.sh"
bash — /usr/local/bin/configure_uart.sh
#!/bin/bash
# udev tarafından çalıştırılan hotplug script

# udevd'nin aktardığı ortam değişkenleri
DEVICE="$DEVNAME"          # /dev/ttyUSB0
ACTION_TYPE="$ACTION"      # add / remove
VENDOR="$ID_VENDOR_ID"     # 10c4
PRODUCT="$ID_MODEL_ID"     # ea60
SERIAL="$ID_SERIAL_SHORT"  # AB12CD34
BAUD="$BAUD_RATE"          # 115200 (kural içinde set edildi)

# Log yaz
logger -t udev-hotplug "Action=$ACTION_TYPE Device=$DEVICE Vendor=$VENDOR"

if [ "$ACTION_TYPE" = "add" ]; then
    # Baud rate ayarla
    stty -F "$DEVICE" "$BAUD"

    # Servise bildir (FIFO, socket veya dosya üzerinden)
    echo "CONNECTED:$DEVICE:$SERIAL" > /run/sensor/event_fifo

    # Lock dosyası oluştur
    touch "/run/sensor/device_${SERIAL}.lock"
fi

if [ "$ACTION_TYPE" = "remove" ]; then
    rm -f "/run/sensor/device_${SERIAL}.lock"
    echo "DISCONNECTED:$DEVICE:$SERIAL" > /run/sensor/event_fifo
fi

ENV değişkenini sonraki kuralda okuma

udev rule — ENV zinciri
# İlk kural: cihaz türünü belirle
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  ENV{MY_UART_TYPE}="ftdi"

SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  ENV{MY_UART_TYPE}="cp210x"

# İkinci kural: türe göre farklı grup ata
SUBSYSTEM=="tty", ENV{MY_UART_TYPE}=="ftdi", GROUP="ftdi_users"
SUBSYSTEM=="tty", ENV{MY_UART_TYPE}=="cp210x", GROUP="sensor_users"

# Üçüncü kural: hepsini ortak dizine symlink et
SUBSYSTEM=="tty", ENV{MY_UART_TYPE}!="", \
  SYMLINK+="uart/%E{MY_UART_TYPE}/%k"

Bu bölümde

  • RUN+="/path/script": kural eşleştiğinde çalıştırılır; add/remove eylemine göre farklılaştırılabilir
  • Uzun işlemler için: RUN+="/bin/systemctl start service" — udevd zaman aşımına uğramaz
  • Script içinde $DEVNAME, $ACTION, $ID_VENDOR_ID: udevd'nin aktardığı ortam değişkenleri
  • ENV{KEY}="value": kural zincirinde sonraki kurallara bağlam aktarımı

05 Seri port ve CAN kuralları

Embedded geliştirmenin temel ihtiyaçları: USB-seri dönüştürücüler için kalıcı isimler, CAN arayüzleri için otomatik başlatma ve doğru grup izinleri.

USB-seri dönüştürücü kuralları

/etc/udev/rules.d/99-usb-serial.rules
# CP2102 (Silicon Labs) — sensor bağlantısı
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  ATTRS{serial}=="0001", \
  SYMLINK+="sensor_uart", \
  GROUP="dialout", \
  MODE="0660"

# FTDI FT232 — debug konsolu
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  SYMLINK+="debug_uart", \
  GROUP="dialout", \
  MODE="0660"

# CH340/CH341 (ucuz USB-UART) — programlama portu
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", \
  SYMLINK+="prog_uart", \
  GROUP="dialout", \
  MODE="0666"

# PL2303 (Prolific) — GPS modülü
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", \
  SYMLINK+="gps_uart", \
  GROUP="dialout", \
  MODE="0660", \
  RUN+="/usr/local/bin/init_gps.sh"

CAN arayüzü kuralları

USB-CAN adaptörleri (slcan, gs_usb driver'ı kullanan Canable/PCAN gibi) Linux'ta özel yapılandırma gerektirir. udev kuralı hem sembolik link hem de otomatik ip link set up yapabilir.

/etc/udev/rules.d/99-can.rules — CAN arayüzleri
# gs_usb driver (CANable, Canable Pro, STM32 bazlı CAN adaptörleri)
SUBSYSTEM=="net", ACTION=="add", \
  ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="606f", \
  NAME="can_vehicle", \
  RUN+="/sbin/ip link set can_vehicle type can bitrate 500000"
RUN+="/sbin/ip link set can_vehicle up"

# slcan (Serial Line CAN — UART üzerinden)
SUBSYSTEM=="tty", ACTION=="add", \
  ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  ATTRS{interface}=="SLCAN", \
  SYMLINK+="can_serial", \
  RUN+="/usr/local/bin/slcan_init.sh"

# KVASER USB CAN
SUBSYSTEM=="net", ACTION=="add", \
  ATTRS{idVendor}=="0bfd", \
  ENV{KVASER_CHANNEL}="%n", \
  NAME="kvcan%n"
bash — /usr/local/bin/slcan_init.sh
#!/bin/bash
# slcan: seri port üzerinden CAN arayüzü başlatma
UART_DEV="$DEVNAME"
CAN_IFACE="slcan0"
BITRATE="500000"

# slcand daemon'u başlat
/usr/bin/slcand -o -s6 -t hw -S "$BITRATE" "$UART_DEV" "$CAN_IFACE"

# Kısa bekleme
sleep 0.5

# Arayüzü aç
/sbin/ip link set "$CAN_IFACE" up

logger -t udev-can "slcan başlatıldı: $UART_DEV -> $CAN_IFACE"

OWNER, GROUP ve MODE

udev rule — izin yönetimi
# Grup izinleri — kullanıcıyı gruba eklemek yeterli
SUBSYSTEM=="tty", KERNEL=="ttyUSB*", \
  GROUP="dialout", MODE="0660"

# Tüm kullanıcılara izin (geliştirme ortamı için)
SUBSYSTEM=="tty", KERNEL=="ttyUSB*", \
  MODE="0666"

# Belirli kullanıcıya sahiplik
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", \
  OWNER="ubuntu", GROUP="ubuntu", MODE="0660"

# Kullanıcıyı dialout grubuna ekle (kural değişikliği gerektirmez)
sudo usermod -aG dialout $USER
# Etkinleştirmek için oturumu yenile veya:
newgrp dialout

Bu bölümde

  • CP2102/FTDI/CH340: ATTRS{idVendor}+ATTRS{idProduct} ile kalıcı SYMLINK ve GROUP ataması
  • gs_usb CAN: NAME= ile sabit arayüz adı, RUN= ile bitrate ayarı ve ip link up
  • slcan: UART'ı CAN arayüzüne dönüştürme script'i; slcand daemon ile
  • GROUP="dialout" + MODE="0660": kullanıcıyı gruba eklemek yeterli, sudo gerekmez

06 Kural debug ve yeniden yükleme

udev kurallarını test etmek, hata ayıklamak ve yeniden yüklemek için gerekli komutlar — sistemi yeniden başlatmadan kural geliştirme döngüsü.

udevadm test ile kural simülasyonu

udevadm test, gerçekten bir cihaz takılmadan kuralların nasıl çalışacağını simüle eder. /dev'de değişiklik yapmaz ancak hangi kuralların eşleştiğini ve hangi atamaların yapıldığını gösterir.

bash — udevadm test
# Önce sysfs yolunu bul
udevadm info -q path -n /dev/ttyUSB0
# /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0

# Kural simülasyonu (gerçek değişiklik yapmaz)
udevadm test /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0

# Örnek çıktı:
# Reading rules file: /lib/udev/rules.d/60-serial.rules
# Reading rules file: /etc/udev/rules.d/99-usb-serial.rules
# LINK '/dev/sensor_uart' /dev/ttyUSB0
# GROUP 'dialout' /dev/ttyUSB0
# MODE '0660' /dev/ttyUSB0
# RUN '/usr/local/bin/sensor_connect.sh'

# Kural eşleşmelerini detaylı göster
udevadm test --action=add /devices/.../ttyUSB0/tty/ttyUSB0 2>&1 | grep -E "IMPORT|RUN|LINK|GROUP"

Kuralları yeniden yükleme

bash — kural yenileme
# Kural dosyalarını yeniden yükle (udevd'ye sinyal gönder)
sudo udevadm control --reload-rules

# Kısaltma
sudo udevadm control -R

# Yeniden yükle + halihazırda bağlı cihazlara kuralları tekrar uygula
sudo udevadm control --reload-rules && sudo udevadm trigger

# Yalnızca belirli subsystem için tetikle
sudo udevadm trigger --subsystem-match=tty
sudo udevadm trigger --subsystem-match=usb

# Belirli cihaz için tetikle
sudo udevadm trigger --sysname-match=ttyUSB0

# Tamamlanmasını bekle
sudo udevadm settle

udevadm ile hata ayıklama

bash — debug teknikleri
# udevd'yi debug modunda çalıştır (verbose)
sudo udevadm control --log-priority=debug
journalctl -f -u systemd-udevd

# Belirli bir kural dosyasını syntax kontrol
udevadm verify /etc/udev/rules.d/99-custom.rules

# Cihaz için hangi kuralların eşleştiğini tam log ile gör
sudo udevadm test --action=add \
  $(udevadm info -q path -n /dev/ttyUSB0) 2>&1

# RUN script'inin çıktısını görmek için log ekle
# Script içine: logger -t my-udev-script "debug message"
journalctl -t my-udev-script -f

# Tüm cihaz özelliklerini dump et
udevadm info --export-db | grep -A5 "ttyUSB0"

Yaygın hatalar ve çözümleri

HataSebepÇözüm
Kural eşleşmiyorATTRS{} yanlış hiyerarşide--attribute-walk ile doğru seviyeyi bul
Symlink oluşmuyorSYMLINK yerine NAME kullanılmışSYMLINK+= kullan
Script çalışmıyorÇalıştırma izni yokchmod +x /path/script.sh
Script çalışmıyorShebang eksik veya yanlış#!/bin/bash satırını kontrol et
Script timeoutUzun süren işlemsystemctl start service ile at
Kural trigger etmiyorudevd kuralları yüklenmemişudevadm control --reload-rules

Bu bölümde

  • udevadm test [sysfs-path]: gerçek değişiklik olmadan kural simülasyonu
  • udevadm control --reload-rules: kural dosyaları değiştikten sonra yenile
  • udevadm trigger: halihazırda bağlı cihazlara kuralları yeniden uygula
  • --log-priority=debug + journalctl: udevd'nin tam log akışını izle

07 udev ve systemd entegrasyonu

systemd, udev'i kendi cihaz yönetim altyapısına entegre eder. Device unit'ler, conditional service başlatma ve socket activation ile donanım-tetiklemeli servisler oluşturulur.

Device unit (.device)

systemd, udev'in oluşturduğu her cihaz için otomatik olarak bir .device unit oluşturur. Bu unit'in adı, sysfs yolundan türetilir. Diğer unit'ler bu device unit'e bağlı hale getirilebilir.

bash — device unit bilgisi
# Device unit adını bul
systemctl list-units --type=device | grep ttyUSB
# dev-ttyUSB0.device  loaded active plugged  /dev/ttyUSB0

# Device unit detayı
systemctl status dev-ttyUSB0.device

# Adlandırma kuralı: /dev/ttyUSB0 → dev-ttyUSB0.device
#                   /dev/sda1    → dev-sda1.device
# (/ yerine - kullanılır, sonuna .device eklenir)

SYSTEMD_WANTS: cihaz takılınca servis başlat

udev kuralı içinde ENV{SYSTEMD_WANTS} ile cihaz takıldığında otomatik olarak bir systemd servisi başlatılabilir. Bu yöntem RUN+ ile script çalıştırmaktan daha güvenilirdir çünkü systemd servis yaşam döngüsünü yönetir.

/etc/udev/rules.d/90-sensor.rules — SYSTEMD_WANTS
# Cihaz takılınca sensor-daemon servisi başlat
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
  ACTION=="add", \
  ENV{SYSTEMD_WANTS}="sensor-daemon@%k.service"

# Template service: sensor-daemon@ttyUSB0.service
# %k = kernel name (ttyUSB0)
/etc/systemd/system/sensor-daemon@.service
[Unit]
Description=Sensor Daemon for %I
BindsTo=dev-%i.device
After=dev-%i.device

[Service]
Type=simple
ExecStart=/usr/local/bin/sensor-daemon /dev/%I
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

ConditionPathExists ile bağımlılık

systemd service — ConditionPathExists
[Unit]
Description=GPS Logger Service
# /dev/gps_uart mevcut değilse başlama
ConditionPathExists=/dev/gps_uart
After=dev-gps_uart.device
Requires=dev-gps_uart.device

[Service]
ExecStart=/usr/local/bin/gps-logger --device=/dev/gps_uart
Restart=on-failure

[Install]
WantedBy=multi-user.target

Socket activation ile USB cihaz bekleme

bash — socket activation + device dependency
# systemd-path ile belirli bir dosya/cihaz görününce servis başlat
# /etc/systemd/system/sensor-watch.path
cat <<'EOF' | sudo tee /etc/systemd/system/sensor-watch.path
[Unit]
Description=Watch for sensor UART

[Path]
PathExists=/dev/sensor_uart
Unit=sensor-daemon.service

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable sensor-watch.path
sudo systemctl start  sensor-watch.path

# /dev/sensor_uart oluştuğunda sensor-daemon.service otomatik başlar

Bu bölümde

  • /dev/ttyUSB0 → dev-ttyUSB0.device: systemd her cihaz için otomatik .device unit oluşturur
  • ENV{SYSTEMD_WANTS}: udev kuralından template servis başlatmanın güvenilir yolu
  • BindsTo=dev-%i.device: cihaz çıkarılınca servis de durur
  • PathExists= unit: /dev/sensor_uart gibi bir yol oluşunca servis başlatır

08 Pratik: özel USB cihazı ve embedded alternatifler

Özel bir USB cihazı için uçtan uca kural yazımı, grup yetkilendirmesi ve kaynak kısıtlı embedded sistemlerde udev alternatifleri: eudev ve mdev.

Özel USB cihazı için tam kural seti

bash — vendor/product ID öğrenme
# lsusb ile tüm USB cihazları listele
lsusb
# Bus 001 Device 004: ID 1234:5678 MyCompany Custom Device

# Detaylı bilgi
lsusb -v -d 1234:5678

# udevadm ile tam özellik listesi
udevadm info --attribute-walk --name=/dev/ttyUSB0 | \
  grep -E "idVendor|idProduct|serial|manufacturer"
/etc/udev/rules.d/99-mydevice.rules — tam kural seti
# Özel USB cihazı: vendor=1234, product=5678
# Adım 1: Cihazı tanımla, ENV ata
SUBSYSTEM=="tty", \
  ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", \
  ENV{MY_DEVICE}="1"

# Adım 2: Seri numarasına göre farklılaştır
SUBSYSTEM=="tty", ENV{MY_DEVICE}=="1", \
  ATTRS{serial}=="SN001", \
  SYMLINK+="mydevice/primary", \
  ENV{MY_DEVICE_ROLE}="primary"

SUBSYSTEM=="tty", ENV{MY_DEVICE}=="1", \
  ATTRS{serial}=="SN002", \
  SYMLINK+="mydevice/secondary", \
  ENV{MY_DEVICE_ROLE}="secondary"

# Adım 3: Ortak izinler (seri numarası ne olursa olsun)
SUBSYSTEM=="tty", ENV{MY_DEVICE}=="1", \
  GROUP="mydevice_group", \
  MODE="0660"

# Adım 4: Bağlantı bildirimi
SUBSYSTEM=="tty", ENV{MY_DEVICE}=="1", ACTION=="add", \
  RUN+="/usr/local/bin/mydevice-init.sh"

SUBSYSTEM=="tty", ENV{MY_DEVICE}=="1", ACTION=="remove", \
  RUN+="/usr/local/bin/mydevice-cleanup.sh"
bash — grup oluşturma ve kullanıcı ekleme
# Grup oluştur
sudo groupadd mydevice_group

# Kullanıcıyı gruba ekle
sudo usermod -aG mydevice_group $USER

# Kuralı yükle ve tetikle
sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=tty

# Test et
ls -la /dev/mydevice/
# lrwxrwxrwx root mydevice_group primary   -> ../../ttyUSB0
# lrwxrwxrwx root mydevice_group secondary -> ../../ttyUSB1

Embedded alternatifler: eudev ve mdev

Tam udev (systemd-udevd) gömülü sistemler için fazla ağır olabilir. Buildroot ve OpenWrt gibi dağıtımlar daha hafif alternatifler sunar.

AraçBoyutKural uyumluluğuKullanım
systemd-udevd~500KB + depsTam udev uyumluDesktop/server Linux
eudev~200KBTam udev uyumluSystemd olmayan embedded
mdev (busybox)~20KBBasit, sınırlıMinimal OpenWrt, initramfs
mdevd~30KBmdev benzeris6-init, runit tabanlı
bash — Buildroot'ta eudev etkinleştirme
# Buildroot menuconfig
make menuconfig
# System configuration → /dev management → Dynamic using eudev

# eudev kural dosyaları: normal udev kurallarıyla aynı format
# /etc/udev/rules.d/ dizinine koyulur
/etc/mdev.conf — mdev kural formatı
# mdev kuralları farklı formattadır:
# regex  owner:group  octal_mode  [=|>|!symlink]  [cmd]

# ttyUSB cihazları: root:dialout, 0660
ttyUSB[0-9]+    root:dialout    0660

# Script tetikleme ($MDEV ortam değişkeni cihaz adını içerir)
ttyUSB[0-9]+    root:dialout    0660    */usr/local/bin/uart_hotplug.sh

# Kural sözdizimi: * = her iki yönde, @ = eklenince, $ = kaldırılınca
ttyUSB[0-9]+    root:dialout    0660    @/bin/sh -c "echo $MDEV connected"

# mdev'i hotplug handler olarak kaydet
echo /sbin/mdev > /proc/sys/kernel/hotplug

Bu bölümde

  • Tam kural seti: ENV zinciri → seri no. ayrımı → ortak izin → add/remove script
  • groupadd + usermod -aG: grup temelli yetkilendirme; sudo gerektirmez
  • eudev: systemd olmadan tam udev kural uyumluluğu; Buildroot'ta kolayca etkinleştirilebilir
  • mdev (busybox): minimal /etc/mdev.conf formatı; ~20KB, initramfs için ideal