How Linux creates device files under /dev

本文详细阐述了Linux系统如何在/dev目录下创建设备文件,包括字符设备、平台设备的创建过程,以及创建方法的区别与实例分析。

This post is used to describe how Linux creates device files under /dev, illustrated with devices attached to TCC8935's DISPLAY bus.


First of all, the "create device file" procedures are device-type specific:

1. Char device.   Example: VIQE //drivers/video/tcc/viqe/tcc_vioc_viqe.c

    When the driver (module) is loaded in:

    static int __init tcc_viqe_init(void)
    {
    int res;

    res = register_chrdev(VIQE_DEV_MAJOR, VIQE_DEV_NAME, &tcc_viqe_fops);
    if (res < 0)
        return res;
    viqe_class = class_create(THIS_MODULE, VIQE_DEV_NAME);
    device_create(viqe_class, NULL, MKDEV(VIQE_DEV_MAJOR, VIQE_DEV_MINOR), NULL, VIQE_DEV_NAME);

    printk(KERN_INFO "%s\n", __FUNCTION__);
    return 0;
    }

   The routine device_create() creates  a node under /dev according to MAJOR / MINOR / NAME parameters, /dev/viqe.

   BTW, routine class_create() creates a class "viqe" under /sys/class.


   Similar examples include WMIXER / SCALER. //drivers/char/tcc_wmixer.c, tcc_scaler.c


