Android和Linux下设备节点的创建笔记

1. Linux kernel创建的/dev/下的设备节点是不对的, 其实是kernel仅负责在/sys/(基于内存的虚拟文件系统)创建一大堆下目录和文件,而真正的设备节点是在用户空间程序创建的,应该是udev实现的。

2. 对于非android系统,应该是mdev,其实到底谁来处理,关键看kernel发送uevent事件,应用层通过什么方式处理的,是侦听socket还是通过设置/proc/sys/kernel/hotplug命令文件。

3. Android的设备节点和Linux的设备节点创建方式有些不同,但是都是通过捕获设备注册的event事件来创建设备节点的,而不是在device_add()里面就注册了,因为在内核启动阶段,根文件系统还没有挂载,没有/dev/目录。
在android系统中,由init进程负责处理这种uevent事件,如果是"add" device事件, init会在/dev/下创建相应的节点,具体代码可查看 system/core/init/devices.c: handle_device_event->make_device 节点的用户、组、权限都可以在devperms中定制。

Android 使用Init 进程来创建设备节点文件,分两种情况:静态节点文件和动态节点文件,以应对已经定义好的冷插拔和系统运行起来后插入的热插拔设备。
(1)对于冷插拔设备,init 进程事先获取等待冷插拔处理的驱动程序,事先定义好个驱动的设备节点文件(在android_source_code/system/core/init/devices.c中),在struct perms_devices[ ] 列出了设备节点的名称。访问权限,用户ID,组ID,若要添加新的用户定义的新设备需要在此结构体中添加相应信息。
(2)init 对于热插拔的动态设备,使用事件处理循环来完成,使用poll()监听来自驱动程序的uevent, 然后调用handle_device_fd()创建设备节点。

/*init.c中针对cold-plug设备节点的创建:*/
int main(int argc, char **argv)
    int ueventd_main(int argc, char **argv)
        device_init();
            coldboot("/sys/class");
            coldboot("/sys/block");
            coldboot("/sys/devices");
                do_coldboot(d); //他是一个递归函数
                    void handle_device_fd()
                        handle_device_event(&uevent);
                            handle_block_device_event(uevent);
                            handle_platform_device_event(uevent);
                            handle_generic_device_event(uevent); //在这个文件中创建设备节点
                                handle_device(uevent->action, devpath, uevent->path, 0, uevent->major, uevent->minor, links);

static void handle_device(const char *action, const char *devpath, const char *path, int block, int major, int minor, char **links)
{
    int i;

    if(!strcmp(action, "add")) {
        make_device(devpath, path, block, major, minor, (const char **)links); /*创建设备节点*/
        if (links) {
            for (i = 0; links[i]; i++)
                make_link_init(devpath, links[i]);
        }
    }

    if(!strcmp(action, "remove")) {
        if (links) {
            for (i = 0; links[i]; i++)
                remove_link(devpath, links[i]); /*移除软链接*/
        }
        unlink(devpath); /*移除设备节点*/
    }

    if (links) {
        for (i = 0; links[i]; i++)
            free(links[i]);
        free(links);
    }
}
/*main.c中针对hot-plug设备的设备节点的创建*/
int main(int argc, char **argv)
{
    .
    .
    .

    nr = poll(ufds, fd_count, timeout);
    if (nr <= 0)
        continue;

    for (i = 0; i < fd_count; i++) {
        if (ufds[i].revents & POLLIN) {
            if (ufds[i].fd == get_property_set_fd())
                handle_property_set_fd();
            else if (ufds[i].fd == get_keychord_fd())
                handle_keychord();
            else if (ufds[i].fd == get_signal_fd())
                handle_signal();
        }
    }

    return 0;
}

 

posted on 2019-01-16 16:14  Hello-World3  阅读(1649)  评论(0编辑  收藏  举报

导航