DM框架-2 buses

本文详细介绍了Linux系统中的总线(bus)概念,包括其在处理器与I/O设备间通信的作用,以及在LinuxDeviceModel中的结构(structbus_type)。文章还涵盖了注册、操作和热插拔功能,以及如何使用sysfs进行设备属性管理和bus_attribute的定义。
摘要由CSDN通过智能技术生成

A bus is a communication channel between the processor and an input/output device. To ensure that the model is generic, all input/output devices are connected to the processor via such a bus (even if it can be a virtual one without a physical hardware correspondent).

When adding a system bus, it will appear in the sysfs file system in /sys/bus. As with kobjects, buses can be organized into hierarchies and will be represented in sysfs.

In the Linux Device Model, a bus is represented by the structure struct bus_type:

struct bus_type {
        const char              *name;
        const char              *dev_name;
        struct device           *dev_root;
        struct bus_attribute    *bus_attrs;
        struct device_attribute *dev_attrs;
        struct driver_attribute *drv_attrs;
        struct subsys_private *p;

        int             (*match)(struct device *dev, struct device_driver *drv);
        int             (*uevent)(struct device *dev, struct kobj_uevent_env *env);
        int             (*probe)(struct device *dev);
        int             (*remove)(struct device *dev);
        //...
};

It can be noticed that a bus has a name, lists of default attributes, a number of specific functions, and the driver’s private data. The uevent function (formerly hotplug) is used with hotplug devices.

Bus operations are the registration, the implementation of the operations described in the struct bus_type structure and the iteration and inspection of the devices connected to the bus.

A bus is registered using bus_register(), and unregistered using bus_unregister().

Implementation example:

#include <linux/device.h>
/* mybus.c */

//bus type
struct bus_type my_bus_type = {
  .name   = "mybus",
  .match  = my_match,
  .uevent = my_uevent,
};

static int __init my_bus_init(void)
{
  int err;

  //...
  err = bus_register(&my_bus_type);
  if (err)
    return err;
  //...
}

static void __exit my_bus_exit(void)
{
  //...
  bus_unregister(&my_bus_type);
  //...
}

The functions that will normally be initialized within a bus_type structure are match and uevent:

#include <linux/device.h>
#include <linux/string.h>
/* mybus.c */

// match devices to drivers; just do a simple name test
static int my_match(struct device *dev, struct device_driver *driver)
{
  return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
}

// respond to hotplug user events; add environment variable DEV_NAME
static int my_uevent(struct device *dev, struct kobj_uevent_env *env)
{
  add_uevent_var(env, "DEV_NAME=%s", dev_name(dev));
  return 0;
}

The match function is used when a new device or a new driver is added to the bus. Its role is to make a comparison between the device ID and the driver ID. The uevent function is called before generating a hotplug in user-space and has the role of adding environment variables.

Other possible operations on a bus are iterating over the drivers or devices attached to it. Although we can not directly access them (lists of drivers and devices being stored in the private data of the driver, the subsys_private *p field), these can be iterated using the bus_for_each_dev and bus_for_each_drv macros.

The Linux Device Model interface allows you to create attributes for the associated objects. These attributes will have a corresponding file in the bus subdirectory in sysfs. The attributes associated with a bus are described by the bus_attribute structure :

struct bus_attribute {
         struct attribute        attr;
         ssize_t (*show)(struct bus_type *, char *buf);
         ssize_t (*store)(struct bus_type *, const char *buf, size_t count);
};

Typically, an attribute is defined by the BUS_ATTR macro. The bus_create_file() and bus_remove_file() functions can be used to add/delete an attribute within the bus structure.

An example of defining an attribute for my_bus is shown below:

/* mybus.c */

#define MY_BUS_DESCR     "SO2 rules forever"

// export a simple bus attribute
static ssize_t my_show_bus_descr(struct bus_type *bus, char *buf)
{
        return snprintf(buf, PAGE_SIZE, "%s\n", MY_BUS_DESCR);
}

/*
 * define attribute - attribute name is descr;
 * full name is bus_attr_descr;
 * sysfs entry should be /sys/bus/mybus/descr
 */
BUS_ATTR(descr, 0444, my_show_bus_descr, NULL);

// specify attribute - in module init function
static int __init my_bus_init(void)
{
        int err;
        //...
        err = bus_create_file(&my_bus_type, &bus_attr_descr);
        if (err) {
                /* handle error */
        }
        //...
}

static void __exit my_bus_exit(void)
{
        //...
        bus_remove_file(&my_bus_type, &bus_attr_descr);
        //...
}

The bus is represented by both a bus_type object and a device object, as we will see later (the bus is also a device).
下回 Devices

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值