android local native socket

来源:互联网 发布:网络摄像机通用软件 编辑:程序博客网 时间:2024/05/21 08:39


一、socket

 面向连接的协议(如TCP)的套接字系统调用过程:


  图片来源于:http://blog.csdn.net/hguisu/article/details/7444092

  linux socket 编程参考:http://blog.csdn.net/hguisu/article/details/7445768


二、android local native socket 

1、启动阶段创建local native socket server

\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);
}

2、获取init进程启动阶段创建的local native socket server :

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;
}

3、创建local native socket client

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;
}

4、创建local native socket server

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等接口。 


0 0
原创粉丝点击