Skip to main content
 首页 » 编程设计

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

2022年07月19日59duanxz

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

本文参考链接:https://www.cnblogs.com/hellokitty2/p/10277639.html