Android设备目录和节点的创建

    在编写linux设备驱动程序的时候,很多时候都是利用mknod命令来手动创建设备节点的,带上名字和主次设备号就可以在/dev目录下生成设备节点。同样Android沿用了linux内核,很多设备驱动的节点是又是什么时候创建的呢? 

    在kernel自解压模块加载完成之后,会去运行android第一个应用程序init。在init.c的main函数中。


System/core/init/init.c 
int main(int argc, char **argv) 
{ 
	…… 
	action_for_each_trigger("boot", action_add_queue_tail); 
	…… 
}

    在init进程解析init.rc脚本完成后,在onboot的最后两句是classstart maincore,其中class

    Start是命令,在keyword.h中定义了class_start对应的function实际就是do_class_start

System/core/init/builtins.c
int do_class_start(int nargs, char **args)
{
	service_for_each_class(args[1], service_start_if_not_disabled);
	return 0;
}

System/core/init/init_parser.c
void 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_classfunc(svc),也就是service_start_if_not_disabled

System/core/init/builtins.c
static 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
	critical

    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.${hardware}.rc。

System/core/init/devices.c
void handle_device_fd()
{
……
	char msg[UEVENT_MSG_LEN+2];
	int  n; 
	while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
		if(n >= UEVENT_MSG_LEN)   /* overflow -- discard */
			continue;

		msg[n] = '\0';
		msg[n+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.c
static 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);
	}
}
   

    首先得到设备的名字,然后是创建一些设备的子目录,如果uevent->subsystem是usb,就需要创建一个/dev/bus/usb的目录。如果是uevent->subsystem是graphic的话,就需要创建一个/dev/graphics的目录,按照这样依次比较下去,创建设备类所需要的子目录。

System/core/init/devices.c
static 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.c
static void make_device(const char *path, const char *upath,  int block, int major, int minor)
{
	……
	mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
	dev = makedev(major, minor);
	setegid(gid);
	mknod(path, mode, dev);
	chown(path, uid, -1);
	setegid(AID_ROOT);
}

    通过get_device_perm得到设备的访问权限,makedev根据主设备号和次设备号得到dev。设置临时setegid,然后又mknod就在设备相应的目录下面创建了设备节点。最后将设备的egid设备为AID_ROOT。到这里整个android的设备目录和节点就创建完成了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值