diff --git a/Documentation/zh_CN/filesystems/sysfs.txt b/Documentation/zh_CN/filesystems/sysfs.txt new file mode 100644 index 0000000000000000000000000000000000000000..e230eaa331226901582f33d030af73499a9b9f5d --- /dev/null +++ b/Documentation/zh_CN/filesystems/sysfs.txt @@ -0,0 +1,372 @@ +Chinese translated version of Documentation/filesystems/sysfs.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Patrick Mochel <mochel@osdl.org> + Mike Murphy <mamurph@cs.clemson.edu> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/filesystems/sysfs.txt çš„ä¸æ–‡ç¿»è¯‘ + +如果想评论或更新本文的内容,请直接è”ç³»åŽŸæ–‡æ¡£çš„ç»´æŠ¤è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡ +äº¤æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘䏿–‡ç‰ˆç»´æŠ¤è€…求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻 +译å˜åœ¨é—®é¢˜ï¼Œè¯·è”ç³»ä¸æ–‡ç‰ˆç»´æŠ¤è€…。 +英文版维护者: Patrick Mochel <mochel@osdl.org> + Mike Murphy <mamurph@cs.clemson.edu> +䏿–‡ç‰ˆç»´æŠ¤è€…: 傅炜 Fu Wei <tekkamanninja@gmail.com> +䏿–‡ç‰ˆç¿»è¯‘者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +䏿–‡ç‰ˆæ ¡è¯‘者: 傅炜 Fu Wei <tekkamanninja@gmail.com> + + +ä»¥ä¸‹ä¸ºæ£æ–‡ +--------------------------------------------------------------------- +sysfs - ç”¨äºŽå¯¼å‡ºå†…æ ¸å¯¹è±¡(kobject)的文件系统 + +Patrick Mochel <mochel@osdl.org> +Mike Murphy <mamurph@cs.clemson.edu> + +修订: 16 August 2011 +原始版本: 10 January 2003 + + +sysfs 简介: +~~~~~~~~~~ + +sysfs 是一个最åˆåŸºäºŽ ramfs 且ä½äºŽå†…å˜çš„æ–‡ä»¶ç³»ç»Ÿã€‚它æä¾›å¯¼å‡ºå†…æ ¸ +æ•°æ®ç»“æž„åŠå…¶å±žæ€§ï¼Œä»¥åŠå®ƒä»¬ä¹‹é—´çš„å…³è”到用户空间的方法。 + +sysfs 始终与 kobject 的底层结构紧密相关。请阅读 +Documentation/kobject.txt 文档以获得更多关于 kobject 接å£çš„ +ä¿¡æ¯ã€‚ + + +使用 sysfs +~~~~~~~~~~~ + +åªè¦å†…æ ¸é…ç½®ä¸å®šä¹‰äº† CONFIG_SYSFS ,sysfs æ€»æ˜¯è¢«ç¼–è¯‘è¿›å†…æ ¸ã€‚ä½ å¯ +通过以下命令挂载它: + + mount -t sysfs sysfs /sys + + +创建目录 +~~~~~~~~ + +任何 kobject åœ¨ç³»ç»Ÿä¸æ³¨å†Œï¼Œå°±ä¼šæœ‰ä¸€ä¸ªç›®å½•在 sysfs ä¸è¢«åˆ›å»ºã€‚这个 +目录是作为该 kobject 的父对象所在目录的åç›®å½•åˆ›å»ºçš„ï¼Œä»¥å‡†ç¡®åœ°ä¼ é€’ +å†…æ ¸çš„å¯¹è±¡å±‚æ¬¡åˆ°ç”¨æˆ·ç©ºé—´ã€‚sysfs ä¸çš„顶层目录代表ç€å†…æ ¸å¯¹è±¡å±‚æ¬¡çš„ +å…±åŒç¥–先;例如:æŸäº›å¯¹è±¡å±žäºŽæŸä¸ªå系统。 + +Sysfs 在与其目录关è”çš„ sysfs_dirent 对象ä¸å†…部ä¿å˜ä¸€ä¸ªæŒ‡å‘实现 +目录的 kobject 的指针。以å‰ï¼Œè¿™ä¸ª kobject 指针被 sysfs 直接用于 +kobject 文件打开和关é—的引用计数。而现在的 sysfs 实现ä¸ï¼Œkobject +引用计数åªèƒ½é€šè¿‡ sysfs_schedule_callback() 函数直接修改。 + + +属性 +~~~~ + +kobject 的属性å¯åœ¨æ–‡ä»¶ç³»ç»Ÿä¸ä»¥æ™®é€šæ–‡ä»¶çš„å½¢å¼å¯¼å‡ºã€‚Sysfs 为属性定义 +了é¢å‘文件 I/O æ“作的方法,以æä¾›å¯¹å†…æ ¸å±žæ€§çš„è¯»å†™ã€‚ + + +属性应为 ASCII ç æ–‡æœ¬æ–‡ä»¶ã€‚以一个文件åªå˜å‚¨ä¸€ä¸ªå±žæ€§å€¼ä¸ºå®œã€‚但一个 +文件åªåŒ…å«ä¸€ä¸ªå±žæ€§å€¼å¯èƒ½å½±å“效率,所以一个包å«ç›¸åŒæ•°æ®ç±»åž‹çš„属性值 +数组也被广泛地接å—。 + +æ··åˆç±»åž‹ã€è¡¨è¾¾å¤šè¡Œæ•°æ®ä»¥åŠä¸€äº›æ€ªå¼‚çš„æ•°æ®æ ¼å¼ä¼šé到强烈åå¯¹ã€‚è¿™æ ·åšæ˜¯ +很丢脸的,而且其代ç 会在未通知作者的情况下被é‡å†™ã€‚ + + +一个简å•的属性结构定义如下: + +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); + + +一个å•独的属性结构并ä¸åŒ…å«è¯»å†™å…¶å±žæ€§å€¼çš„æ–¹æ³•。åç³»ç»Ÿæœ€å¥½ä¸ºå¢žåˆ ç‰¹å®š +对象类型的属性定义自己的属性结构体和å°è£…函数。 + +例如:é©±åŠ¨ç¨‹åºæ¨¡åž‹å®šä¹‰çš„ device_attribute 结构体如下: + +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 *); + +ä¸ºäº†å®šä¹‰è®¾å¤‡å±žæ€§ï¼ŒåŒæ—¶å®šä¹‰äº†ä¸€ä¸‹è¾…助å®: + +#define DEVICE_ATTR(_name, _mode, _show, _store) \ +struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) + +例如:声明 + +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, + }, +}; + + +å系统特有的回调函数 +~~~~~~~~~~~~~~~~~~~ + +当一个å系统定义一个新的属性类型时,必须实现一系列的 sysfs æ“作, +ä»¥å¸®åŠ©è¯»å†™è°ƒç”¨å®žçŽ°å±žæ€§æ‰€æœ‰è€…çš„æ˜¾ç¤ºå’Œå‚¨å˜æ–¹æ³•。 + +struct sysfs_ops { + ssize_t (*show)(struct kobject *, struct attribute *, char *); + ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); +}; + +[å系统应已ç»å®šä¹‰äº†ä¸€ä¸ª struct kobj_type 结构体作为这个类型的 +æè¿°ç¬¦ï¼Œå¹¶åœ¨æ¤ä¿å˜ sysfs_ops 的指针。更多的信æ¯å‚è§ kobject çš„ +文档] + +sysfs 会为这个类型调用适当的方法。当一个文件被读写时,这个方法会 +将一般的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; +} + + + +è¯»å†™å±žæ€§æ•°æ® +~~~~~~~~~~~~ + +在声明属性时,必须指定 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 会分é…一个大å°ä¸º (PAGE_SIZE) çš„ç¼“å†²åŒºå¹¶ä¼ é€’ç»™è¿™ä¸ªæ–¹æ³•ã€‚ +Sysfs å°†ä¼šä¸ºæ¯æ¬¡è¯»å†™æ“作调用一次这个方法。这使得这些方法在执行时 +会出现以下的行为: + +- 在读方é¢ï¼ˆread(2)),show() 方法应该填充整个缓冲区。回想属性 + 应åªå¯¼å‡ºäº†ä¸€ä¸ªå±žæ€§å€¼æˆ–是一个åŒç±»åž‹å±žæ€§å€¼çš„æ•°ç»„,所以这个代价将 + ä¸ä¼šä¸å¤ªé«˜ã€‚ + + 这使得用户空间å¯ä»¥å±€éƒ¨åœ°è¯»å’Œä»»æ„çš„å‘剿œç´¢æ•´ä¸ªæ–‡ä»¶ã€‚如果用户空间 + å‘åŽæœç´¢åˆ°é›¶æˆ–使用‘0’å移执行一个pread(2)æ“作,show()方法将 + 冿¬¡è¢«è°ƒç”¨ï¼Œä»¥é‡æ–°å¡«å……缓å˜ã€‚ + +- 在写方é¢ï¼ˆwrite(2)),sysfs 希望在第一次写æ“作时得到整个缓冲区。 + ä¹‹åŽ Sysfs ä¼ é€’æ•´ä¸ªç¼“å†²åŒºç»™ store() 方法。 + + 当è¦å†™ sysfs æ–‡ä»¶æ—¶ï¼Œç”¨æˆ·ç©ºé—´è¿›ç¨‹åº”é¦–å…ˆè¯»å–æ•´ä¸ªæ–‡ä»¶ï¼Œä¿®è¯¥æƒ³è¦ + 改å˜çš„值,然åŽå›žå†™æ•´ä¸ªç¼“冲区。 + + 在读写属性值时,属性方法的执行应æ“作相åŒçš„缓冲区。 + +注记: + +- 写æ“作导致的 show() 方法é‡è½½ï¼Œä¼šå¿½ç•¥å½“剿–‡ä»¶ä½ç½®ã€‚ + +- 缓冲区应总是 PAGE_SIZE 大å°ã€‚对于i386,这个值为4096。 + +- show() 方法应该返回写入缓冲区的å—节数,也就是 snprintf()çš„ + 返回值。 + +- show() 应始终使用 snprintf()。 + +- store() 应返回缓冲区的已用å—节数。如果整个缓å˜éƒ½å·²å¡«æ»¡ï¼Œåªéœ€è¿”回 + count 傿•°ã€‚ + +- show() 或 store() å¯ä»¥è¿”å›žé”™è¯¯å€¼ã€‚å½“å¾—åˆ°ä¸€ä¸ªéžæ³•值,必须返回一个 + 错误值。 + +- ä¸€ä¸ªä¼ é€’ç»™æ–¹æ³•çš„å¯¹è±¡å°†ä¼šé€šè¿‡ sysfs 调用对象内嵌的引用计数固定在 + 内å˜ä¸ã€‚尽管如æ¤ï¼Œå¯¹è±¡ä»£è¡¨çš„物ç†å®žä½“(如设备)å¯èƒ½å·²ä¸å˜åœ¨ã€‚如有必è¦ï¼Œ + 应该实现一个检测机制。 + +一个简å•çš„(未ç»å®žéªŒè¯å®žçš„)设备属性实现如下: + +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); + + +(注æ„:真æ£çš„实现ä¸å…许用户空间设置设备å。) + +顶层目录布局 +~~~~~~~~~~~~ + +sysfs ç›®å½•çš„å®‰æŽ’æ˜¾ç¤ºäº†å†…æ ¸æ•°æ®ç»“构之间的关系。 + +顶层 sysfs 目录如下: + +block/ +bus/ +class/ +dev/ +devices/ +firmware/ +net/ +fs/ + +devices/ 包å«äº†ä¸€ä¸ªè®¾å¤‡æ ‘çš„æ–‡ä»¶ç³»ç»Ÿè¡¨ç¤ºã€‚ä»–ç›´æŽ¥æ˜ å°„äº†å†…éƒ¨çš„å†…æ ¸ +è®¾å¤‡æ ‘ï¼Œåæ˜ 了设备的层次结构。 + +bus/ 包å«äº†å†…æ ¸ä¸å„ç§æ€»çº¿ç±»åž‹çš„å¹³é¢ç›®å½•布局。æ¯ä¸ªæ€»çº¿ç›®å½•包å«ä¸¤ä¸ª +å目录: + + devices/ + drivers/ + +devices/ 包å«äº†ç³»ç»Ÿä¸å‡ºçŽ°çš„æ¯ä¸ªè®¾å¤‡çš„符å·é“¾æŽ¥ï¼Œä»–ä»¬æŒ‡å‘ root/ 下的 +设备目录。 + +drivers/ 包å«äº†æ¯ä¸ªå·²ä¸ºç‰¹å®šæ€»çº¿ä¸Šçš„设备而挂载的驱动程åºçš„目录(这里 +å‡å®šé©±åŠ¨æ²¡æœ‰è·¨è¶Šå¤šä¸ªæ€»çº¿ç±»åž‹)。 + +fs/ 包å«äº†ä¸€ä¸ªä¸ºæ–‡ä»¶ç³»ç»Ÿè®¾ç«‹çš„目录。现在æ¯ä¸ªæƒ³è¦å¯¼å‡ºå±žæ€§çš„æ–‡ä»¶ç³»ç»Ÿå¿…é¡» +在 fs/ 下创建自己的层次结构(å‚è§Documentation/filesystems/fuse.txt)。 + +dev/ 包å«ä¸¤ä¸ªå目录: char/ å’Œ block/。在这两个å目录ä¸ï¼Œæœ‰ä»¥ +<major>:<minor> æ ¼å¼å‘½å的符å·é“¾æŽ¥ã€‚这些符å·é“¾æŽ¥æŒ‡å‘ sysfs 目录 +ä¸ç›¸åº”的设备。/sys/dev æä¾›ä¸€ä¸ªé€šè¿‡ä¸€ä¸ª stat(2) æ“作结果,查找 +设备 sysfs 接å£å¿«æ·çš„æ–¹æ³•。 + +更多有关 driver-model 的特性信æ¯å¯ä»¥åœ¨ Documentation/driver-model/ +䏿‰¾åˆ°ã€‚ + + +TODO: 完æˆè¿™ä¸€èŠ‚ã€‚ + + +å½“å‰æŽ¥å£ +~~~~~~~~ + +以下的接å£å±‚æ™®éå˜åœ¨äºŽå½“å‰çš„sysfsä¸: + +- 设备 (include/linux/device.h) +---------------------------------- +结构体: + +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); +}; + +声明: + +DEVICE_ATTR(_name, _mode, _show, _store); + +增/åˆ å±žæ€§: + +int device_create_file(struct device *dev, const struct device_attribute * attr); +void device_remove_file(struct device *dev, const struct device_attribute * attr); + + +- æ€»çº¿é©±åŠ¨ç¨‹åº (include/linux/device.h) +-------------------------------------- +结构体: + +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); +}; + +声明: + +BUS_ATTR(_name, _mode, _show, _store) + +增/åˆ å±žæ€§: + +int bus_create_file(struct bus_type *, struct bus_attribute *); +void bus_remove_file(struct bus_type *, struct bus_attribute *); + + +- è®¾å¤‡é©±åŠ¨ç¨‹åº (include/linux/device.h) +----------------------------------------- + +结构体: + +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); +}; + +声明: + +DRIVER_ATTR(_name, _mode, _show, _store) + +增/åˆ å±žæ€§ï¼š + +int driver_create_file(struct device_driver *, const struct driver_attribute *); +void driver_remove_file(struct device_driver *, const struct driver_attribute *); + + +文档 +~~~~ + +sysfs 目录结构以åŠå…¶ä¸åŒ…å«çš„å±žæ€§å®šä¹‰äº†ä¸€ä¸ªå†…æ ¸ä¸Žç”¨æˆ·ç©ºé—´ä¹‹é—´çš„ ABI。 +对于任何 ABI,其自身的稳定和适当的文档是éžå¸¸é‡è¦çš„。所有新的 sysfs +属性必须在 Documentation/ABI 䏿œ‰æ–‡æ¡£ã€‚è¯¦è§ Documentation/ABI/README。