翻譯sysfs.txt

sysfs是一個內存文件系統,他提供了內核與用戶之間的數據屬性和連接交互,sysfs與kobject聯繫緊密。


內核編譯的時候要 CONFIG_SYSFS

 mount -t sysfs sysfs /sys 


每一個註冊的kobject都有一個目錄在sysfs,這個目錄地址在kobj的父對象目錄下,表徵爲層級,頂層目錄表現爲最高層級。


sysfs_dirent對象下面有一個指向kobj的指針,這個指針之前是用來作引用計數用的,現如今引用計數只被sysfs_schedule_callback()修改。


屬性被當做普通文件形式暴露出來。可以通過普通文件io讀寫內核屬性。


屬性應該是asc碼 txt文件,最好一個文件只有一個值,明顯這種機制不夠用,所以也允許多個值的情況。


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

};

int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); 

void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); 

一個光的屬性不包含讀寫函數,子系統需要自己分裝。

例如:

struct device_attribute { struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); 

ssize_t (*store)(struct device *dev, struct device_attribute *attr,

 const char *buf, size_t count);

 };


int device_create_file(struct device *, const struct device_attribute *); 

void device_remove_file(struct device *, const struct device_attribute *); 


It also defines this helper for defining device attributes: 
#define DEVICE_ATTR(_name, _mode, _show, _store) \ 

struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)


For example, declaring


static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); 

static struct device_attribute dev_attr_foo = { .attr= { .name = "foo",
.mode = S_IWUSR | S_IRUGO,
.show = show_foo,
.store = store_foo, }, 

};


當子系統定義了一個新的屬性類型,那他必須自己實現讀寫函數來調用打印和保存方法。

struct sysfs_ops { 

ssize_t (*show)(struct kobject *, struct attribute *, char *);
        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);

 };


子系統必須先定義kobj_type用來保存sysfs_ops指針。


當文件被讀或者寫了,sysfs會調用正確的方法。


#define to_dev(obj) container_of(obj, struct device, kobj) 

#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { 

struct device_attribute *dev_attr = to_dev_attr(attr);
        struct device *dev = to_dev(kobj);
        ssize_t ret = -EIO;
        if (dev_attr->show) 

ret = dev_attr->show(dev, dev_attr, buf); 

if (ret >= (ssize_t)PAGE_SIZE) { 

print_symbol("dev_attr_show: %s returned bad count\n", (unsigned long)dev_attr->show); 

}
        return ret;

 } 


爲了讀寫屬性,show和store函數必須被賦值,函數類型需要要與設備屬性的一樣

ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); 

ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); 


sysfs申請一個頁表來發送數據,每次讀寫只會調用一次底層函數,因此有如下的要求:

讀的時候,show函數必須要填滿整個buffer,回想一個屬性只能傳一個或者一組值,這樣效率纔不會太低。

這樣允許用戶空間 局部的讀和seek整個文件,如果用戶seek到0 或者pread 0 ,那麼show函數會再次調用,充填buffer


寫的時候,sysfs認爲整個buffer都有內容,傳遞整個buffer到store函數

寫的時候,先讀出來,修改 在寫回去

讀寫的buffer需要用同一個buffer


寫會使得show刷新不管文件pos

buffer永遠一個頁表大小

show函數會返回buffer字符的數量 ,實現是靠scnprintf函數

store函數返回不超過一個頁表大小數據,

讀寫會返回錯誤值


對象會被sysfs保存在內存中,實際對象是否存在不得而知。


A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); }
static ssize_t store_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { snprintf(dev->name, sizeof(dev->name), "%.*s", (int)min(count, sizeof(dev->name) - 1), buf); return count; }
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(Note that the real implementation doesn't allow userspace to set the name for a device.) 


sysfs目錄結構直接暴露了內核數據結構層級。

devices/ 表徵設備樹

bus/ bus類型 都有 

devices/   指向根目錄下的設備目錄
drivers/  包含 每個啓動的驅動

dev/  包含 char 和 block 裏面有 <major>:<minor>鏈接,指向設備目錄,stat 命令就是用的這裏


The following interface layers currently exist in sysfs:
- devices (include/linux/device.h)
---------------------------------- Structure:
struct device_attribute { struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); };
Declaring:
DEVICE_ATTR(_name, _mode, _show, _store);
Creation/Removal:
int device_create_file(struct device *dev, const struct device_attribute * attr); void device_remove_file(struct device *dev, const struct device_attribute * attr);
- bus drivers (include/linux/device.h)
-------------------------------------- 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); };
Declaring:
BUS_ATTR(_name, _mode, _show, _store)
Creation/Removal:
int bus_create_file(struct bus_type *, struct bus_attribute *); void bus_remove_file(struct bus_type *, struct bus_attribute *);
- device drivers (include/linux/device.h)
-----------------------------------------
Structure:
struct driver_attribute { struct attribute        attr;
        ssize_t (*show)(struct device_driver *, char * buf);
        ssize_t (*store)(struct device_driver *, const char * buf, size_t count); };
Declaring:
DRIVER_ATTR(_name, _mode, _show, _store)
Creation/Removal:
int driver_create_file(struct device_driver *, const struct driver_attribute *); void driver_remove_file(struct device_driver *, const struct driver_attribute *);



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章