Android设备节点
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第1章Android设备节点的创建
在编写linux设备驱动程序的时候,很多时候都是利用mknod命令来手动创建设备节点的,带上名字和主次设备号就可以在/dev目录下生成设备节点。同样Android沿用了linux内核,很多设备驱动的节点是又是什么时候创建的呢?
在kernel自解压模块加载完成之后,会去运行android第一个应用程序init。在init.c的
在之前解析init.rc脚本的时候,service会被放在service_list的链表里。接下来就是要执行
Android的服务不是选项不是disabled并且带core和main的选项的服务都是需要开机自动加载的服务。而ueventd是由system/core/init/ueventd.c编译而成的。
System/core/init/ueventd.c
int ueventd_main(int argc, char **argv)
{
……
ueventd_parse_config_file("/ueventd.rc");
……
snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
ueventd_parse_config_file(tmp);
……
device_init();
……
while(1) {
ufd.revents = 0;
nr = poll(&ufd, 1, -1);
if (nr <= 0)
continue;
if (ufd.revents == POLLIN)
handle_device_fd();
}
}
Ueventd的main函数做的事情比较多,首先是要解析根文件系统下的ueventd.rc以及ueventd.
就是parse_line_device。
然后通过device_init给设备添加创建NETLINK套接字。
System/core/init/ueventd.c
int ueventd_main(int argc, char **argv)
{
……
ueventd_parse_config_file("/ueventd.rc");
……
snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
ueventd_parse_config_file(tmp);
……
device_init();
……
while(1) {
ufd.revents = 0;
nr = poll(&ufd, 1, -1);
if (nr <= 0)
continue;
if (ufd.revents == POLLIN)
handle_device_fd();
}
}
通过轮询的方式查看设备的uevent的变化,在设备注册产生kobject_uevent。在设备处理时候调用了handle_device_fd()。
接收的uevent的小心不能超过1024个字节,如果超出就算溢出将不会处理。如果接收的uevent有效,解析这个uevent会根据设备的类型来解析。之后handle_device_event会处理设备的event。而handle_firmware_event则是和某些设备需要firmware回去处理firmware的加载。
如果event的subsystem为block,说明是个块设备,就会交由handle_block_device_event去处理。或者subsystem是platform设备的话,则有handle_platform_device_event来处理。如果两者都不是的话,说明是一个普通设备,handle_generic_device_event会来处理。块设备和
if (!strncmp(uevent->subsystem, "usb", 3)) {
if (!strcmp(uevent->subsystem, "usb")) {
/* This imitates the file system that would be created
* if we were using devfs instead.
* Minors are broken up into groups of 128, starting at "001"
*/
int bus_id = uevent->minor / 128 + 1;
int device_id = uevent->minor % 128 + 1;
/* build directories */
mkdir("/dev/bus", 0755);
mkdir("/dev/bus/usb", 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id);
mkdir(devpath, 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
} else {
/* ignore other USB events */
return;
}
……
else if (!strncmp(uevent->subsystem, "graphics", 8)) {
base = "/dev/graphics/";
mkdir(base, 0755);
} else if (!strncmp(uevent->subsystem, "drm", 3)) {
base = "/dev/dri/";
mkdir(base, 0755);
} else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
base = "/dev/oncrpc/";
mkdir(base, 0755);
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
base = "/dev/adsp/";
……
handle_device(uevent->action, devpath, uevent->path, 0,
uevent->major, uevent->minor, links);
}
首先得到设备的名字,然后是创建一些设备的子目录,如果uevent->subsystem是usb,就需要创建一个/dev/bus/usb的目录。如果是uevent->subsystem是graphic的话,就需要创建一个/dev/graphics的目录,按照这样依次比较下去,创建设备类所需要的子目录。