Linux 文件系統(tǒng)與設(shè)備文件

1 Linux 文件系統(tǒng)

1.1 Linux 文件系統(tǒng)與設(shè)備驅(qū)動關(guān)系

下圖表明了 Linux 中虛擬文件系統(tǒng)概荷、磁盤/Flash文件系統(tǒng)以及一般的設(shè)備文件與設(shè)備驅(qū)動程序之間的關(guān)系。

文件系統(tǒng)與設(shè)備驅(qū)動之間的關(guān)系

應(yīng)用程序與 VFS 之間的接口是系統(tǒng)調(diào)用,而 VFS 與文件系統(tǒng)以及設(shè)備文件之間的接口是 file_operations 結(jié)構(gòu)體成員函數(shù)糯俗,此結(jié)構(gòu)體包含了對文件進(jìn)行打開珍手、關(guān)閉真竖、讀寫荐开、控制的一系列成員函數(shù)。由于字符設(shè)備的上層沒有類似于磁盤的 ext2 等文件系統(tǒng)尖阔,所以字符設(shè)備的 file_operations 成員函數(shù)就直接由設(shè)備驅(qū)動提供了贮缅。

由此可以看出對于塊設(shè)備的訪問有兩種方法:

  • 一種方法是不通過文件系統(tǒng)直接訪問裸設(shè)備,Linux 內(nèi)核實現(xiàn)了統(tǒng)一的 def_blk_fops這一個 file_operations介却,他的源碼位于 fs/block_dev.c谴供。所以當(dāng)運行類似于 "dd if=/dev/sd1 of=sdb1.img" 的命令把整個 /dev/sdb1裸分區(qū)復(fù)制到 sdb1.img 的時候,內(nèi)核走的是 def_blk_fops這個 file_operations齿坷;
  • 另一種方法是通過文件系統(tǒng)來訪問設(shè)備桂肌,file_operations 的實現(xiàn)則位于文件系統(tǒng)內(nèi),文件系統(tǒng)會把正對文件的讀寫轉(zhuǎn)換為針對設(shè)備原始扇區(qū)的讀寫永淌。ext2崎场、fat、btrfs 等文件系統(tǒng)中會實現(xiàn)針對 VFS 的file_operations 成員函數(shù)遂蛀,設(shè)備驅(qū)動層將看不到 file_operations的存在谭跨。

1.2 設(shè)備驅(qū)動程序

在設(shè)備驅(qū)動程序設(shè)計中,一般而言李滴,會關(guān)心 file 和 inode 這兩個結(jié)構(gòu)體螃宙。

file 結(jié)構(gòu)體

file 結(jié)構(gòu)體代表一個打開的文件,系統(tǒng)中每個打開的文件在內(nèi)核空間都有一個與之關(guān)聯(lián)的 struct file所坯。它由內(nèi)核在打開文件時創(chuàng)建谆扎,并傳遞給在文件上進(jìn)行任何操作的函數(shù)。在文件的所有實例都關(guān)閉后芹助,內(nèi)核釋放此結(jié)構(gòu)體的數(shù)據(jù)堂湖。結(jié)構(gòu)體原型如下:

struct file {
    union{
        struct llist_node fu_llist;
        struct rcu_head fu_rcuhead;
    } f_u;

    struct path f_path;
    #define f_dentry f_path.dentry;
    struct inode *f_inode; //cached value
    const struct file_operations *f_op; //和文件關(guān)聯(lián)的操作

    //Protects f_ep_links, flags.
    //must not be taken from IRQ context
    spinlock_t f_lock;
    atomic_long_t f_count;
    unsigned int f_flags; //文件標(biāo)志,如 O_RDONLY O_NONBLOCK OSYNC
    fmode_t f_mode;  //文件讀寫模式 FMODE_READ FMODE_WRITE
    struct fown_struct f_owner;
    const struct cred *fcred;
    struct file_ra_state f_ra;

