sysfs是什么??


來源:https://blog.csdn.net/qq_36412526/article/details/83751520

第一次接觸:sysfs, 這里記錄過程:

 

原文:Documenttation/filesystems/sysfs.txt sysfs-用於導出內核對象(kobject)的文件系統

sysfs是什么: sysfs是一個基於ram的內存文件系統(ramfs)。它提供了一種方法用於導出內核數據結構,屬性,以及它們兩者之間的聯系到用戶空間。 sysfs和kobject結構關聯。參考Documenttation/kobject.txt獲取更多kobject信息。

sysfs用法: 如果定義了CONFIG_SYSFS sysfs就會編譯進內核。可以用以下命令掛載: mount -t sysfs sysfs /sys

目錄創建 每個注冊在系統的kobject都會在sysfs創建一個目錄。創建的目錄位於kobject的parent目錄下,展現了kobject之間的內部層級關系。sysfs頂層的目錄表示共同的祖先目錄;比如object歸屬的subsystems。 sysfs內部保存了一個指向kobject的指針。過去kobject指針被sysfs直接用來處理引用次數在文件打開或關閉的時候。現在的sysfs實現了kobject的引用次數只能被函數sysfs_schedule_callback()修改。

屬性(attribute) attribute能為kobject導出普通文件的格式。sysfs用文件I/O操作來操作attribute定義的函數,提供了一種讀寫內核屬性的途徑。 attributes應該是ASCII文本文件,最好每個文件保存一個值。有人注意到一個文件保存一個值顯得效率不高,所以保存同類型的一組值也是普遍認可的。 混合類型、保存多行數據,且比較花哨的數據是不贊成的。這樣做會讓你在公眾面前丟臉且你的代碼會被毫無征兆地重寫。 attribute定義如下

struct attribute{
	char *name;
	struct module *owner;
	mode_t mode;
	};

int sysfs_create_file(struct kobject *kobj,const struct attribute *attr);
void sysfs_remove_file(struct kobject *kobj,const struct attribute *attr);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

空的attribute不含讀寫attribute的函數。子系統(subsystems)鼓勵定義自己的attribute結構體和包裝函數用於添加和刪除object的attribute。

舉例來說,設備驅動模型定義了device_attribute的結構體如下:

struct device_attribute{
	struct attribute attr;
	ssize_t (*show)(struct device *dev,struct device_attribute *attr,char *buf);
	ssize_t (*strore)(struct device *dev,struct device_attibute *attr,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 *);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

它同時定義了輔助宏來定義設備attributes:

#define DEVICE_ATTR(_name,_mode,_show,_store)\
struct device_attribute dev_attr_##_name =__ATTR(_name,_mode,_show,_store)
  • 1
  • 2

舉例,聲明

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

等效於:

static struct device_attribute dev_attr_foo = 
	.attr = {
	.name = "foo",
	.mode = S_IWUSR | S_IRUGO,
	.show = show_foo,
	.store = store_foo,
	},
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

subsystem相關的callbacks

當subsystem定義了新的attribute類型,它必須實現一組自己的sysfs操作函數用於sysfs讀寫調用.

struct sysfs_ops {
        ssize_t (*show)(struct kobject *, struct attribute *, char *);
        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
};
  • 1
  • 2
  • 3
  • 4

[subsystems 應該已經定義了一個kobj_type結構體作為類型描述符,它保存了sysfs_ops指針.詳情參考kobject文檔.]

當讀寫文件的時候,sysfs調用kobj_type的相應方法函數.該函數隨后轉換kobject和attribute指針到相應的指針類型,然后調用相應的方法函數. 舉例:

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

讀/寫 attribute 數據 為了讀寫attribute,在聲明attribute的時候必須定義show()或store()函數.這些函數應該盡量簡單如device attribute定義的函數:

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);
  • 1
  • 2
  • 3

IOW,這些函數只需要一個object,attribute,buffer作為參數. sysfs分配了一個buffer(PAGE_SIZE字節)並把它傳入這些函數.sysfs會在每次讀寫的時候調用這些函數.要求這些函數實現以下功能:

-on read(2),show()函數會填充整個buffer.一個attribute應該只導出一個值,或一組相似的值,因此這個效率不高. 這 使用戶空間可以部分讀且隨意向后搜索.如果用戶空間向前搜索到0或使用pread(2)在0位置讀,show()函數會被再次調用        並填充整個buffer.

-on write(2),sysfs在首次寫的時候傳遞整個buffer,sysfs然后傳遞整個buffer到store()函數. 當寫sysfs文件時,用戶空間先讀整個文件,然后修改,最后再寫回文件. attribute函數讀和寫的時候應該使用同一個buffer.

其他注意點:

-寫操作將導致show()函數被再次調用,不管當前文件位置在哪里.

-buffer的長度固定為PAGE_SIZE.在i386,長度為4096

-show()函數返回輸出到buffer的字節數.也就是scnprintf()函數的返回值

-show()函數應該使用scnprintf()函數

-store()函數應該返回buffer占用的字節數,如果整個buffer都被占用,應該返回count參數

-show()和store()函數可以返回錯誤,如果有錯誤的值,確保返回一個錯誤

-函數的參數object將被保存在內存中通過它的引用計數器計數.但object代表的實體不一定在內存中,如果有必要,要有方法檢測.

一個設備屬性的簡單的實現如下:

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);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

(注意,實際上設備的名字不能在用戶空間更改.)

頂層目錄安排

sysfs目錄展現了內核數據結構之間的關系. 頂層目錄如下: block/ bus/ class/ dev/ devices/ firmware/ net/ fs/

devices/ 一個文件系統代表了設備樹(device tree).直接映射到內核的設備樹,它是device結構體的層級關系. bus/ 內核的多種總線類型的目錄布局.每個總線目錄含兩個子目錄: devices/ 系統里發現的每個設備的符號連接指向root/目錄下的 device目錄 drivers/ 特定總線上設備加載的驅動目錄 fs/  某些文件系統的目錄.每個文件系統如果要導出attributes必須要創建它自己的目錄層級到fs/下 dev/ 里面有兩個目錄char/和block/.這兩個目錄里有命名為:的符號連接.這些符號連接到sysfs目錄下對應的device./sys/dev提供了一個快速的方式來查找sysfs中stat操作的結果

更多關於驅動模型的特征信息可以參考Documentation/driver-model/.

Current Interfaces

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);
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Declaring:

DEVICE_ATTR(_name, _mode, _show, _store);
  • 1

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);

  • 1
  • 2
  • 3
  • 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);
};
  • 1
  • 2
  • 3
  • 4
  • 5

Declaring:

BUS_ATTR(_name, _mode, _show, _store)
  • 1

Creation/Removal:

int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);

  • 1
  • 2
  • 3
  • 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);
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Declaring:

DRIVER_ATTR(_name, _mode, _show, _store)

  • 1
  • 2

Creation/Removal:

int driver_create_file(struct device_driver *, const struct driver_attribute *);
void driver_remove_file(struct device_driver *, const struct driver_attribute *);

  • 1
  • 2
  • 3

文檔

sysfs目錄結構和每個目錄的attribute定義了一種ABI在內核和用戶空間.對於任何ABI,穩定和正確的文檔是很重要的.所有新的sysfs attributes必須配上文檔.參考Documentation/ABI/README閱讀更多的信息.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM