【翻译】(16)Bionic Overview

-----------------

英文文档见android-ndk-r6b的documentation.html

属于Android Native Development Kit (NDK)的一部分

http://developer.android.com/sdk/ndk/index.html

翻译仅个人见解

-----------------

 

Bionic C Library Overview:

 

Bionic C库概述:

==========================

 

Introduction:

 

介绍:

 

Core Philosophy:

 

核心哲学:

 

  The core idea behind Bionic's design is: KEEP IT REALLY SIMPLE.

 

  Bionic的设计背后的核心理念是:让它真正地简单。

 

  This implies that the C library should only provide lightweight wrappers around kernel facilities and not try to be too smart to deal with edge cases.

 

  这暗示着C库应该只提供对内核设施的轻量级封装,并且不要尝试太智能地处理边缘条件(注:即边际问题,极端条件)。

 

  The name "Bionic" comes from the fact that it is part-BSD and part-Linux: its source code consists of a mix of BSD C library pieces with custom Linux-specific bits used to deal with threads, processes, signals and a few others things.

 

  Bionic的名称(注:中文意思是“仿生学的”)来源于它是半BSD半Linux的事实:它的源码由BSD C库片段,混合了定制的特定于Linux的片段组成,用于处理线程、进程、信号,和其它少数东西。

 

  All original BSD pieces carry the BSD copyright disclaimer. Bionic-specific bits carry the Android Open Source Project copyright disclaimer. And everything is released under the BSD license.

 

  所有原来的BSD片段带有BSD版权的免责声明。特定于Bionic的片段带有Android开放源码项目版权的免责声明。并且所有东西都在BSD许可证下发布。

 

Architectures:

 

架构:

 

  Bionic currently supports the ARM and x86 instruction sets. In theory, it should be possible to support more, but this may require a little work (e.g. adding system call IDs to SYSCALLS.html, described below, or modifying the dynamic linker).

 

  Bionic当前支持ARM和x86指令集。理论上,它应该可以支持更多CPU类型,但这可能需要小许工作(例如,添加系统调用ID到SYSCALLS.html,下面会描述,或者修改动态链接器)。(注:SYSCALLS.html,这里的原意是指源码树下bionic/libc/SYSCALLS.TXT这个文件,当它并没有打包到NDK的发布包中,如果感兴趣可以取官方的bionic代码或到github搜索bionic代码。下文每当提到SYSCALLS.html实际上也是指SYSCALLS.TXT)

 

  The ARM-specific code is under arch-arm/ and the x86-specific one is under arch-x86/

 

  ARM特定代码在arch-arm/目录下,而x86特定代码在arch-x86/目录下。(注:因为这个文档原来是在Android源码树的bionic目录下,所以NDK发布包里没有这些代码,下同)

 

  Note that the x86 version is only meant to run on an x86 Android device. We make absolutely no claim that you could build and use Bionic on a stock x86 Linux distribution (though that would be cool, so patches are welcomed :-))

 

  注意x86版本只针对运行在x86的Android设备而言。我们绝不敢断言你可以在一个常规x86 Linux分发版上构建和使用Bionic(但是那样子很酷,所以欢迎打补丁:-))

 

Syscall stubs:

 

系统调用插桩:

 

  Each system call function is implemented by a tiny assembler source fragment (called a "syscall stub"), which is generated automatically by tools/gensyscalls.py which reads the SYSCALLS.html file for input.

 

  每个系统调用函数由很小的汇编源码片段实现(称为“系统调用插桩”),它是由tools/gensyscalls.py自动生成,读取SYSCALLS.html文件作为输入。

 

  SYSCALLS.html contains the list of all syscall stubs to generate, along with the corresponding syscall numeric identifier (which may differ between ARM and x86), and its signature

 

  SYSCALLS.html包含所有要生成的系统调用插桩的列表,以及相应系统调用的数字标识符(ARM和x86的可能不同),以及其签名。

 

  If you modify this file, you may want to use tools/checksyscalls.py which checks its content against official Linux kernel header files, and will report errors when invalid syscall ids are used.

 

  如果你修改这个文件,你可能想要使用tools/checksyscalls.py,它根据官方Linux内核头文件检查其内容,如果其中使用了非法的系统调用ID就报告错误。

 

  Sometimes, the C library function is really a wrapper that calls the corresponding syscall with another name. For example, the exit() function is provided by the C library and calls the _exit() syscall stub.

 

  有时,C库函数其实是换另一个名称调用相应系统调用的封装函数。例如C库提供的exit()函数,它调用_exit系统调用插桩。

 

  See SYSCALLS.html for documentation and details.

 

  文档和详细信息请查看SYSCALLS.html。

 

