sysfs and devtmpfs

本文详细解释了Linux文件系统中sysfs与devtmpfs的功能差异。sysfs主要用于提供设备信息及控制接口,而devtmpfs则由内核自动生成设备节点。两者虽然都涉及设备管理,但各自的侧重点不同。

sysfs and devtmpfs

 

Question:

Ulrich Dangel explains verywell the difference between devtmpfs and udev.

What about sysfs?

I understand that the kernel uses sysfs toexport device nodes to user space to be used by udev. So devtmpfs and sysfs arethe same? If yes, why do they use different names? If no, what is the realdifference between sysfs and devtmpfs?

 

 

 

Answen:

No. Sysfs does not contain device nodes.Sysfs mainly contains files that provide information about devices, as well assome files that allow processes to control how devices operate. But for themost part devices cannot beused through what sysfs provides.

Let's take ahard disk, for example. There's a directory for it somewhere under /sys/devices, with a path that depends on how it's connected to the computer(e.g. /sys/devices/pci0000:00/… for a disk connected to a controller that'sconnected to the computer's primary PCI bus). In that directory, you can findvarious information such as its size, whether it's removable, its power state,etc. There are subdirectories for partitions as well. But there's nothing inthere that provides access to the content of the disk. Elsewhere in /sys, there aresymbolic links to the directory corresponding to that disk: in /sys/block, in /sys/class/block, etc. But still nothing to access thecontent of the disk.

In /dev, the entry forthe disk is a special file — a blockdevice. This file allows processes to read and write the content of the disk.(Though for a disk that usually doesn't happen; instead the content of the disk— or of a partition — is mounted, so the kernel is accessing the device,processes don't.)

 

Device filesallow some operations other than reading and writing content to be madethrough ioctl. It would be possible to provide allthe information and control interfaces that sysfs provides through ioctl on thedevice file. However this would be less convenient for several reasons:

1、  With separate files in /sys, permissionscan be set on a fine-grained basis. With a single file per device in /dev, it's all ornothing.

2、  Separate files can be read and writteneasily by applications. You can just use cat or echo. With ioctl, it's a lot harder: there'sno shell interface, often no interface in other high-level languages.

3、  With ioctl, the command has to beencoded in a number rather than a name, and the format of the arguments has tobe defined at a binary level. Using names and simple text formats makes iteasier to write software.

 

Going in theother direction, it would be possible to provide access to the device contentvia a file in sysfs. But this would require extra work in the kernel: sysfs isdesigned primarily to serve small files and symbolic links, and withoutthe ioctl supportthat existing applications expect. I don't think there would be a significantbenefit to expanding sysfs to support existing device types, hence the continuedexistence of device files.

 

Sysfs isautomatically populated by the kernel, reflecting the actually availabledevices in real time.

The meaning of a file in sysfs comesfrom its path, which is chosen by the driver that provides that file. 

/dev works differently:the meaning of a file comes from the device file's type (block or character)and its major and minor numbers (that's what ls -l lists instead of the file size fora device).

 

Dynamic /dev that reflects connecteddevices in real time

Traditionally, /dev wasstatic, with device files created during system installation; but that doesn'twork so well when devices can be hotplugged, hence the wish for a dynamic /dev thatreflects connected devices in real time.

 

Linux has gonethrough several iterations of a dynamic /dev. Linux 2.4 has devfs, where the kernel automatically createdentries to reflect connected devices. But that was notso nice, because it hard-coded device naming and permission policies into thekernel, so it was replaced by the userland program udev to manage policy, and /dev on asimple tmpfs filesystem (an in-memory filesystem with no special meaning to thekernel). And then devfs made a partial comeback, with devtmpfs, which is an instance of tmpfs whereentries for available devices are automatically created by the kernel, but udevdoes all the management it wants on top of that.

 

 

 

 

 

 

 

 

From: http://unix.stackexchange.com/questions/236533/sysfs-and-devtmpfs


