ldkiller

ldkiller

0个粉丝

2

问答

0

专栏

1

资料

ldkiller  发布于  2014-10-06 08:45:17
采纳率 0%
2个问答
3726

android 生成设备节点的方法

在Android中,由于没有mdev和udev,所以它没有办法动态的生成设备节点,那么它是如何做的呢?

我们可以在system/core/init/下的init.c和devices.c中找到答案:

init.c中

int main(int argc, char **argv)
{
    ...

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

   for(;;) {
       ...
        if (ufds[0].revents == POLLIN)
            handle_device_fd(device_fd);

        if (ufds[1].revents == POLLIN)
            handle_property_set_fd(property_set_fd);
        if (ufds[3].revents == POLLIN)
            handle_keychord(keychord_fd);
    }

    return 0;
}
我们再来看看handle_device_fd(),该函数定义在devices.c中

void handle_device_fd(int fd)
{
        ...
        handle_device_event(&uevent);
        handle_firmware_event(&uevent);
    }
}
而handle_device_event定义如下:

static void handle_device_event(struct uevent *uevent)
{
    ...
    if(!strcmp(uevent->action, "add")) {
        make_device(devpath, block, uevent->major, uevent->minor);
        return;
    }
    ...
}
make_device定义如下:

static void make_device(const char *path, int block, int major, int minor)
{
    ...
    mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
    dev = (major << 8) | minor;
    ...
    setegid(gid);
    mknod(path, mode, dev);
    chown(path, uid, -1);
    setegid(AID_ROOT);
}
我们看看get_device_perm如下实现:

static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid)
{
    mode_t perm;

    if (get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) {
        return perm;
    } else if (get_device_perm_inner(devperms, path, uid, gid, &perm) == 0) {
        return perm;
    } else {
        struct listnode *node;
        struct perm_node *perm_node;
        struct perms_ *dp;

        /* Check partners list. */
        list_for_each(node, &devperms_partners) {
            perm_node = node_to_item(node, struct perm_node, plist);
            dp = &perm_node->dp;

            if (dp->prefix) {
                if (strncmp(path, dp->name, strlen(dp->name)))
                    continue;
            } else {
                if (strcmp(path, dp->name))
                    continue;
            }
            /* Found perm in partner list. */
            *uid = dp->uid;
            *gid = dp->gid;
            return dp->perm;
        }
        /* Default if nothing found. */
        *uid = 0;
        *gid = 0;
        return 0600;
    }
}
我们最后可以看到在devperms中定义了要生成的设备节点:

static struct perms_ devperms[] = {
    { "/dev/null",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/zero",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/full",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/ptmx",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/tty",           0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/random",        0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/urandom",       0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/ashmem",        0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/binder",        0666,   AID_ROOT,       AID_ROOT,       0 },

        /* logger should be world writable (for logging) but not readable */
    { "/dev/log/",          0662,   AID_ROOT,       AID_LOG,        1 },

    /* the msm hw3d client device node is world writable/readable. */
    { "/dev/msm_hw3dc",     0666,   AID_ROOT,       AID_ROOT,       0 },

    /* gpu driver for adreno200 is globally accessible */
    { "/dev/kgsl",          0666,   AID_ROOT,       AID_ROOT,       0 },

        /* these should not be world writable */
    { "/dev/diag",          0660,   AID_RADIO,      AID_RADIO,        0 },
    { "/dev/diag_arm9",     0660,   AID_RADIO,      AID_RADIO,        0 },
    { "/dev/android_adb",   0660,   AID_ADB,        AID_ADB,        0 },
    { "/dev/android_adb_enable",   0660,   AID_ADB,        AID_ADB,        0 },
    { "/dev/ttyMSM0",       0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
    { "/dev/ttyHS0",        0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
    { "/dev/uinput",        0660,   AID_SYSTEM,     AID_BLUETOOTH,  0 },
    { "/dev/alarm",         0664,   AID_SYSTEM,     AID_RADIO,      0 },
    { "/dev/tty0",          0660,   AID_ROOT,       AID_SYSTEM,     0 },
    { "/dev/graphics/",     0660,   AID_ROOT,       AID_GRAPHICS,   1 },
    { "/dev/msm_hw3dm",     0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
    { "/dev/input/",        0660,   AID_ROOT,       AID_INPUT,      1 },
    { "/dev/eac",           0660,   AID_ROOT,       AID_AUDIO,      0 },
    { "/dev/cam",           0660,   AID_ROOT,       AID_CAMERA,     0 },
    { "/dev/pmem",          0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
    { "/dev/pmem_adsp",     0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/pmem_camera",   0660,   AID_SYSTEM,     AID_CAMERA,     1 },
    { "/dev/oncrpc/",       0660,   AID_ROOT,       AID_SYSTEM,     1 },
    { "/dev/adsp/",         0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/snd/",          0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/mt9t013",       0660,   AID_SYSTEM,     AID_SYSTEM,     0 },
    { "/dev/msm_camera/",   0660,   AID_SYSTEM,     AID_SYSTEM,     1 },
    { "/dev/akm8976_daemon",0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8976_aot",   0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8973_daemon",0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8973_aot",   0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/bma150",        0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/cm3602",        0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8976_pffd",  0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/lightsensor",   0640,   AID_SYSTEM,     AID_SYSTEM,     0 },
    { "/dev/msm_pcm_out",   0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_pcm_in",    0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_pcm_ctl",   0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_snd",       0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_mp3",       0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/audience_a1026", 0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/tpa2018d1",     0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_audpre",    0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/msm_audio_ctl", 0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/htc-acoustic",  0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/vdec",          0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/q6venc",        0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/snd/dsp",       0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/snd/dsp1",      0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/snd/mixer",     0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/smd0",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qemu_trace",    0666,   AID_SYSTEM,     AID_SYSTEM,     0 },
    { "/dev/qmi",           0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi0",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi1",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi2",          0640,   AID_RADIO,      AID_RADIO,      0 },
        /* CDMA radio interface MUX */
    { "/dev/ts0710mux",     0640,   AID_RADIO,      AID_RADIO,      1 },
    { "/dev/ppp",           0660,   AID_RADIO,      AID_VPN,        0 },
    { "/dev/tun",           0640,   AID_VPN,        AID_VPN,        0 },
    { NULL, 0, 0, 0, 0 },
};




在Android中,没有独立的类似于udev或者mdev的用户程序,这个功能集成到了init中做了。代码见:system/core/init/init.c文件,如下:

if (ufds[0].revents == POLLIN)

handle_device_fd(device_fd);

其中handle_device_fd(device_fd)函数在system/core/init/devices.c中实现,参数device_fd 由函数device_init()->open_uevent_socket()->socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)函数调用返回。

函数handle_device_fd(device_fd)中,根据传进来的device_fd参数,调用recv(fd, msg, UEVENT_MSG_LEN, 0)函数,将内核探测到的设备并通过NETLINK机制传过来的socket描述符转化成消息。接着调用parse_event(msg, &uevent);函数将消息翻译成uevent事件,并将改事件传递给handle_device_event(&uevent)函数。

handle_device_event(&uevent)函数中,依据参数uevent->subsystem类型创建dev下的相应目录,如:/dev/graphics。紧接着根据uevent->action是"add"还是"remove"来实现设备节点的创建与删除。如果uevent->action是"add",则调用make_device(devpath, block, uevent->major, uevent->minor)函数生成设备节点。如果uevent->action是"remove",则调用unlink(devpath)对设备节点进行删除。
我来回答
回答0个
时间排序
认可量排序
易百纳技术社区暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区