    u64 v_version;
    #ifdef CONFIG_SECURITY
    void *f_security;
    #endif

    //need for tty driver, and maybe others 
    void *private_data; //文件私有數(shù)據(jù)

    #ifdef CONFIG_EPOLL
    //used tye fs/eventpoll.c to link all the hooks to this file 
    struct list_head f_ep_links;
    struct list_head f_tfile_llink;
    #endif 

    struct address_space *f_mapping;
    
    
} __attribute__((aligned(4))); //lest something weird decides that 2 is OK

文件讀/寫模式 mode状土、標(biāo)志 f_flags 都是設(shè)備驅(qū)動關(guān)心的內(nèi)容无蜂,而私有數(shù)據(jù)指針 private_data 在設(shè)備驅(qū)動中被廣泛應(yīng)用,大多被指向設(shè)備驅(qū)動自定義以用于描述設(shè)備的結(jié)構(gòu)體声诸。

inode 結(jié)構(gòu)體

VFS node 包含文件的訪問權(quán)限、屬性退盯、組彼乌、大小泻肯、生成時間、訪問時間慰照、最后修改時間等信息灶挟。它是 Linux管理文件系統(tǒng)的最基本的單位,也是文件系統(tǒng)連接任何子目錄毒租、文件的橋梁稚铣。其定義如下:

struct inode{
    ...
    umode_t i_mode; //inode 的權(quán)限
    uid_t i_uid;  //inode 的擁有者id
    gid_t i_gid;  //inode 所屬的群組 id
    dev_t i_rdve; //若是設(shè)備文件,此字段將記錄設(shè)備的設(shè)備號
    loff_t i_size; //inode 所代表文件的大小 

    unsigned int i_blkbits;
    blkcnt_t i_blocks; //inode 所使用的block數(shù)墅垮, 一個block為 512 個字節(jié)
    union{
        struct pipe_inode_info *i_pipe;
        struct block_device  *i_bdev; //若是塊設(shè)備惕医,為其對應(yīng)的block_device結(jié)構(gòu)體指針
        struct cdev *i_cdev; //若是字符設(shè)備,為其對應(yīng)的 cdev 的結(jié)構(gòu)體指針
    };
    ...
};

對于表示設(shè)備文件的 inode 結(jié)構(gòu)算色,i_rdev 字段包含設(shè)備編號抬伺。linux 內(nèi)核設(shè)備編號分為主設(shè)備編號和次設(shè)備編號,前者為 dev_t 的高 12 位灾梦,后者位 dev_t 的低 20 位峡钓。下列操作用于從設(shè)備號中獲取主設(shè)備號和次設(shè)備號:

unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);

查看 /proc/devices 文件可以獲知系統(tǒng)中注冊的設(shè)備,第一列位主設(shè)備號若河,第 2 列為設(shè)備名稱能岩。如:

Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  5 ttyprintk
  6 lp
  7 vcs
 10 misc
Block devices:
259 blkext
  7 loop
  8 sd
  9 md
128 sd
134 sd
135 sd
253 device-mapper
254 mdp

查看/dev 目錄可以獲知系統(tǒng)中包含的設(shè)備文件,日期的前兩列分別給出了主設(shè)備號和次設(shè)備號萧福。如:

crw--w----   1 root    tty       4,  29 4月   9 16:39 tty29
crw--w----   1 root    tty       4,   3 4月   9 16:39 tty3
crw--w----   1 root    tty       4,  30 4月   9 16:39 tty30
crw--w----   1 root    tty       4,  31 4月   9 16:39 tty31
crw--w----   1 root    tty       4,  32 4月   9 16:39 tty32

主設(shè)備號是與驅(qū)動對應(yīng)的概念拉鹃,同一類設(shè)備使用相同的主設(shè)備號。
同一驅(qū)動可支持多個同類設(shè)備统锤,因此次設(shè)備號就是用來表示同一驅(qū)動下不同設(shè)備毛俏。