init: Add the ability to find the boot device by partition UUID The current mechanism for specifying boot devices on Android systems involves passing a set of "boot_devices" though command line, bootconfig, or device tree. The bootdevices are specified as strings and, in general, need to match a sysfs path but without the "/sys/devices" or "/sys/devices/platform" prefix. The sysfs path is generally the path to the closest parent of the block device that is a "platform" device. As an example, if the sysfs path of the expected boot device is: /sys/devices/platform/soc@0/7c4000.mmc/mmc_host/mmc1/mmc1:0001/block/mmcblk1 The bootloader would specify it as "soc@0/7c4000.mmc" since: * We strip off "/sys/devices/platform/" * As we move up directories, we don't find one whose subsystem is "platform" until we get up to "/sys/devices/platform/soc@0/7c4000.mmc". The current mechanism is a bit brittle. Specifically: * The sysfs path isn't _really_ stable and can change across kernel upgrades. For instance, during one kernel upgrade the device tree for a product changed so that the root node changed from "soc" to "soc@0" and this changed all sysfs paths. In the past device tree folks have asserted that we shouldn't rely on dts node names to stay consistent, yet those node names are used to construct sysfs paths. * For some devices, like USB, the path of the closest "platform" device tends to be the path of the USB controller. This means that if two USB disks are plugged in we can't guarantee which one will be identified as the boot device. Add a new method of finding the boot device by passing the partition UUID that we loaded the kernel from. Using the partition UUID to identify the boot device is standard on Linux. You can see this because when you're not using an initramfs you can use the syntax "root=PARTUUID=<valid-uuid-id>[/PARTNROFF=n]" to specify the root. Using the same idea for Android's boot code makes sense. With this new method for finding the boot device, we can make the code much more specific about matching sysfs paths. Once we find the sysfs path for the kernel we can make sure that all of the other boot partition share the same "scsi" or "mmc" parent instead of going all the way to the closest platform device. In the above example, this means that we'd make sure that all boot devices are found under this sysfs node: /sys/devices/platform/soc@0/7c4000.mmc/mmc_host/mmc1/mmc1:0001/block/mmcblk1 ...instead of just making sure they are under: /sys/devices/platform/soc@0/7c4000.mmc There is the question of what we should do if the bootloader passes _both_ an old style "boot_devices" and also a partition UUID. In this case, we'll issue a warning and then ignore the old "boot_devices". Considering it a warning rather than an error could allow switching to the "boot_part_uuid" method even if an old bootloader is still hardcoding some old "boot_devices". NOTE: Using partition UUID won't cause any security problems even though someone _could_ plug in an external device crafted to have the same UUID as the normal boot device's kernel partition. We already have "verity" in the system making sure our filesystems are not tampered with and this would also protect us from booting a tampered disk. That means that the worst someone could do in this case would be to confuse the system and make the device non-bootable. Chromebooks have been using the partition UUID to find the root filesystems for years and this has never been a problem. NOTE: this new method relies on the commit ("init: Add partition_uuid to Uevent") which in turn relies upstream kernel commit 74f4a8dc0dd8 ("block: add partition uuid into uevent as "PARTUUID"").
07-16
#!/bin/sh # === 第一张图内容 === add_module_pre_hook() { MODULE_PRE_HOOKS="$MODULE_PRE_HOOKS $1" } add_module_post_hook() { MODULE_POST_HOOKS="$MODULE_POST_HOOKS $1" } load_kernel_module() { modprobe $1 } msg() { printf "\e[$1m$2\e[0m" } info() { msg "0;32" "$1\n" # Green } debug() { [ "$DEBUG" = "true" ] && msg "0;37" "DEBUG: $1\n" # White } fatal() { msg "1;31" "\nFATAL: $1\n" # Red while : ; do : ; done } # === 第二张图内容 === taskset -p 0x80$$ # Variables shared among modules ROOTFS_DIR="/rootfs" # where to do the switch root MODULE_PRE_HOOKS="" # functions to call before running each module MODULE_POST_HOOKS="" # functions to call after running each module MODULES_DIR=/init.d # place to look for modules EFI_DIR=/sys/firmware/efi # place to store device firmware information # make mount stop complaining about missing /etc/fstab touch /etc/fstab # initialize /proc, /sys, /run/lock and /var/lock mkdir -p /proc /sys /run/lock /var/lock mount -t proc proc /proc mount -t sysfs sysfs /sys if [ -d $EFI_DIR ]; then mount -t efivarfs none /sys/firmware/efi/efivars fi # populate bootparam environment for p in `cat /proc/cmdline`; do if [ -n "$quoted" ]; then value="$value $p" if [ "`echo $p | sed -e 's/\"$//'`" != "$p" ]; then eval "bootparam_${quoted}=\"${value}\"" unset quoted fi continue fi opt=`echo $p | cut -d'=' -f1` opt=`echo $opt | sed -e 'y/-/_/'` if [ "`echo $p | cut -d'=' -f1`" = "$p" ]; then eval "bootparam_${opt}=true" else value=`echo $p | cut -d'=' -f2-` if [ "`echo $value | sed -e 's/^\"//'`" != "$value" ]; then quoted=${opt} continue fi eval "bootparam_${opt}=\"${value}\"" fi done # === 第三张图内容 === # use /dev with devtmpfs if grep -q devtmpfs /proc/filesystems; then mkdir -p /dev mount -t devtmpfs devtmpfs /dev else if [ ! -d /dev ]; then fatal "ERROR: /dev doesn't exist and kernel doesn't have devtmpfs enabled." fi fi mkdir $ROOTFS_DIR # Load module definitions for m in $MODULES_DIR/*; do debug "source module:$m" source $m done # Load and run modules for m in $MODULES_DIR/*; do # Skip backup files if [ "`echo $m | sed -e 's/\~$//'`" != "$m" ]; then continue fi module=`basename $m | cut -d'-' -f2` debug "Loading module $module" # pre hooks for h in $MODULE_PRE_HOOKS; do debug "Calling module hook (pre): $h" eval "$h pre $module" debug "Finished module hook (pre): $h" done # Check if module enabled if ! eval "${module}_enabled"; then debug "Skipping module $module" continue fi # Execute module main function debug "Running ${module}_run" eval "${module}_run" debug "Ran ${module}_run" # post hooks for h in $MODULE_POST_HOOKS; do debug "Calling module hook (post): $h" eval "$h post $module" debug "Finished module hook (post): $h" done done # Catch all fatal "ERROR: Initramfs failed to initialize the system." 详细讲解一下这段
最新发布
08-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值