慢慢欣赏linux 设备节点的创建

linux可以通过udev接收内核消息创建设备节点。例如虚拟节点/dev/pts/0就是动态创建的。

static int __init tty_class_init(void)
    =>tty_class = class_create(THIS_MODULE, "tty");

static void __init unix98_pty_init(void)
    =>ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
    =>pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
    =>ptm_driver->owner = THIS_MODULE;
    ptm_driver->driver_name = "pty_master";
    ptm_driver->name = "ptm";
    ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
    ptm_driver->minor_start = 0;
    ptm_driver->type = TTY_DRIVER_TYPE_PTY;
    ptm_driver->subtype = PTY_TYPE_MASTER;
    ptm_driver->init_termios = tty_std_termios;
    ptm_driver->init_termios.c_iflag = 0;
    ptm_driver->init_termios.c_oflag = 0;
    ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
    ptm_driver->init_termios.c_lflag = 0;
    ptm_driver->init_termios.c_ispeed = 38400;
    ptm_driver->init_termios.c_ospeed = 38400;
    ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
        TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
    =>tty_set_operations(ptm_driver, &ptm_unix98_ops);
    =>pts_driver->owner = THIS_MODULE;
    pts_driver->driver_name = "pty_slave";
    pts_driver->name = "pts";
    pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
    pts_driver->minor_start = 0;
    pts_driver->type = TTY_DRIVER_TYPE_PTY;
    pts_driver->subtype = PTY_TYPE_SLAVE;
    pts_driver->init_termios = tty_std_termios;
    pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
    pts_driver->init_termios.c_ispeed = 38400;
    pts_driver->init_termios.c_ospeed = 38400;
    pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
        TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
    =>tty_set_operations(pts_driver, &pty_unix98_ops);
                                                        /\
                                                        ||
                                                        V
                                                        static const struct tty_operations pty_unix98_ops = {
                                                            .lookup = pts_unix98_lookup,
                                                            .install = pty_unix98_install,
                                                            .remove = pty_unix98_remove,
                                                            .open = pty_open,
                                                            .close = pty_close,
                                                            .write = pty_write,
                                                            .write_room = pty_write_room,
                                                            .flush_buffer = pty_flush_buffer,
                                                            .chars_in_buffer = pty_chars_in_buffer,
                                                            .unthrottle = pty_unthrottle,
                                                            .set_termios = pty_set_termios,
                                                            .shutdown = pty_unix98_shutdown
                                                        };
    =>tty_register_driver(ptm_driver)
    =>tty_register_driver(pts_driver)
    =>register_sysctl_table(pty_root_table);
    =>tty_default_fops(&ptmx_fops);
    ptmx_fops.open = ptmx_open;
    =>cdev_init(&ptmx_cdev, &ptmx_fops);
    =>cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1)
    =>register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx")
    =>device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");

static int ptmx_open(struct inode *inode, struct file *filp)
    =>ret = __ptmx_open(inode, filp);
        =>/* find a device that is not in use. */
        index = devpts_new_index(inode);
        =>tty = tty_init_dev(ptm_driver, index, 1);
        =>filp->private_data = tty;
        =>retval = devpts_pty_new(inode, tty->link);
            =>dentry = d_alloc_name(root, s);
            =>d_add(dentry, inode);
            =>fsnotify_create(root->d_inode, dentry);
        =>retval = ptm_driver->ops->open(tty, filp);
    
