O Sistema de Arquivos sysfs no Kernel Linux

O sysfs é um sistema de arquivos em memória (baseado em ramfs) integrado ao kernel Linux, projetado para expor hierarquias de objetos internos — especialmente instâncias de kobject — para o espaço de usuário. Ele não armazena dados em disco, mas sim reflete dinamicamente a estrutura de objetos do kernel, como dispositivos, barramentos, drivers e subsistemas, permitindo inspeção e, em alguns casos, modificação controlada de atributos.

Montagem e Estrutura Básica

Quando habilitado via configuração CONFIG_SYSFS=y, o sysfs pode ser montado manualmente:

mount -t sysfs sysfs /sys

Seu ponto de montagem padrão é /sys. Cada kobject registrado no kernel gera automaticamente um diretório sob /sys, organizado conforme sua relação hierárquica de pai-filho. Por exemplo:

  • /sys/devices/: representa a árvore física de dispositivos;
  • /sys/bus/: agrupa dispositivos por tipo de barramento (PCI, USB etc.), com subdiretórios devices/ (links simbólicos para /sys/devices) e drivers/ (módulos ativos);
  • /sys/class/: agrupa dispositivos por funcionalidade lógica (ex: net/, graphics/);
  • /sys/dev/: fornece acesso rápido a dispositivos via major:minor (ex: /sys/dev/block/8:0 → link para /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda).

Atributos e Interface de I/O

Os atributos são arquivos regulaers dentro desses diretórios, que permitem leitura (show) ou escrita (store) de propriedades do objeto subjacente. Eles seguem uma interface padronizada baseada em estruturas como struct attribute:

struct attribute {
    const char *name;
    umode_t     mode;
    struct module *owner;
};

Subsistemas definem wrappers especializados — por exemplo, struct device_attribute para dispositivos:

struct device_attribute {
    struct attribute attr;
    ssize_t (*show)(struct device *, struct device_attribute *, char *);
    ssize_t (*store)(struct device *, struct device_attribute *, const char *, size_t);
};

#define DEVICE_ATTR_RW(_name) \
    struct device_attribute dev_attr_##_name = __ATTR_RW(_name)

// Uso típico:
static ssize_t led_brightness_show(struct device *dev,
                                   struct device_attribute *attr,
                                   char *buf) {
    struct led_classdev *led_cdev = dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%d\n", led_cdev->brightness);
}

static ssize_t led_brightness_store(struct device *dev,
                                    struct device_attribute *attr,
                                    const char *buf, size_t count) {
    struct led_classdev *led_cdev = dev_get_drvdata(dev);
    unsigned long val;
    if (kstrtoul(buf, 0, &val) == 0 && val <= LED_FULL)
        led_set_brightness(led_cdev, val);
    return count;
}

static DEVICE_ATTR_RW(brightness);

Essa abordagem garante tipagem segura, encapsulamento e reutilização. Funções show devem usar scnprintf() para evitar estouros de buffer; store deve retornar count se bem-sucedida, ou um valor negaitvo em caso de erro.

Operações Internas

O sysfs delega operações de leitura/escrita a funções de callback definidas no struct kobj_type associado ao kobject. Essas callbacks recebem ponteiros genéricos e usam container_of() para recuperação de tipo:

static ssize_t device_attr_read(struct kobject *kobj,
                                struct attribute *attr,
                                char *buf) {
    struct device_attribute *dev_attr = to_dev_attr(attr);
    struct device *dev = container_of(kobj, struct device, kobj);
    return dev_attr->show(dev, dev_attr, buf);
}

Importante: cada operação read() ou write() aciona a função correspondente inteiramente — não há cache parcial nem suporte nativo a seeks arbitrários. O buffer fornecido tem tamanho fixo de PAGE_SIZE (geralmente 4 KiB).

Outras Interfaces de Atributo

Além de dispositivos, outros domínios oferecem interfaces análogas:

  • Barramentos: struct bus_attribute, macros BUS_ATTR_RW();
  • Drivers: struct driver_attribute, macros DRIVER_ATTR_RW();
  • Clases: struct class_attribute.

Todas compartilham o mesmo modelo de operações, mas diferenciam os tipos de objeto-alvo e os protótipos das funções de callback.

Considerações de Estabilidade e Documentação

O conteúdo de /sys forma parte de uma ABI entre kernel e espaço de usuário. Alterações em nomes de arquivos, formatos de dados ou semântica exigem justificativa técnica rigorosa e atualização da documentação em Documentation/ABI/. Novos atributos devem incluir entradas descritivas em Documentation/ABI/testing/, explicando propósito, formato esperado, permissões e restrições de uso.

Tags: linux-kernel sysfs kobject device-driver linux-system-programming

Publicado em 10-6 08:18