time_t:

 

time_t:

 

  time_t is 32-bit as defined by the kernel on 32-bit CPUs. A 64-bit version would be preferable to avoid the Y2038 bug, but the kernel maintainers consider that this is not needed at the moment.

 

  time_t是在32位CPU上,由内核定义的32位类型。一个64位版本将更好,以避免Y2038缺陷(注:Y2038问题是指由于time_t的长度问题导致系统无法正确表示2038年以后的时间。大多数64位机器可以避免这个问题),但内核维护者认为现在没必要。

 

  Instead, Bionic provides a <time64.h> header that defines a time64_t type, and related functions like mktime64(), localtime64(), etc...

 

  取而代之的是,Bionic提供一个<time64.h>头文件,定义了time64_t类型,以及相关的函数如mktime64(),localtime64(),等等……

 

Timezone management:

 

时区管理:

 

  The name of the current timezone is taken from the TZ environment variable, if defined. Otherwise, the system property named 'persist.sys.timezone' is checked instead.

 

  当前时区的名称从TZ环境变量中取,如果它被定义了的话。否则,改为检查名为persist.sys.timezone的系统属性。(注:系统属性是Android的概念,见下)

 

  The zoneinfo timezone database and index files are located under directory /system/usr/share/zoneinfo, instead of the more Posix-compliant path of /usr/share/zoneinfo

 

  zoneinfo时区数据库及索引文件位于目录/system/usr/share/zoneinfo下,而非更加兼容Posix的路径/usr/share/zoneinfo。

 

off_t:

 

off_t:

 

  For similar reasons, off_t is 32-bit. We define loff_t as the 64-bit variant due to BSD inheritance, but off64_t should be available as a typedef to ease porting of current Linux-specific code.

 

  由于类似的原因,off_t是32位的。我们定义loff_t作为64位版本,以继承BSD的习惯,但off64_t应该可用,作为一个typedef以减轻当前Linux特定代码的移植。

 

Linux kernel headers:

 

Linux内核头文件:

 

  Bionic comes with its own set of "clean" Linux kernel headers to allow user-space code to use kernel-specific declarations (e.g. IOCTLs, structure declarations, constants, etc...). They are located in:

 

  Bionic带有它自己的“干净的”Linux内核头文件,以允许用户空间代码使用特定于内核的声明(例如IOCTL,结构体声明,常量,等等……)。它们位于以下目录:

 

     ./kernel/common,

     ./kernel/arch-arm

     ./kernel/arch-x86

 

  These headers have been generated by a tool (kernel/tools/update-all.py) to only include the public definitions from the original Linux kernel headers.

 

  这些头文件已经用工具生成了(kernel/tools/update-all.py),使其只包含来自原来Linux内核头文件的公共定义。

 

  If you want to know why and how this is done, read kernel/README.TXT to get all the (gory) details.

 

  如果你想知道为什么和如何做这件事,请阅读kernel/README.TXT以获得所有(血腥的)细节。(注:Android源码树的bionic\libc\kernel\README.TXT文件中RATIONALE部分提到,Linux内核维护者不愿意大幅度修改内核的头文件,这些修正工作一般交由Linux分发版的打包者来做,而Android底层开发者认为最好的方法是用自动工具彻底改掉这些头文件在用户编译时产生的bug)

 

PThread implementation:

 

