Android设备节点.doc_第1页
Android设备节点.doc_第2页
Android设备节点.doc_第3页
Android设备节点.doc_第4页
Android设备节点.doc_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章 Android设备节点的创建在编写linux设备驱动程序的时候,很多时候都是利用mknod命令来手动创建设备节点的,带上名字和主次设备号就可以在/dev目录下生成设备节点。同样Android沿用了linux内核,很多设备驱动的节点是又是什么时候创建的呢?在kernel自解压模块加载完成之后,会去运行android第一个应用程序init。在init.c的main函数中。System/core/init/init.cint main(int argc, char *argv)action_for_each_trigger(boot, action_add_queue_tail);在init进程解析init.rc脚本完成后,在on boot的最后两句是class start main和core,其中classStart是命令,在keyword.h中定义了class_start对应的function实际就是do_class_start。System/core/init/builtins.cint do_class_start(int nargs, char *args) service_for_each_class(args1, service_start_if_not_disabled); return 0;System/core/init/init_parser.cvoid service_for_each_class(const char *classname, void (*func)(struct service *svc)list_for_each(node, &service_list) svc = node_to_item(node, struct service, slist); if (!strcmp(svc-classname, classname) func(svc); 在之前解析init.rc脚本的时候,service会被放在service_list的链表里。接下来就是要执行service_for_each_class的func(svc),也就是service_start_if_not_disabled。System/core/init/builtins.cstatic void service_start_if_not_disabled(struct service *svc) if (!(svc-flags & SVC_DISABLED) service_start(svc, NULL); Android的service大都是编译成可执行文件以命令的格式,我们注意到在init.rc中又这么个service值得关注下。service ueventd /sbin/ueventd class core criticalAndroid的服务不是选项不是disabled并且带core和main的选项的服务都是需要开机自动加载的服务。而ueventd是由system/core/init/ueventd.c编译而成的。System/core/init/ueventd.cint 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.$hardware.rc。System/core/init/ueventd_parser.cint ueventd_parse_config_file(const char *fn)char *data; data = read_file(fn, 0); if (!data) return -1; parse_config(fn, data); DUMP(); return 0;static void parse_config(const char *fn, char *s)state.parse_line = parse_line_device;for (;) switch (token) case T_EOF: state.parse_line(&state, 0, 0); return; case T_NEWLINE: if (nargs) tate.parse_line(&state, 0, 0);解析过程中,会去循环解析这个文件,对解析的结果调用state.parse_line,对应的回调函数就是parse_line_device。System/core/init/ueventd_parser.cstatic void parse_line_device(struct parse_state* state, int nargs, char *args) set_device_permission(nargs, args);在set_device_permission(nargs, args)中会获取设备的mode,uid,gid。给设备增加操作权限。然后通过device_init给设备添加创建NETLINK套接字。System/core/init/ueventd.cint 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) if(n = UEVENT_MSG_LEN) /* overflow - discard */ continue; msgn = 0; msgn+1 = 0; struct uevent uevent; parse_event(msg, &uevent); handle_device_event(&uevent); handle_firmware_event(&uevent); 接收的uevent的小心不能超过1024个字节,如果超出就算溢出将不会处理。如果接收的uevent有效,解析这个uevent会根据设备的类型来解析。之后handle_device_event会处理设备的event。而handle_firmware_event则是和某些设备需要firmware回去处理firmware的加载。System/core/init/devices.cstatic void handle_device_event(struct uevent *uevent) if (!strcmp(uevent-action,add) fixup_sys_perms(uevent-path); if (!strncmp(uevent-subsystem, block, 5) handle_block_device_event(uevent); else if (!strncmp(uevent-subsystem, platform, 8) handle_platform_device_event(uevent); else handle_generic_device_event(uevent); 如果event的subsystem为block,说明是个块设备,就会交由handle_block_device_event去处理。或者subsystem是platform设备的话,则有handle_platform_device_event来处理。如果两者都不是的话,说明是一个普通设备,handle_generic_device_event会来处理。块设备和平台设备的处理方式比较特殊,先看一般通用设备的处理过程。System/core/init/devices.cstatic void handle_generic_device_event(struct uevent *uevent)name = parse_device_name(uevent, 64);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的目录,按照这样依次比较下去,创建设备类所需要的子目录。System/core/init/devices.cstatic void handle_device(const char *action, const char *devpath, const char *path, int block, int major, int minor, char *links) if(!strcmp(action, add) make_device(devpath, path, block, major, minor);如果uevent的action是设备添加,就会调用make_device来创建设备节点。System/core/init/devices.cstatic void make_device(const char *path, const char *upath, int block, int major, int minor)mode = get_device_perm(path, &uid, &gi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论