2 devfs

devfs(設(shè)備文件系統(tǒng))是由 linux2.4 內(nèi)核引入,它使得設(shè)備驅(qū)動程序能自主管理自己的設(shè)備文件饲窿。具體來說煌寇,devfs具有如下優(yōu)點:

  1. 可以通過程序在設(shè)備初始化時在 /dev 目錄下創(chuàng)建設(shè)備文件,卸載設(shè)備時將它刪除逾雄。
  2. 設(shè)備驅(qū)動程序可以指定設(shè)備名阀溶、所有者和權(quán)限位,用戶空間程序仍可以修改所有者和權(quán)限位鸦泳。
  3. 不再需要為設(shè)備驅(qū)動程序分配主設(shè)備號以及處理次設(shè)備號银锻,在程序中可以直接給 register_chr_dev() 傳遞 0 主設(shè)備號以獲得可用的主設(shè)備號,并在 devfs_register() 中指定次設(shè)備號做鹰。

驅(qū)動程序應(yīng)調(diào)用下面這些函數(shù)來進(jìn)行設(shè)備文件的創(chuàng)建和撤銷工作击纬。

//創(chuàng)建設(shè)備目錄
devfs_handle_t devfs_mk_dir(devfs_handle_t dir, const char *name, void *info);
//創(chuàng)建設(shè)備文件
devfs_handle_t devfs_register(devfs_handle_t dir, const char *name, unsigned int flags, \
unsigned int major, unsigned int minor, umode_t mode, void *ops, void *info);
//撤銷設(shè)備文件
void devfs_unregister(devfs_handle_t de);

在 Linux 2.4 的設(shè)備編程中,分別在模塊加載钾麸、卸載函數(shù)中創(chuàng)建和撤銷設(shè)備文件是被普遍采用并值得大力推薦的好方法更振。以下為示例代碼:

static devfs_handle_t devfs_handle;
static int __init xxx_init(void)
{
    int ret;
    int i;
    //在內(nèi)核中注冊設(shè) 
    ret = register_chr_dev(XXX_MAJOR, DEVICE_NAME, &xxx_fops);
    if(ret < 0)
    {
        printk(DEVICE_NAME " can't register major number\n");
        return ret;
    }

    //創(chuàng)建設(shè)備文件
    devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
    XXX_MAJOR, 0, S_IFCHR | S_IWUSR | S_IRUSR, &xxx_fops, NULL);
    ...
    printk(DEVICE_NAME " initialized.\n");
    return 0;
}

static void __exit xxx_exit(void)
{
    devfs_unregister(devfs_handle);    //撤銷設(shè)備文件
    unregister_chrdev(XXX_MAJOR, DEVICE_NAME); //注銷設(shè)備
}

module_init(xxx_init);
moudule_exit(xxx_exit);

3 udev 用戶空間設(shè)備管理

3.1 udev 和 devfs 的區(qū)別

在 Linux 2.6 內(nèi)核中炕桨,devfs 被認(rèn)為是過時的方法,并最終被淘汰了肯腕,udev 取代了它献宫。Linux VFS 內(nèi)核維護(hù)者 Al viro 指出了幾點 udev 取代 devfs 的原因:

  1. devfs 所做的工作被確信可以在用戶態(tài)來完成。
  2. devfs 被加入內(nèi)核之時实撒,大家期望它的質(zhì)量可以迎頭趕上姊途。
  3. 發(fā)現(xiàn) devfs 有一些可修復(fù)和無法修復(fù)的bug。
  4. 對于無法修復(fù)的 bug 在相當(dāng)長的一段時間內(nèi)沒有改觀知态。
  5. devfs 的維護(hù)者和作者對齊感到失望并停止對其維護(hù)捷兰。

Linux 設(shè)計中強調(diào)的一個基本觀點是機(jī)制和策略的分離。機(jī)制是穩(wěn)定的肴甸,而策略是靈活的导坟,機(jī)制應(yīng)該在內(nèi)核完成崩侠,而策略最好在用戶空間實現(xiàn)驻粟。

