Android: 在 init.rc 中套接字的创建和使用简析

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. init.rc中套接字的创建和使用

在Android中,我们可以在 init.rc 中,通过脚本片段

service xxx ...
   		...
   		socket sock_xxx stream 0666 root system
   		...

指示 init 进程创建套接字,然后供用户使用。

2.1 init 进程创建套接字流程

/* 解析 init.rc ,记录要创建的 socket 的列表 */
parse_line_service() /* system/core/init/init_parser.c */
	...
   		switch (kw) {
   		case K_socket:
   			struct socketinfo *si;
   		
   			si = calloc(1, sizeof(*si));
   			
   			si->name = args[1];
        	si->type = args[2];
        	si->perm = strtoul(args[3], 0, 8);
        	if (nargs > 4)
            	si->uid = decode_uid(args[4]);
        	if (nargs > 5)
            	si->gid = decode_uid(args[5]);
        	if (nargs > 6)
            	si->socketcon = args[6];
        	si->next = svc->sockets;
        	svc->sockets = si;
   			break;
   		...
   		}
   		...
/* 创建 socket */
service_start() /* system/core/init/init.c */
	...
	for (si = svc->sockets; si; si = si->next) {
		int socket_type = (!strcmp(si->type, "stream") ? SOCK_STREAM :
                          (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
		int s = create_socket(si->name, socket_type, si->perm, si->uid, si->gid, si->socketcon ?: scon);
		...
		fd = socket(PF_UNIX, type, 0) /* 创建 UNIX domain 套接字 */
		bind(fd, (struct sockaddr *) &addr, sizeof (addr))
		
		/* 导出 UNIX 套接字:创建文件 /dev/socket/ANDROID_SOCKET_xxx */
		publish_socket(si->name, s)
			/*
        	 * 添加一个套接字环境变量
        	 * key: ANDROID_SOCKET_xxx
        	 * val: 套接字的文件句柄
        	 */
        	...
        	add_environment(key, val) /* 后面的程序(具体是service daemon) 使用这个环境变量来获取套接字句柄 */           
	}
	...

2.2 使用套接字

要使用套接字的地方,调用 android_get_control_socket() 获取对应 init.rc 中命名的 sock_xxx 套接字的句柄。

android_get_control_socket() /* system/core/include/cutils/sockets.h */
	 char key[64] = ANDROID_SOCKET_ENV_PREFIX;
	 const char *val;
	 int fd;
	
	/* build our environment variable, counting cycles like a wolf ... */
#if HAVE_STRLCPY
	strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
	        name,
	        sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
	#else   /* for the host, which may lack the almightly strncpy ... */
	strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
	        name,
	        sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
	    key[sizeof(key)-1] = '\0';
	#endif
	
	val = getenv(key); /* socket 套接字句柄字串 */
	if (!val)
		return -1;
	
	errno = 0;
	fd = strtol(val, NULL, 10); /* socket 套接字句柄 */
	if (errno)
		return -1;
	
	return fd;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值