2. Platform device

     According to other blogs, Linux creates device node for platform devices when the DEVICE is registered, rather than the driver is registered.

     For example:

     platform_device_register(&tcc_lcd_device); (the struct tcc_lcd_device's NAME is "tccfb", which is identical with it's driver's name.

     CALLS platform_device_add(dev) -> CALLS device_add()

     routine device_add() calls device_create_file() to create files under /sys

     and

     calls devtmpfs_create_node() to create device node under /dev.

     NOTE: see blow blogs for details:  http://jieohsong.blog.163.com/blog/static/110530884201343054853424/ and


     I'm not sure if it's correct but i do cannot find a "tccfb" node under /dev.

     Well, my understanding is totally different. The driver creates device node within PROBE phase, and, the approach is device specific.


     Example 1: tccfb  //drivers/video/tcc/tcc_vioc_fb.c

     This is a PLATFORM device since the driver is registered via platform_driver_register().

     In routine probe(), calls register_framebuffer() -> do_register_framebuffer() , in do_register_framebuffer(),

     fb_info->dev = device_create(fb_class, fb_info->device,
                     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);

     The fb_class is "graphics", FB_MAJOR is 29.

     Here, we see device_create() again, exact the same as a char device above. And, there is a node under /dev/graphics, fb0, major number is 29.


     Example 2:  overlay //drivers/video/tcc/tcc_overlay.c

     This is a PLATFORM device.

     static struct platform_device tcc_overlay_device = {
    .name    = "tcc_overlay",
    .dev    = {
        .release     = NULL,
     },
    .id    = 0,
     };

     But also a MISC device.

     static struct miscdevice overlay_misc_device =
     {
    DEV_MINOR,
    DEVICE_NAME,
    &tcc_overlay_fops,
     };

    At the end of probe(), within misc_register(&overlay_misc_device), calls

    misc->this_device = device_create(misc_class, misc->parent, dev,
                      misc, "%s", misc->name);

    Familiar? That it!  It creates /dev/overlay.



    


<think>好的,我现在需要分析用户提供的Ansible任务是否可以正常识别和使用。用户的任务是创建GPT分区表、分区、格式化、创建目录并挂载。首先,我得检查YAML语法是否正确。任务中的cmd使用了多行命令,以竖线符号(|)开始,这应该会把多行命令合并为一个脚本执行。但Ansible的command模块默认不会通过shell执行,所以像换行分隔的命令可能不会按预期执行,导致只有第一个命令(parted -s /dev/vdb mklabel gpt)被执行,而后续命令被忽略。 接下来,用户使用的是community.general.command模块,这个模块和shell模块的区别在于是否通过shell处理命令。command模块直接执行命令,不经过shell解析,所以多行命令可能无法正确执行。需要用shell模块或者在command模块中使用shell的语法,比如用&&连接命令,或者将命令作为脚本传递。 另外,幂等性问题也很重要。多次运行这个任务可能会导致错误,例如重复创建分区或格式化已有分区。需要使用creates或only_if条件判断,比如检查分区是否存在,目录是否已挂载等,确保任务可以安全重复执行。 挂载目录/data需要在文件系统表中添加条目,否则重启后挂载会失效。用户的任务中没有使用mount模块的选项,比如修改/etc/fstab,这可能导致挂载不是永久的。 权限方面,执行parted、mkfs.xfs、mount等命令可能需要root权限,确保Ansible以sudo权限运行,或者在任务中指定become: yes。 总结问题点:多行命令在command模块中无法正确执行,缺乏幂等性处理,缺少永久挂载配置,可能需要root权限。建议改用shell模块,拆分任务,添加条件判断,并使用mount模块处理挂载和fstab更新。</think>### **Ansible 任务分析:分区、格式化与挂载** 你提供的 Ansible 任务列表 **可以执行**,但存在以下关键问题需要优化。以下是逐步分析和改进方案: --- ### **1. 当前任务的问题** #### **问题 1:`command` 模块的多行命令执行异常** - **原因**:`community.general.command` 模块默认逐行执行命令,但实际会将多行合并为单行命令,导致只有第一个 `parted` 命令生效,后续命令被忽略。 - **示例**: 你的 `cmd` 实际会被解析为: ```bash parted -s /dev/vdb mklabel gpt parted -s /dev/vdb mkpart "vdb1" 0% 100% mkfs.xfs /dev/vdb1 mkdir /data mount /dev/vdb1 /data ``` (所有命令合并为一行,无法正确执行) #### **问题 2:缺乏幂等性** - **风险**:重复运行 Playbook 会导致: - 重复创建分区表(覆盖已有分区)。 - 重复格式化分区(数据丢失)。 - 重复挂载目录(可能覆盖已有挂载)。 #### **问题 3:挂载非持久化** - **原因**:`mount` 命令未写入 `/etc/fstab`,重启后挂载失效。 #### **问题 4:权限不足** - **风险**:`parted`、`mkfs.xfs`、`mount` 需要 `root` 权限,但任务未指定 `become: yes`。 --- ### **2. 改进方案** #### **步骤 1:使用 `shell` 模块替代 `command`** - **原因**:`shell` 模块支持多行脚本和 Shell 语法(如 `&&`、换行符)。 - **优化后任务**: ```yaml tasks: - name: 创建分区并挂载 ansible.builtin.shell: | parted -s /dev/vdb mklabel gpt && \ parted -s /dev/vdb mkpart "vdb1" 0% 100% && \ mkfs.xfs /dev/vdb1 && \ mkdir -p /data && \ mount /dev/vdb1 /data args: executable: /bin/bash # 明确指定 Shell become: yes # 提权 ``` #### **步骤 2:添加幂等性检查** - **方法**:通过 `creates` 或 `when` 条件判断文件/分区是否存在。 - **优化后任务**(拆分任务): ```yaml tasks: - name: 检查分区表是否存在 ansible.builtin.stat: path: /dev/vdb1 register: vdb1_partition - name: 创建 GPT 分区表 ansible.builtin.shell: | parted -s /dev/vdb mklabel gpt && \ parted -s /dev/vdb mkpart "vdb1" 0% 100% when: not vdb1_partition.stat.exists # 仅当分区不存在时执行 become: yes - name: 格式化分区为 XFS ansible.builtin.command: mkfs.xfs /dev/vdb1 when: not vdb1_partition.stat.exists become: yes - name: 创建挂载目录 ansible.builtin.file: path: /data state: directory mode: '0755' - name: 挂载分区 ansible.builtin.mount: path: /data src: /dev/vdb1 fstype: xfs state: mounted # 自动写入 /etc/fstab become: yes ``` #### **步骤 3:使用 Ansible 原生模块替代 Shell** - **优势**:更安全、更易维护。 - **示例**(推荐方式): ```yaml tasks: - name: 创建分区 community.general.parted: device: /dev/vdb label: gpt number: 1 state: present flags: [ lvm ] part_start: 0% part_end: 100% become: yes - name: 格式化分区 community.general.filesystem: dev: /dev/vdb1 fstype: xfs become: yes - name: 创建挂载目录 ansible.builtin.file: path: /data state: directory - name: 永久挂载分区 ansible.builtin.mount: path: /data src: /dev/vdb1 fstype: xfs state: mounted become: yes ``` --- ### **3. 最终建议** 1. **使用专用模块**:如 `community.general.parted`、`community.general.filesystem`、`mount`,而非 Shell 命令。 2. **拆分任务**:每个操作独立成任务,便于错误处理和状态跟踪。 3. **幂等性设计**:通过 `when` 条件或模块内置的幂等性(如 `mount` 的 `state: mounted`)确保安全执行。 4. **权限管理**:始终添加 `become: yes` 提权。 --- ### **验证方法** 1. **语法检查**: ```bash ansible-playbook --syntax-check your_playbook.yml ``` 2. **空运行测试**: ```bash ansible-playbook -C your_playbook.yml ``` 3. **实际执行**: ```bash ansible-playbook your_playbook.yml ``` 通过上述优化,你的任务将更健壮、可维护且符合 Ansible 最佳实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值