3.2 熱插拔事件

udev 完全在用戶態(tài)工作役电,利用設(shè)備加入或移除時內(nèi)核所發(fā)送的熱插拔事件(Hotplug Event)來工作。在熱插拔時庶柿,設(shè)備的詳細(xì)信息會由內(nèi)核通過 netlink 套接字發(fā)送出來村怪,發(fā)出來的事情叫 uevent。udev 的設(shè)備命名策略浮庐、權(quán)限控制和事件處理都是在用戶態(tài)下完成的甚负,它利用從內(nèi)核收到的信息進(jìn)行創(chuàng)建設(shè)備文件節(jié)點等工作。以下是一個獲取熱插拔事件 uevent的范例:

#include <linux/netlink.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <poll.h>
#include <stdio.h>


static void die(char *s)
{
    write(2, s, strlen(s));
    exit(1);
}

int main(int argc, char* argv[])
{
    struct sockaddr_nl nls;
    struct pollfd pfd;
    char buf[512];

    //open hotplug event netlink socket 
    
    memset(&nls, 0, sizeof(struct sockaddr_nl));
    nls.nl_family = AF_NETLINK;
    nls.nl_pid = getpid();
    nls.nl_groups = -1;

    pfd.events = POLLIN;
    pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if(-1 == pfd.fd)
        die("Not root\n");

    //Listen to netlink socket 
    if(bind(pfd.fd, (void *)&nls, sizeof(struct sockaddr_nl)))
        die("Bind failed.\n");

    while(-1 != poll(&pfd, 1, -1))
    {
        int i, len;
        len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT);
        if(-1 == len)
            die("recv\n");

        //print the data to stdout 
        i = 0;
        while(i < len){
            printf("%s\n", buf + i);
            i += strlen(buf + i) + 1;
        }
    }
    die("poll\n");

    return 0;
}

編譯上述代碼审残,在虛擬機(jī)上運行梭域,插拔光盤等設(shè)備,會打印熱插拔事件搅轿。

udev 就是采用這種方式接收 netlink 消息病涨,并根據(jù)它的內(nèi)容和用戶設(shè)置給 udev 的規(guī)則做匹配來進(jìn)行工作。

對于冷插拔的設(shè)備來說璧坟,Linux 內(nèi)核提供了 sysfs 下面的一個 uevent 節(jié)點既穆,可以往該節(jié)點寫一個 “add”,導(dǎo)致內(nèi)核重新發(fā)送 netlink雀鹃,之后 udev 就可以收到冷插拔的 netlink 消息了幻工。上述程序會dump 出如下信息:

ACTION=add
DEVPATH=/module/psmouse
SEQNUM=1682
SUBSYSTEM=module
UDEV_LOG=3
USEC_INITIALIZED=220903546792

devfs 與 udev 的一個顯著區(qū)別:

  • 采用 devfs,當(dāng)一個并不存在的 /dev 節(jié)點被打開的時候黎茎,devfs 能自動加載對應(yīng)的驅(qū)動囊颅,而udev不這么做。
  • udev 任務(wù)驅(qū)動應(yīng)該在設(shè)備被發(fā)現(xiàn)時,而不是設(shè)備被訪問時加載踢代。故 udev 獲取設(shè)備發(fā)現(xiàn)時的熱插拔事件先鱼,在設(shè)備發(fā)現(xiàn)時加載設(shè)備的驅(qū)動。

3.3 sysfs 文件系統(tǒng)與 Linux 設(shè)備模型

Linux 2.6 以后內(nèi)核引入了 sysfs 文件系統(tǒng)奸鬓,與 proc 類似。sysfs 把連接在系統(tǒng)上的設(shè)備和總線組織成為一個分級的文件掸读,它們可以由用戶空間存取串远,向用戶空間導(dǎo)出內(nèi)核數(shù)據(jù)結(jié)構(gòu)以及它們的屬性。sysfs 的一個目的就是展示設(shè)備驅(qū)動模型中各組件的層次關(guān)系儿惫。其頂級目錄包含 block澡罚、bus、devices肾请、class留搔、fs、kernel铛铁、power 和 firmware 等隔显。

