«

Android5.0网络之socket接口的改变

时间:2024-3-2 19:15     作者:韩俊     分类: Android


socket是网络编程的基础,Android中socket接口定义在bionic里面,Android5.0后,为了更好使用fwmark,用netd中的函数实现部分代替了bionic的socket实现。

上代码

bionic/libc/bionic/libc_init_dynamic.cpp

// We flag the __libc_preinit function as a constructor to ensure
 64 // that its address is listed in libc.so's .init_array section.
 65 // This ensures that the function is called by the dynamic linker
 66 // as soon as the shared library is loaded.
 67 __attribute__((constructor)) static void __libc_preinit() {
 68   // Read the kernel argument block pointer from TLS.
 69   void** tls = __get_tls();
 70   KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT];
 71   KernelArgumentBlock* args = *args_slot;  
 72 
 73   // Clear the slot so no other initializer sees its value.
 74   // __libc_init_common() will change the TLS area so the old one won't be accessible anyway.
 75   *args_slot = NULL;
 76 
 77   __libc_init_common(*args);
 78 
 79   // Hooks for various libraries to let them know that we're starting up.
 80   malloc_debug_init();
 81   <span style="background-color: rgb(255, 255, 102);">netdClientInit();</span>                                                                                                                                                     
 82 }
上面的代码在libc动态库加载的时候回执行


bionic/libc/bionic/NetdClient.cpp

template <typename FunctionType>
 28 static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
 29     typedef void (*InitFunctionType)(FunctionType*);
 30     InitFunctionType initFunction = reinterpret_cast<InitFunctionType>(dlsym(handle, symbol));
 31     if (initFunction != NULL) {
 32         initFunction(function);
 33     }
 34 }
 35 
 36 static void netdClientInitImpl() {
 37     void* netdClientHandle = dlopen("libnetd_client.so", RTLD_LAZY);
 38     if (netdClientHandle == NULL) {
 39         // If the library is not available, it's not an error. We'll just use
 40         // default implementations of functions that it would've overridden.
 41         return;
 42     }
 43     netdClientInitFunction(netdClientHandle, "netdClientInitAccept4",
 44                            &__netdClientDispatch.accept4);
 45     netdClientInitFunction(netdClientHandle, "netdClientInitConnect",
 46                            &__netdClientDispatch.connect);
 47     netdClientInitFunction(netdClientHandle, "netdClientInitNetIdForResolv",
 48                            &__netdClientDispatch.netIdForResolv);
 49     netdClientInitFunction(netdClientHandle, "netdClientInitSocket", &__netdClientDispatch.socket);
 50 }
 51 
 52 static pthread_once_t netdClientInitOnce = PTHREAD_ONCE_INIT;
 53 
 54 extern "C" __LIBC_HIDDEN__ void <span style="background-color: rgb(255, 255, 102);">netdClientInit</span>() {
 55     if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
 56         __libc_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
 57     }
 58 }   
上面代码中,netdClientInitFunction最终完成了bionic到netd的映射



下面这段代码就是bionic中提供给上层的接口

bionic/libc/bionic/accept4.cpp

int accept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
 22     return __netdClientDispatch.accept4(sockfd, addr, addrlen, flags);                                                                                                  
 23 }

// This structure is modified only at startup (when libc.so is loaded) and never
 34 // afterwards, so it's okay that it's read later at runtime without a lock.
 35 __LIBC_HIDDEN__ NetdClientDispatch __netdClientDispatch __attribute__((aligned(32))) = {
 36     __accept4,
 37     __connect,
 38     __socket,                                                                                                                                                           
 39     fallBackNetIdForResolv,
 40 };
__accept4等函数是汇编实现,完成到kernel的调用


system/netd/client/NetdClient.cpp

下面代码中netdClientInitAccept4就是bionic/libc/bionic/NetdClient.cpp中netdClientInitFunction中的参数netdClientInitAccept4,这样就完成了bionic到netd的映射

// accept() just calls accept4(..., 0), so there's no need to handle accept() separately.
139 extern "C" void netdClientInitAccept4(Accept4FunctionType* function) {
140     if (function && *function) {
141         libcAccept4 = *function;
142         *function = netdClientAccept4;
143     }   
144 }   
145 
146 extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
147     if (function && *function) {
148         libcConnect = *function;
149         *function = netdClientConnect;                                                                                                                                  
150     }                      
151 }   
152 
153 extern "C" void netdClientInitSocket(SocketFunctionType* function) {
154     if (function && *function) {
155         libcSocket = *function;
156         *function = netdClientSocket;
157     }
158 }       
159     
160 extern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) {
161     if (function) {
162         *function = getNetworkForResolv;
163     }
164 }


system/netd/client/NetdClient.cpp

下面是netd中accept4的实现,可以看到最终通过FwmarkServer对socket做mark

int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
 52     int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags);
 53     if (acceptedSocket == -1) {
 54         return -1;
 55     }
 56     int family;                                                                                                                                                         
 57     if (addr) {
 58         family = addr->sa_family;
 59     } else {
 60         socklen_t familyLen = sizeof(family);
 61         if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) {
 62             return closeFdAndSetErrno(acceptedSocket, -errno);
 63         }
 64     }
 65     if (FwmarkClient::shouldSetFwmark(family)) {
 66         FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0};
 67         if (int error = FwmarkClient().send(&command, sizeof(command), acceptedSocket)) {
 68             return closeFdAndSetErrno(acceptedSocket, error);
 69         }
 70     }
 71     return acceptedSocket;
 72 }


标签: android

热门推荐