PThread实现:

 

   Bionic's C library comes with its own pthread implementation bundled in. This is different from other historical C libraries which:

 

   Bionic的C库来自它自己捆绑的pthread实现。不同于其它历史上的C库的以下做法:

 

    - place it in an external library (-lpthread)

 

    - 把它放在外部库(-lpthread编译选项)。

 

    - play linker tricks with weak symbols at dynamic link time

 

    - 玩链接器技巧,在链接期使用弱符号。

 

   The support for real-time features (a.k.a. -lrt) is also bundled in the C library.

 

   实时特性的支持(即-lrt)也被捆绑到C库中。

 

   The implementation is based on futexes and strives to provide *very* short code paths for common operations. Notable features are the following:

 

   它的实现是基于futex(注:快速用户空间互斥锁),并且努力为公共操作提供非常短的代码路径(注:这里的code path应该是指多线程下机器码的执行轨迹,下同)。值得注意的特性如下:

 

      - pthread_mutex_t, pthread_cond_t are only 4 bytes each.

 

      - pthread_mutex_t(注:对应互斥锁的类型),pthread_cond_t(注:对应条件变量的类型)每个只占4字节。

 

      - Normal, recursive and error-check mutexes are supported, and the code path is heavily optimized for the normal case, which is used most of the time.

 

      - 支持正常的、递归的和检查错误的mutex(注:互斥锁),而且代码路径在正常情况下被大幅度优化,用于大部分时候。

 

      - Process-shared mutexes and condition variables are not supported. Their implementation requires far more complexity and was absolutely not needed for Android (which uses other inter-process synchronization capabilities).

 

      - 不支持进程间共享的mutex和条件变量。它们需要远比原来复杂的实现,而且Android完全不需要它们(Android使用其它进程间同步能力)

 

        Note that they could be added in the future without breaking the ABI by specifying more sophisticated code paths (which may make the common paths slightly slower though).

 

        注意未来可能添加这些机制,但不会通过指定更复杂的代码路径来打破这些ABI(虽然可能会使公共路径稍微变慢)。

 

      - There is currently no support for read/write locks, priority-ceiling in mutexes and other more advanced features. Again, the main idea being that this was not needed for Android at all but could be added in the future.

 

      - 当前不支持读写锁,mutex的优先级上限和其它更多先进特性。再一次重申,主要想法是,Android完全不需要它,但未来可能会添加它。

 

pthread_cancel():

 