block 目錄包含所有的塊設(shè)備;devices 目錄包含系統(tǒng)所有的設(shè)備饵逐,并根據(jù)設(shè)備掛接的總線類型組織稱層次結(jié)構(gòu)括眠;bus 目錄包含系統(tǒng)中所有的總線類型;class 目錄包含系統(tǒng)中的設(shè)備類型(如網(wǎng)卡設(shè)備倍权、聲卡設(shè)備掷豺、輸入設(shè)備等)。

在 /sys/bus 的 pci 等子目錄下薄声,又會再分出 drivers 和 devices 目錄中的文件是對 /sys/devices 目錄中文件的符號鏈接当船。同樣地,/sys/class 目錄下也包含許多對 /sys/devices 下文件的鏈接默辨。Linux 2.6 以后內(nèi)核的設(shè)備模型德频。

Linux 設(shè)備模型

Linux 內(nèi)核中,分別使用 bus_type廓奕、device_driver 和 device 來描述總線抱婉、驅(qū)動和設(shè)備,這 3 個結(jié)構(gòu)體定義于 include/linux/device.h 頭文件中桌粉,其定義如代碼清單:

struct bus_type{
    const char *name;
    const char *dev_name;
    struct device *dev_root;
    
    ...
    
    int (*match)(struct device *dev, struct device_driver *drv);

    ...
};

struct device_driver{
    const char *name;
    struct bus_type *bus;

    ...

    int (*probe)(struct device *dev);
    int (*remove)(struct device *dev);

    ...
};

struct device{

    ...
    
    struct bus_type *bus; //type of bus device is on
    struct device_driver *driver; //which driver has allocated this device

    ...
    
};

device_driver 和 device 分別表示驅(qū)動和設(shè)備蒸绩,而這兩者都必須依附于一種總線,因此都包含 struct bus_type 指針铃肯。在 Linux 內(nèi)核中患亿,設(shè)備和驅(qū)動都是分開注冊的,注冊一個設(shè)備時并不需要驅(qū)動已經(jīng)存在,而 1個驅(qū)動被注冊的時候步藕,也不需要對應(yīng)設(shè)備已經(jīng)存在惦界,設(shè)備和驅(qū)動各自涌向內(nèi)核,并尋找自己的另一半咙冗,而正是 bus_type 的match() 成員函數(shù)將兩者捆綁在一起沾歪,一旦配對成功,對應(yīng)總線的xxx_driver 的probe() 就被執(zhí)行(xxx是總線名雾消,如platform灾搏、pci、i2c立润、spi狂窑、usb等)。

總線桑腮、驅(qū)動和設(shè)備最終都會落實為 sysfs 中的 1 個目錄泉哈,因為進(jìn)一步追蹤代碼會發(fā)現(xiàn),它們實際上可以認(rèn)為是 kobject 的派生類破讨,kobject 可以看作是所有總線丛晦、設(shè)備和驅(qū)動的抽象基類,1 個 kobject 對應(yīng) sysfs 中的一個目錄提陶。

總線采呐、設(shè)備和驅(qū)動中的各個 attribute 則直接落實為 sysfs 中的 1 個文件,attribute 會伴隨著 show() 和 store() 這兩個函數(shù)搁骑,分別用于讀寫 attribute 對應(yīng)的 sysfs 文件斧吐,代碼給出了 attribute、bus_attribute仲器、driver_attribute 和 device_attribute 這幾個結(jié)構(gòu)體的定義煤率。

struct attribute{
    const char *name;
    umode_t mode;
   #ifdef CONFiG_DEBUG_LOCK_ALLOC
    bool ignore_lockdep:1;
    struct lock_class_key *key;
    struct lock_class_key *key;
   #endif 
};

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