int device_register(struct device *dev)
    =>device_initialize(dev);
    =>return device_add(dev);
        =>error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
            =>retval = kobject_add_varg(kobj, parent, fmt, args);
                =>retval = kobject_add_varg(kobj, parent, fmt, args);
                    =>if (MAJOR(dev->devt)) {
                        error = device_create_file(dev, &devt_attr);
                        if (error)
                            goto ueventattrError;

                        error = device_create_sys_dev_entry(dev);
                        if (error)
                            goto devtattrError;

                        devtmpfs_create_node(dev);//里面为空,不会执行
                    }
        =>error = device_create_file(dev, &uevent_attr);
        =>if (MAJOR(dev->devt)) {
            error = device_create_file(dev, &devt_attr);
            if (error)
                goto ueventattrError;

            error = device_create_sys_dev_entry(dev);
            if (error)
                goto devtattrError;

            devtmpfs_create_node(dev);//不执行
        }
        =>error = device_add_class_symlinks(dev);//dev/ttyS0 1 2 3节点创建的关键在于这句话,很是疑惑
        if (error)
            goto SymlinkError;
        error = device_add_attrs(dev);
        if (error)
            goto AttrsError;
        error = bus_add_device(dev);
        if (error)
            goto BusError;
        error = dpm_sysfs_add(dev);
        if (error)
            goto DPMError;
        device_pm_add(dev);
        =>if (dev->bus)
            blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                         BUS_NOTIFY_ADD_DEVICE, dev);
        =>kobject_uevent(&dev->kobj, KOBJ_ADD);///通过内核kobject_uevent向用户态发消息,udev或者mdev监听之后再用户态增加/dev/xxx节点
        =>bus_probe_device(dev);
        if (parent)
            klist_add_tail(&dev->p->knode_parent,
                       &parent->p->klist_children);

        if (dev->class) {
            mutex_lock(&dev->class->p->class_mutex);
            /* tie the class to the device */
            klist_add_tail(&dev->knode_class,
                       &dev->class->p->class_devices);

            /* notify any interfaces that the device is here */
            list_for_each_entry(class_intf,
                        &dev->class->p->class_interfaces, node)
                if (class_intf->add_dev)
                    class_intf->add_dev(dev, class_intf);
            mutex_unlock(&dev->class->p->class_mutex);
        }
    done:
        put_device(dev);
        return error;

以串口节点为例,查看内容:
#cat /sys/class/tty/ttyS0/dev
4:64

#cat /sys/class/tty/ttyS0/uevent
MAJOR=4
MINOR=64
DEVNAME=ttyS0


Linux驱动开发二:自动获得设备节点在/dev/目录下
https://blog.csdn.net/long123bin/article/details/40055763

在/dev下自动创建设备节点
https://blog.csdn.net/huyubin/article/details/46726949

/dev下设备节点的创建 
https://bbs.csdn.net/topics/392371795

Linux中tty、pty、pts的概念区别
https://www.cnblogs.com/zengkefu/p/5558851.html

/dev/tty 与 /dev/pts
https://www.cnblogs.com/zengkefu/p/5558840.html

三种创建节点的方法
https://blog.csdn.net/qq_33160790/article/details/67165019

Linux设备节点文件的创建—从mknod到devfs再到udev
https://blog.csdn.net/tankai19880619/article/details/17792167

devtmpfs文件系统创建设备节点                  老旧方法,仅做参考
http://blog.chinaunix.net/uid-27717694-id-3574368.html

Linux Kernel 学习笔记4:自动创建设备节点
https://blog.csdn.net/stone8761/article/details/70232768

ttyUSB串口设备节点生成过程
https://blog.csdn.net/mingtianwoyueni/article/details/63709861

device_create device_destroy 使用==mknod及通过class_create自动创建设备节点
http://blog.chinaunix.net/uid-22666248-id-3052861.html

一步一步学习 Linux 驱动之自动创建设备节点
https://blog.csdn.net/xy010902100449/article/details/45394981

Linux下的device_create创建字符设备节点流程        作者分析得很不错
https://blog.csdn.net/chen_chuang_/article/details/48462591

class_create(),device_create解析.device_create和device_add区别
https://blog.csdn.net/wanmj2/article/details/42709707

Linux设备模型浅析之uevent篇
https://wenku.baidu.com/view/3f08de275901020207409cd4.html

device_create和device_add区别
https://blog.csdn.net/qq_16777851/article/details/81259307

device_create和device_add和udev 
http://bbs.chinaunix.net/thread-4151639-1-1.html


 

猜你喜欢

转载自blog.csdn.net/shipinsky/article/details/83066709