面向连接的协议(如TCP)的套接字系统调用过程:
图片来源于:http://blog.csdn.net/hguisu/article/details/7444092
linux socket 编程参考:http://blog.csdn.net/hguisu/article/details/7445768
\system\core\rootdir\init.rc中:
service installd /system/bin/installd
class main
socket installd stream 600 system system
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
socket cryptfs stream 0660 root mount
在启动install,vold等服务时,同时会创建socket server ,即socket device :dev/socket/installd, dev/socket/vold , dev/socket/xxx
system/core/init/util.c
这些都是在开机初始化化init进程中启动service时完成:
service_start
create_socket
publish_socket
int create_socket(const char *name, int type, mode_t perm, uid_t uid,
gid_t gid, const char *socketcon)
{
struct sockaddr_un addr;
int fd, ret;
char *filecon;
if (socketcon)
setsockcreatecon(socketcon);
fd = socket(PF_UNIX, type, 0); // create local socket ,get fd
if (fd < 0) {
ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
return -1;
}
if (socketcon)
setsockcreatecon(NULL);
// init
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX; // local socket
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", // 本地socket device address : dev/socket/xxxx
name);
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)) // bind socket fd to local socket addr
if (ret) {
ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
goto out_unlink;
}
setfscreatecon(NULL);
freecon(filecon);
chown(addr.sun_path, uid, gid);
chmod(addr.sun_path, perm);
INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
addr.sun_path, perm, uid, gid);
return fd;
}
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val); //将create_socket创建的socket添加到环境变量中。
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
init进程创建的socket server , android native层提供了接口函数根据socket name获取相对应的socket fd。
然后server端继续listen, accept操作。
sockets.h
static inline int android_get_control_socket(const char *name)
{
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 name 从环境变量获取已创建的socket的fd 。
if (!val)
return -1;
errno = 0;
fd = strtol(val, NULL, 10);
if (errno)
return -1;
return fd;
}
system\core\libcutils\socket_local_client.c
nt socket_local_client(const char *name, int namespaceId, int type)
{
int s;
s = socket(AF_LOCAL, type, 0);
if(s < 0) return -1;
if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
close(s);
return -1;
}
return s;
}
system\core\libcutils\socket_local_server.c
int socket_local_server(const char *name, int namespace, int type)
{
int err;
int s;
s = socket(AF_LOCAL, type, 0);
if (s < 0) return -1;
err = socket_local_server_bind(s, name, namespace);
if (err < 0) {
close(s);
return -1;
}
if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
int ret;
ret = listen(s, LISTEN_BACKLOG);
if (ret < 0) {
close(s);
return -1;
}
}
return s;
}
以上这些接口在android native层编程时,可以直接方便地使用。省去调用socket,bind等接口。