Ueventd.rc对硬件设备访问权限处理
ueventd.rc
---------------------------------------------------------
/dev/null 0666 root root
/dev/zero 0666 root root
/dev/full 0666 root root
/dev/ptmx 0666 root root
/dev/tty 0666 root root
/dev/random 0666 root root
/dev/urandom 0666 root root
/dev/ashmem 0666 root root
/dev/binder 0666 root root
# logger should be world writable (for logging) but not readable
/dev/log/* 0662 root log
# the msm hw3d client device node is world writable/readable.
/dev/msm_hw3dc 0666 root root
# gpu driver for adreno200 is globally accessible
/dev/kgsl 0666 root root
/dev/graphics/* 0660 root graphics
/dev/msm_hw3dm 0660 system graphics
/dev/input/* 0660 root input
/dev/eac 0660 root audio
/dev/cam 0660 root camera
/dev/pmem 0660 system graphics
/dev/pmem_adsp* 0660 system audio
/dev/pmem_camera* 0660 system camera
/dev/oncrpc/* 0660 root system
/dev/adsp/* 0660 system audio
/dev/snd/* 0660 system audio
/dev/mt9t013 0660 system system
/dev/msm_camera/* 0660 system system
/dev/msm_pcm_in* 0660 system audio
/dev/msm_pcm_ctl* 0660 system audio
/dev/msm_snd* 0660 system audio
/dev/msm_mp3* 0660 system audio
/dev/audience_a1026* 0660 system audio
/dev/tpa2018d1* 0660 system audio
/dev/msm_audpre 0660 system audio
/dev/msm_audio_ctl 0660 system audio
/dev/htc-acoustic 0660 system audio
/dev/vdec 0660 system audio
/dev/q6venc 0660 system audio
/dev/snd/dsp 0660 system audio
/dev/snd/dsp1 0660 system audio
/dev/snd/mixer 0660 system audio
/dev/smd0 0640 radio radio
/dev/qmi 0640 radio radio
/dev/qmi0 0640 radio radio
/dev/qmi1 0640 radio radio
/dev/qmi2 0640 radio radio
/dev/bus/usb/* 0660 root usb
/dev/mtp_usb 0660 root mtp
/dev/usb_accessory 0660 root usb
/dev/tun 0660 system
/dev/video* 0666 root root
工作遇到打开/dev/video0失败的问题,在ueventd.rc中添加一行 /dev/video* 0666 root root 就OK 啦
下面介绍android init 对其解析与启动
Android的每个目录下面都有一个非常重要的文件Android.mk,负责编译该目录下面的代码。
System/core/init/android.mk
LOCAL_MODULE:= init
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
LOCAL_STATIC_LIBRARIES := libcutils libc
上面的代码会生成一个叫init的可执行程序,它会被放在/下面,且同时 会产生一个符号链接/sbin/eventd,指向/init. 我们不禁要问,为什么这样做?
Init是一个脚本解释器,它会对目标系统下的两个文件解析,
/init.rc
/init.xxx.rc (xxx代表平台平台名)
先看看源代码目录/device/xxx/init.rc
service ueventd /sbin/ueventd
class core
critical
看来init在解析脚本的时候又启动了一个自己的进程,只是进程名变成了ueventd.
System/core/init/init.c/main
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
根据进程名不同,程序执行路径不同。Ueventd顾名思义应该是接收uvent的守护进程,这里它的主要作用根据uevent是创建或删除/dev/xxx(xxx设备名),我们知道在linux下面创建设备节点的接口mknod,我们跟进去看看这个接口是在哪里调用的
System/core/init/Ueventd.c/ueventd_main
get_hardware_name(hardware, &revision);
ueventd_parse_config_file("/ueventd.rc");
snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
ueventd_parse_config_file(tmp);
device_init();
ufd.events = POLLIN;
ufd.fd = get_device_fd();
ueventd有两个脚本需要解析,ueventd.rc,ueventd.xxx.rc,脚本,又见脚本这个脚本可以让客户设置/dev 或 /sys目录及子目录的权限.
system/core/rootdir/ueventd.rc
eg> /dev/binder
这里请注意,ueventd_parse_config_file并不创建设备节点,它的作用是提供数据库,当有设备节点生成的时候,eventd会参考这个数据库设置设备节点的权限。
system/core/init/devices.c/device_init
device_fd = uevent_open_socket(64*1024, true);
if(device_fd < 0)
return;
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
fcntl(device_fd, F_SETFL, O_NONBLOCK);
if (stat(coldboot_done, &info) < 0) {
t0 = get_usecs();
coldboot("/sys/class");
coldboot("/sys/block");
coldboot("/sys/devices");
t1 = get_usecs();
fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000);
close(fd);
log_event_print("coldboot %ld uS\n", ((long) (t1 - t0)));
} else {
log_event_print("skipping coldboot, already done\n");
}
这个函数很简单,主要是创建了uevent的socket handle,同时触发/sys/clas,/sys/block,/sys/devices这三个目录及其子目录下的uevent,然后接受并创建设备节点,至此设备节点才算创建,coldboot里面有个很有意思的函数do_coldboot,这是一个递归调用函数,实现的很有意思,大家可以看看.
ufd.events = POLLIN;
ufd.fd = get_device_fd();
while(1) {
ufd.revents = 0;
nr = poll(&ufd, 1, -1);
if (nr <= 0)
continue;
if (ufd.revents == POLLIN)
handle_device_fd();
}
死循环,接受kernel传过来的uevent,动态创建或删除节点.
handle_device_fd会最终调用mknod创建设备节点,流程如下:
handle_device_fd-> handle_device_event-> make_device-> mknod