struct driver_attribute{
    struct attribute attr;
    ssize_t (*show)(struct device_driver *driver, char *buf);
    ssize_t (*store)(struct device_driver *driver, const char *buf, size_t count);
};

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

事實上,sysfs 中的目錄來源于 bus_type乏冀、device_driver蝶糯、device,而目錄中的文件則來源于 attribute辆沦。
比如昼捍,我們在 drivers/base/bus.c文件中可以找到這樣的代碼:

static  BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO, 
        show_drivers_autoprobe, store_drivers_autoprobe);
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);

3.4 udev 的組成

udev 在用戶空間執(zhí)行,動態(tài)建立/刪除設(shè)備文件肢扯,允許每個人都不用關(guān)心主/次設(shè)備號而提供LSB(Linux 標(biāo)準(zhǔn)規(guī)范妒茬, Linux Standard Base)名稱,并可以根據(jù)需要固定名稱蔚晨。

udev 的工作過程如下:

  1. 當(dāng)內(nèi)核檢測到系統(tǒng)中出現(xiàn)了新設(shè)備后乍钻,內(nèi)核會通過 netlink 套接字發(fā)送uevent。
  2. udev 獲取內(nèi)核發(fā)送的信息,進(jìn)行規(guī)則匹配银择。匹配的事物包括 SUBSYSTEM多糠、ACTION、attribute浩考、內(nèi)核提供的名稱(通過 KERNEL ==)夹孔,以及其它環(huán)境變量。

以下是利用命令行工具 udevadm monitor --kernel --property --udev 捕獲到一個虛擬機(jī) Ubuntu 16.4.1 退出虛擬 ISO 文件的打游瞿酢:

KERNEL[15730.816373] change   /devices/pci0000:00/0000:00:1f.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0 (block)
ACTION=change
DEVNAME=/dev/sr0
DEVPATH=/devices/pci0000:00/0000:00:1f.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0
DEVTYPE=disk
DISK_MEDIA_CHANGE=1
MAJOR=11
MINOR=0
SEQNUM=4324
SUBSYSTEM=block

UDEV  [15730.923482] change   /devices/pci0000:00/0000:00:1f.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0 (block)
ACTION=change
DEVLINKS=/dev/cdrom /dev/disk/by-id/ata-VBOX_CD-ROM_VB2-01700376 /dev/dvd /dev/disk/by-path/pci-0000:00:1f.1-ata-2
DEVNAME=/dev/sr0
DEVPATH=/devices/pci0000:00/0000:00:1f.1/ata2/host1/target1:0:0/1:0:0:0/block/sr0
DEVTYPE=disk
DISK_MEDIA_CHANGE=1
ID_ATA=1
ID_BUS=ata
ID_CDROM=1
ID_CDROM_CD=1
ID_CDROM_DVD=1
ID_CDROM_MRW=1
ID_CDROM_MRW_W=1
ID_FOR_SEAT=block-pci-0000_00_1f_1-ata-2
ID_MODEL=VBOX_CD-ROM
ID_MODEL_ENC=VBOX\x20CD-ROM\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
ID_PATH=pci-0000:00:1f.1-ata-2
ID_PATH_TAG=pci-0000_00_1f_1-ata-2
ID_REVISION=1.0
ID_SERIAL=VBOX_CD-ROM_VB2-01700376
ID_SERIAL_SHORT=VB2-01700376
ID_TYPE=cd
MAJOR=11
MINOR=0
SEQNUM=4324
SUBSYSTEM=block
SYSTEMD_READY=0
TAGS=:uaccess:systemd:seat:
USEC_INITIALIZED=1513182

可以根據(jù)以上信息析蝴,創(chuàng)建一個規(guī)則,以便每次插入的時候绿淋,為該盤創(chuàng)建一個 /dev/testISO 的符號鏈接。

