小组人员移植ntfs-3g碰到lseek越界问题,经过查证其使用了llseek函数导致死机的问题。
其实问题很简单:
调用处: llseek (int, unsigned long, unsigned long, loff_t*, int);
但是在android bionic中将其对应到函数lseek,其函数声明如下:
off_t lseek(int, off_t, int); 这个函数只支持32位的offset偏移,应该使用如下函数:
loff_t lseek64(int, loff_t, int); 这个函数支持64位的offset偏移
下面我们来简要介绍一下bionic的主要特性:
Bionic是Android的C/C++ library, libc是GNU/Linux以及其他类Unix系统的基础函数库,
最常用的就是GNU的libc,也叫glibc。Android之所以采用bionic而不是glibc,有几个原因:
1、版权问题,因为glibc是LGPL
2、库的体积和速度,bionic要比glibc小很多。
3、提供了一些Android特定的函数,getprop LOGI等
还有些也常用uclibc,这些库未使用的原因基本相似。
懒的写,从网上搜到的的贴一下bionic主要目录结构及主要功能:
|-- Android.mk
|-- CleanSpec.mk
|-- libc (c 库)
| |-- Android.mk
| |-- arch-arm (arm构架相关的实现,主要是针对arm的优化,以及和处理器相关的调用)
| |-- arch-sh (ST公司的SH4体系实现)
| |-- arch-x86 (x86架构相关的实现)
| |-- arch-mips (mips架构相关的实现)
| |-- bionic
| |-- CAVEATS
| |-- docs
| |-- include
| |-- inet
| |-- Jamfile
| |-- kernel
| |-- MODULE_LICENSE_BSD
| |-- netbsd
| |-- NOTICE
| |-- private
| |-- README
| |-- regex
| |-- stdio
| |-- stdlib
| |-- string
| |-- SYSCALLS.TXT
| |-- tools
| |-- tzcode
| |-- unistd
| |-- wchar
| `-- zoneinfo
|-- libdl (动态链接库访问接口 dlopen dlsym dlerror dlclose dladdr的实现)
| |-- Android.mk
| |-- arch-sh
| |-- dltest.c
| |-- libdl.c
| |-- MODULE_LICENSE_BSD
| `-- NOTICE
|-- libm (C数学函数库, 提供了常见的数序函数和浮点运算)
| |-- alpha
| |-- amd64
| |-- Android.mk
| |-- arm
| |-- bsdsrc
| |-- fpclassify.c
| |-- i386
| |-- i387
| |-- ia64
| |-- include
| |-- isinf.c
| |-- Makefile-orig
| |-- man
| |-- MODULE_LICENSE_BSD_LIKE
| |-- NOTICE
| |-- powerpc
| |-- sh
| |-- sincos.c
| |-- sparc64
| `-- src
|-- libstdc++ (standard c++ lib)
| |-- Android.mk
| |-- include
| |-- MODULE_LICENSE_BSD
| |-- NOTICE
| `-- src
|-- libthread_db (线程调试库,可以利用此库对多线程程序进行调试)
| |-- Android.mk
| |-- include
| |-- libthread_db.c
| |-- MODULE_LICENSE_BSD
| `-- NOTICE
|-- linker (Android dynamic linker)
| |-- Android.mk
| |-- arch
| |-- ba.c
| |-- ba.h
| |-- debugger.c
| |-- dlfcn.c
| |-- linker.c
| |-- linker_debug.h
| |-- linker_format.c
| |-- linker_format.h
| |-- linker.h
| |-- MODULE_LICENSE_APACHE2
| |-- NOTICE
| |-- README.TXT
| `-- rt.c
|-- MAINTAINERS
下面就几个重要的观点说明一下:
Core Philosophy:
The core idea behind Bionic's design is: KEEP IT REALLY SIMPLE.
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.
The name "Bionic" comes from the fact that it is part-BSD and part-Linux:
its source code consists in a mix of BSD C library pieces with custom
Linux-specific bits used to deal with threads, processes, signals and a few
others things.
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.
这些在overview.txt中说明的,不翻译了,英文简洁明了更好
1、系统调用sys_call问题
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.TXT file for input.
基本上的系统调用函数上层进行简单的封装,然后利用汇编代码进行具体实现将利用int 80系统中断调
用到kernel内核中的函数,包含process management,file,signals,sockets,epoll等
举例说明下:
如下面的函数提供给外部使用即lseek64函数,进行简单的封装
loff_t lseek64(int fd, loff_t off, int whence)
{
loff_t result;
if ( __llseek(fd, (unsigned long)(off >> 32),(unsigned long)(off), &result, whence ) < 0 )
return -1;
return result;
}
自动生成的汇编代码,主要调用__NR__xxx函数,进行内核中
/* autogenerated by gensyscalls.py */
#include <sys/linux-syscalls.h>
.text
.type __llseek, #function
.globl __llseek
.align 4
.fnstart
__llseek:
mov ip, sp
.save {r4, r5, r6, r7}
stmfd sp!, {r4, r5, r6, r7}
ldmfd ip, {r4, r5, r6}
ldr r7, =__NR__llseek
swi #0
ldmfd sp!, {r4, r5, r6, r7}
movs r0, r0
bxpl lr
b __set_syscall_errno
.fnend
这些代码都在bionic\libc\arch-$ARCh\syscalls下面
2、线程操作函数问题
Bionic's C library comes with its own pthread implementation bundled in.
This is different from other historical C libraries which:
- place it in an external library (-lpthread)
- play linker tricks with weak symbols at dynamic link time
有如下的几个函数不支持:
pthread_cancel()
pthread_once()
3、linux标准头文件问题
Linux kernel headers:
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:
./kernel/common,
./kernel/arch-$ARCH
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.
4、外部引用bionic头文件
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:
libc/arch-$ARCH/include
libc/include
libc/kernel/common
libc/kernel/arch-$ARCH
to your C include path.
这些就是android系统中使用的标C头文件所在处,请关注之