pthread_cancel():(注:pthread_cancel用于请求取消线程的执行,见https://computing.llnl.gov/tutorials/pthreads/man/pthread_cancel.txt)

 

   pthread_cancel() will *not* be supported in Bionic, because doing this would involve making the C library significantly bigger for very little benefit.

 

   Bionic将不会支持pthread_cancel(),因为这样做会因为很小的利益而造成C库显著变大。

 

   Consider that:

 

   考虑以下理由:

 

     - A proper implementation must insert pthread cancellation checks in a lot of different places of the C library. And conformance is very difficult to test properly.

 

     - 一个合理的实现必须在C库的许多不同地方插入pthread取消检查。合理地测试一致性是非常困难的。

 

     - A proper implementation must also clean up resources, like releasing memory, or unlocking mutexes, properly if the cancellation happens in a complex function (e.g. inside gethostbyname() or fprintf() + complex formatting rules). This tends to slow down the path of many functions.

 

     - 一个合理的实现也必须清理资源,像释放资源,或者如果取消发生在一个复杂的函数中,能合理地解锁mutex(例如在gethostbyname()或fprintf()加上复杂的格式化规则的情况下)。这样做会致使许多函数的执行路径被减慢。

 

     - pthread cancellation cannot stop all threads: e.g. it can't do anything against an infinite loop

 

     - pthread的取消操作不能阻止所有线程:例如,它无法对一个无限循环的线程起作用。

 

     - pthread cancellation itself has short-comings and isn't very portable (see http://advogato.org/person/slamb/diary.html?start=49 for example).

 

     - pthread的取消操作本身有缺点,并且不是太容易移植(例子见http://advogato.org/person/slamb/diary.html?start=49)

 

   All of this is contrary to the Bionic design goals. If your code depends on thread cancellation, please consider alternatives.

 

   所有这些理由都背离了Bionic的设计目标。如果你的代码依赖于线程取消,请考虑其它替换品。

 

   Note however that Bionic does implement pthread_cleanup_push() and pthread_cleanup_pop(), which can be used to handle cleanups that happen when a thread voluntarily exits through pthread_exit() or returning from its main function.

 

   然而,注意Bionic实现了pthread_cleanup_push()和pthread_cleanup_pop(),它们用于在线程自行通过pthread_exit()退出,或从它自己的主函数返回时,处理清理工作。(注:pthread_cleanup_push和pthread_cleanup_pop的作用是定义一个代码范围,让线程退出时执行pthread_cleanup_push的参数指定的回调,行为类似一个栈)

 

pthread_once():

 

pthread_once():(注:pthread_once用于让多个线程在执行同一操作时只执行最多一次,一般用来初始化,见https://computing.llnl.gov/tutorials/pthreads/man/pthread_once.txt)

 

  Do not call fork() within a callback provided to pthread_once(). Doing this may result in a deadlock in the child process the next time it calls pthread_once().

 

  不要在提供给pthread_once()的回调中调用fork()。这样做可能在子进程内下一次调用pthread_once()时导致死锁。

 

  Also, you can't throw a C++ Exception from the callback (see C++ Exception Support below).

 

  同样,你不能从回调中抛出C++异常(见下面的C++异常支持)。

 

  The current implementation of pthread_once() lacks the necessary support of multi-core-safe double-checked-locking (read and write barriers).

 

  当前pthread_once()的实现缺少多核安全的双检查锁定的必要支持(读写壁垒)。(注:双检查锁定,缩写为DCL,常用于单实例的延迟初始化。这里的读写壁垒是指,强行让多核对内存的操作按原有的顺序执行,避免因为CPU的优化策略导致线程问题,在C#中有专门的方法叫MemoryBarrier,详细见http://en.wikipedia.org/wiki/Double-checked_locking)

 

Thread-specific data

 

线程特定数据

 

  The thread-specific storage only provides for a bit less than 64 pthread_key_t objects to each process. The implementation provides 64 real slots but also uses about 5 of them (exact number may depend on implementation) for its own use (e.g. two slots are pre-allocated by the C library to speed-up the Android OpenGL sub-system).

 

  线程特定存储只给每个进程提供少于64个pthread_key_t对象。实现提供64个真实槽位,而且用了其中大概5个(具体数字可能依赖于实现)供它自己使用(例如两个槽位是由C库预分配的,以加速Android的OpenGL子系统)。

 

  Note that Posix mandates a minimum of 128 slots, but we do not claim to be Posix-compliant.

 

  注意Posix规定最小128个槽,但我们不需要兼容Posix。(注:Posix是Unix可移植操作系统接口的缩写)

 

  Except for the main thread, the TLS area is stored at the top of the stack. See comments in bionic/libc/bionic/pthread.c for details.

 

  除了主线程,TLS(注:线程局部存储的缩写,线程局部存储是指保存局部于某个线程的静态或全局数据的内存区域)区域被分配在栈顶。详细请参考bionic/libc/bionic/pthread.c里的注释。

 

  At the moment, thread-local storage defined through the __thread compiler keyword is not supported by the Bionic C library and dynamic linker.

 

  到目前,Bionic C库及动态链接器不支持通过__thread编译器关键字定义的线程局部存储。

 

Multi-core support

 

多核支持

 

  At the moment, Bionic does not provide or use read/write memory barriers. This means that using it on certain multi-core systems might not be supported, depending on its exact CPU architecture.

 

  到目前,Bionic不提供或使用读写内存壁垒(注:是指一种约束内存访问的机制,用于双检查锁定。详细见前)。这意味着在某些多核系统可能不被支持使用它,依赖于它具体的CPU架构。

 

Android-specific features:

 

Android特定的特性:

 

  Bionic provides a small number of Android-specific features to its clients:

 

  Bionic提供少数特定于Android的特性给它的客户端:

 

  - access to system properties:

 

  - 系统属性的访问:

 

       Android provides a simple shared value/key space to all processes on the system. It stores a liberal number of 'properties', each of them being a simple size-limited string that can be associated to a size-limited string value.

 

       Android提供简单的共享值/键空间给系统的所有进程。它保存有任意个数的属性,它们中每一对是有大小限制的字符串,关联到一个有大小限制的字符串值。

 

       The header <sys/system_properties.h> can be used to read system properties and also defines the maximum size of keys and values.

 

       头文件<sys/system_properties.h>可用于读取系统属性,并且定义了键和值的最大长度。

 

   - Android-specific user/group management:

 

   - Android特定的用户/组管理:

 

       There is no /etc/passwd or /etc/groups in Android. By design, it is meant to be used by a single handset user. On the other hand, Android uses the Linux user/group management features extensively to secure process permissions, like access to various filesystem directories.

 

       Android中没有/etc/passwd或/etc/groups。设计上,这意味着只用于单手机用户。另一方面,Android引申Linux的用户/组管理特性,用于安全进程权限,像对不同文件系统目录的访问。

 

       In the Android scheme, each installed application gets its own uid_t/gid_t starting from 10000; lower numerical ids are reserved for system daemons.

 

       在Android的计划中,每个安装的应用个程序获取它自己的uid_t/gid_t,值始于10000;低于10000的ID数保留给系统的后台进程。

 

       getpwnam() recognizes some hard-coded subsystems names (e.g. "radio") and will translate them to their low-user-id values. It also recognizes "app_1234" as the synthetic name of the application that was installed with uid 10000 + 1234, which is 11234. getgrnam() works similarly

 

       getpwnam()识别一些硬编码的子系统名称(例如“radio”)并且把它们翻译成它们的低用户ID值。还会把app_1234识别为所安装的应用程序的组合名称,uid为10000 + 1234,即11234。getgrnam()也是类似地工作。(注:getpwnam用于在用户数据库中搜索用户名)

 

       getgrouplist() will always return a single group for any user name, which is the one passed as an input parameter.

 

       getgrouplist()将总是对作为输入参数传入的任意用户名,返回单个组。(注:Linux上getgrouplist用于获取指定用户的组访问列表)

 

       getgrgid() will similarly only return a structure that contains a single-element members list, corresponding to the user with the same numerical value than the group.

 

       类似地getgrgid()将只返回一个结构体,包含单元素的成员列表,对应使用相同数值的用户而非组。(注:Linux上getgrgid用于从组数据库中获取组ID)

 

       See bionic/libc/bionic/stubs.c for more details.

 

       更详细信息请参考bionic/libc/bionic/stubs.c

 

    - getservent()

 

    - getservent()(注:Linux上用于读取/etc/services的下一行)

 

       There is no /etc/services on Android. Instead the C library embeds a constant list of services in its executable, which is parsed on demand by the various functions that depend on it. See bionic/libc/netbsd/net/getservent.c and bionic/libc/netbsd/net/services.h

 

       Android上没有/etc/services文件。取而代之的是在C库中把一个服务常量表嵌入到它的可执行文件中,根据需要它被依赖于它的几个函数解析。参考See bionic/libc/netbsd/net/getservent.c和bionic/libc/netbsd/net/services.h。

 

       The list of services defined internally might change liberally in the future. This feature is mostly historically and is very rarely used.

 

       内部定义的服务列表未来可能会较宽松地改变。这个特性更多是历史性的而且很少用。

 

       The getservent() returns thread-local data. getservbyport() and getservbyname() are also implemented in a similar fashion.

 

       getservent()返回线程局部数据。getservbyport()和getservbyname()也是使用类似的方式实现。

 

     - getprotoent()

 

     - getprotoent()(注:Linux上用于读取/etc/protocols的下一行)

 

       There is no /etc/protocol on Android. Bionic does not currently implement getprotoent() and related functions. If added, it will likely be done in a way similar to getservent()

 

       在Android上没有/etc/protocol。现时Bionic不实现getprotoent()和相关函数。如果增加了,它将很可能以类似getservent()的方式工作。

 

DNS resolver:

 

DNS(注:域名系统的缩写)解析器

 

  Bionic uses a NetBSD-derived resolver library which has been modified in the following ways:

 

  Bionic使用NetBSD衍生的解析器库,它用以下方式被修改:

 

     - don't implement the name-server-switch feature (a.k.a. <nsswitch.h>)

 

     - 没有实现命名服务开关(注:应作Name Service Switch,缩写为NSS)特性(即<nsswitch.h>)

 

     - read /system/etc/resolv.conf instead of /etc/resolv.conf

 

     - 读取/system/etc/resolv.conf而非/etc/resolv.conf

 

     - read the list of servers from system properties. the code looks for 'net.dns1', 'net.dns2', etc.. Each property should contain the IP address of a DNS server.

 

     - 从系统属性中读取服务器列表。代码寻找'net.dns1','net.dns2'等等……每个属性应该包含DNS服务器的IP地址。

 

       these properties are set/modified by other parts of the Android system (e.g. the dhcpd daemon).

 

       这些属性被Android系统的其它部件设置或修改(例如dhcpd后台程序)。

 

       the implementation also supports per-process DNS server list, using the properties 'net.dns1.<pid>', 'net.dns2.<pid>', etc... Where <pid> stands for the numerical ID of the current process.

 

       实现还支持逐个进程的DNS服务器列表,使用属性'net.dns1.<pid>', 'net.dns2.<pid>',等等……这里<pid>代表当前进程的数字ID。

 

     - when performing a query, use a properly randomized Query ID (instead of a incremented one), for increased security.

 

     - 每当执行一次请求,合理地使用一个随机查询ID(而非递增),以增强安全性。

 

     - when performing a query, bind the local client socket to a random port for increased security.

 

     - 当执行一个请求,绑定本地客户端套接字到一个随机端口,以增强安全性。

 

     - get rid of *many* unfortunate thread-safety issues in the original code

 

     - 避免在原始代码中许多不合理的线程安全问题。

 

  Bionic does *not* expose implementation details of its DNS resolver; the content of <arpa/nameser.h> is intentionally blank. The resolver implementation might change completely in the future.

 

  Bionic不会暴露它的DNS解析器的实现细节;<arpa/nameser.h>的内容是故意空白的。解析器的实现可能在未来完全改变。

 

PThread Real-Time Timers:

 

PThread实时定时器:

 

  timer_create(), timer_gettime(), timer_settime() and timer_getoverrun() are supported.

 

  支持timer_create(), timer_gettime(), timer_settime()和timer_getoverrun()。

 

  Bionic also now supports SIGEV_THREAD real-time timers (see timer_create()). The implementation simply uses a single thread per timer, unlike GLibc which uses complex heuristics to try to use the less threads possible when several timers with compatible properties are used.

 

  现在Bionic还支持SIGEV_THREAD实时定时器(见timer_create())。实现简单地对每个定时器使用一个单线程,而不像GLibc那样使用复杂的启发式机制以尝试在使用几个带兼容属性的定时器时用尽可能少的线程。(注:启发式,是指计算机程序根据某些特征进行相应的调整)

 

  This means that if your code uses a lot of SIGEV_THREAD timers, your program may consume a lot of memory. However, if your program needs many of these timers, it'd better handle timeout events directly instead.

 

  这意味着如果你的代码使用许多SIGEV_THREAD定时器,你的程序会消耗很多内存。然而,如果你的程序需要许多这样的定时器,最好改为直接处理超时事件。

 

  Other timers (e.g. SIGEV_SIGNAL) are handled by the kernel and use much less system resources.

 

  其它定时器(例如SIGEV_SIGNAL)由内核处理,以使用非常少的系统资源。

 

Binary Compatibility:

 

二进制兼容性:

 

  Bionic is *not* in any way binary-compatible with the GNU C Library, ucLibc or any known Linux C library. This means several things:

 

  Bionic和GNU C库、ucLibc或任何已知Linux C库完全不是二进制兼容的。(注:所谓二进制兼容,是指不需要重新编译就可以跨操作系统运行某个程序)。这意味着几件事:

 

  - You cannot expect to build something against the GNU C Library headers and have it dynamically link properly to Bionic later.

 

  - 你不能期待用GNU C库头文件构建一些东西,并且让它稍后会正确地动态链接到Bionic。

 

  - You should *really* use the Android toolchain to build your program against Bionic. The toolchain deals with many important details that are crucial to get something working properly.

 

  - 事实上你应该使用Android工具链构建你的程序到Bionic上。工具链会处理许多对于让一些事情正确地工作很关键的重要细节。

 

  Failure to do so will usually result in the inability to run or link your program, or even runtime crashes. Several random web pages on the Internet describe how you can successfully write a "hello-world" program with the ARM GNU toolchain. These examples usually work by chance, if anything else, and you should not follow these instructions unless you want to waste a lot of your time in the process.

 

  通常不这样做将导致运行或链接你的程序失败,甚至在运行期崩溃。在互联网上随便找几个网页都会描述如何成功地用ARM GNU工具链书写hello-world程序。这些例子一般会偶尔成功,如果是其他东西,那么你不应该跟从那些指示,除非你想浪费大量时间在问题的处理上。

 

  Note however that you *can* generate a binary that is built against the GNU C Library headers and then statically linked to it. The corresponding executable should be able to run (if it doesn't use dlopen()/dlsym())

 

  注意,然而你可以生成一个二进制文件,用GNU C库头文件来构建,然后静态链接它。对应的可执行文件应该可以操作(如果它不使用dlopen()/dlsym())(注:dlopen用于打开动态库,dlsym用于从动态库中获取符号的地址或函数指针)

 

Dynamic Linker:

 

动态链接器:

 

  Bionic comes with its own dynamic linker (just like ld.so on Linux really comes from GLibc). This linker does not support all the relocations generated by other GCC ARM toolchains.

 

  Bionic有它自己的动态链接器(就像出自GLibc的ld.so)。这个链接器不支持其它GCC ARM工具链生成的所有重定位(注:重定位是指在程序运行前把名称的符号引用替换为内存的实际地址)。

 

C++ Exceptions Support:

 

C++异常支持:

 

  At the moment, Bionic doesn't support C++ exceptions, what this really means is the following:

 

  现在,Bionic不支持C++异常,这事实上意味着以下内容:

 

    - If pthread_once() is called with a C++ callback that throws an exception, then the C library will keep the corresponding pthread_once_t mutex locked. Any further call to pthread_once() will result in a deadlock.

 

    - 如果pthread_once()被一个抛异常的C++回调调用,那么C库将一直让对应的pthread_once_t互斥量锁住。任何对pthread_once()的进一步调用将导致死锁。

 

      A proper implementation should be able to register a C++ exception cleanup handler before the callback to properly unlock the pthread_once_t. Unfortunately this requires tricky assembly code that is highly dependent on the compiler.

 

      一个合适的实现应该能在回调之前注册一个C++异常的清除句柄以合理地解锁pthread_once_t。很不幸这需要巧妙而且高度依赖于编译器的汇编码。

 

      This feature is not planned to be supported anytime soon.

 

      这个特性最近不会计划去做。

 

    - The same problem may arise if you throw an exception within a callback called from the C library. Fortunately, these cases are very rare in the real-world, but any callback you provide to the C library should *not* throw an exception.

 

    - 如果你在一个从C库中调用的回调中抛出异常的话,相同的问题也会发生。幸运地,这些情况在真实世界中很少见,但你提供给C库的任何回调都不应该抛异常。

 

    - Bionic lacks a few support functions to have exception support work properly.

 

    - Bionic缺乏一些能使异常支持正常工作的支持函数。

 

System V IPCs:

 

系统五进程间通信:

 

  Bionic intentionally does not provide support for System-V IPCs mechanisms, like the ones provided by semget(), shmget(), msgget(). The reason for this is to avoid denial-of-service. For a detailed rationale about this, please read the file docs/SYSV-IPCS.html.

 

  Bionic故意不提供系统五进程间通信机制,如semget(),shmget(),msgget()提供的机制。这样做的理由是避免拒绝服务攻击。关于这个问题的详细解释,请阅读文件docs/SYSV-IPCS.html。(注:semget用于获取信号量,shmget用于获取共享内存,msgget用于获取消息队列)

 

Include Paths:

 

包含路径:

 

  The Android build system should automatically provide the necessary include paths required to build against the C library headers. However, if you want to do that yourself, you will need to add:

 

  Android构建系统会自动地提供使用C库头文件构建所需的必要包含路径。然而,如果你想自己做,你将需要添加:

 

      libc/arch-$ARCH/include

      libc/include

      libc/kernel/common

      libc/kernel/arch-$ARCH

 

  to your C include path.

 

  到你的C包含路径。(注:编译器的-I选项)

 

 

你可能感兴趣的:(view)