#iso 
SUBSYSTEM=="block", ACTION=="change", KERNEL="*sr?", ENV{ID_TYPE}=="cd", SYMLINK+="testISO"

TO-DO: 實驗未成功

3.5 udev 規(guī)則文件

udev 的規(guī)則文件以行為單位尝盼,以 “#” 開頭的行代表注釋行吞滞。其余的每一行代表一個規(guī)則。每個規(guī)則分成多個匹配部分和賦值部分盾沫。匹配部分用匹配專用的關(guān)鍵字來表示裁赠,匹配關(guān)鍵字包括:ACTION、KERNEL赴精、BUS佩捞、SUBSYSTEM、ATTR等蕾哟;賦值部分用賦值專用關(guān)鍵字一忱,賦值關(guān)鍵字包括:NAME(創(chuàng)建的設(shè)備文件文件名)、SYSLINK(符號創(chuàng)建鏈接名)谭确、OWNER(設(shè)置設(shè)備的所有者)帘营、GROUP(設(shè)置設(shè)備的組)、IMPORT(調(diào)用外部程序)逐哈、MODE(節(jié)點訪問權(quán)限)等芬迄。

由此可知,udev 可以實現(xiàn)設(shè)備的名稱或者符號鏈接的自定義昂秃,通過規(guī)則文件禀梳,匹配相應(yīng)設(shè)備,從而實現(xiàn)自定義設(shè)備名稱肠骆,而devfs 則無法做到算途。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蚀腿,隨后出現(xiàn)的幾起案子郊艘,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纱注,死亡現(xiàn)場離奇詭異畏浆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狞贱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門刻获,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞎嬉,你說我怎么就攤上這事蝎毡。” “怎么了氧枣?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵沐兵,是天一觀的道長。 經(jīng)常有香客問我便监,道長扎谎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任烧董,我火速辦了婚禮毁靶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逊移。我一直安慰自己预吆,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布胳泉。 她就那樣靜靜地躺著拐叉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扇商。 梳的紋絲不亂的頭發(fā)上巷嚣,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音钳吟,去河邊找鬼廷粒。 笑死,一個胖子當(dāng)著我的面吹牛红且,可吹牛的內(nèi)容都是我干的坝茎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼暇番,長吁一口氣:“原來是場噩夢啊……” “哼嗤放!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起壁酬,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤次酌,失蹤者是張志新(化名)和其女友劉穎恨课,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岳服,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡剂公,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吊宋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纲辽。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖璃搜,靈堂內(nèi)的尸體忽然破棺而出拖吼,到底是詐尸還是另有隱情,我是刑警寧澤这吻,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布吊档,位于F島的核電站,受9級特大地震影響唾糯,放射性物質(zhì)發(fā)生泄漏怠硼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一趾断、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吩愧,春花似錦芋酌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糖权,卻和暖如春堵腹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背星澳。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工疚顷, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禁偎。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓腿堤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親如暖。 傳聞我的和親對象是個殘疾皇子笆檀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自,格式做了調(diào)整盒至。 如果你使用Linux比較長時間了酗洒,那你就知道士修,在對待設(shè)備文件這塊,Linux改變了幾次策略樱衷。...
    mikeliuy閱讀 7,770評論 0 1
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,135評論 2 34
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言耍鬓,發(fā)作 oo-boon-too 的音阔籽。了解發(fā)音是有意...
    螢火蟲de夢閱讀 99,159評論 9 467
  • 大學(xué)的時候,幫朋友寫的操作系統(tǒng)調(diào)研的作業(yè)牲蜀,最近整理過去的文檔時候偶然發(fā)現(xiàn)笆制,遂作為博客發(fā)出來。 從串口驅(qū)動到Linu...
    free_will閱讀 7,366評論 7 59
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理涣达,服務(wù)發(fā)現(xiàn)在辆,斷路器,智...
    卡卡羅2017閱讀 134,601評論 18 139