移植exFAT到Android4.2.2

最近在Android上测试64GB的TF卡支持情况,发现在Windows平台上默认会把卡格式化为exFAT,而不是以前的FAT32或NTFS,故而引发了我对该文件系统的了解。 

在Linux内核中不支持exFAT文件系统,需要像对ntfs(移植可查阅“参考网址”相关内容)支持一样使用fuse,即用户态文件系统,那什么是exFAT和fuse呢? 

1.exFAT 

exFAT(Extended File Allocation Table),又名FAT64,是一种特别适合于闪存的文件系统,可支持单个文件超过4GB的大小。 

2.fuse 

用户空间文件系统(Filesystem in Userspace,简称FUSE)是操作系统中的概念,指完全在用户态实现的文件系统。目前Linux通过内核模块对此进行支持。 

上面两个名词的详细资料请查阅“参考网址”相关内容。 

了解完了相关内容,那如何移植呢?下面是移植过程: 

1.准备工作 

a.exFAT源码 

使用svn co http://exfat.googlecode.com/svn/trunk/ exfat-read-only命令下载整份exfat源码到当前的exfat-read-only目录中,现在的(2013年07月24日的版本为1.0.0)。 

b.fuse源码 

从https://code.google.com/p/exfat/wiki/HOWTO了解到还需要fuse-devel或libfuse-dev,故而从http://sourceforge.net/projects/fuse/files/fuse-2.X/2.9.3/下载最新的fuse-2.9.3.tar.gz文件。 

2.移植步骤 

a.设置内核的配置:CONFIG_FUSE_FS=y;(会创建/dev/fuse结点) 

b.在Android源码目录下的external目录下创建exfat-fuse目录,交将上面通过svn下载的exFAT代码复制到该目录下,并将fuse-2.9.3.tar.gz文件解压后将其文件也复制到该目录下,进入到exfat-fuse目录,执行./configure命令,会创建include/config.h等文件; 

c.在exfat-fuse目录下创建Android.mk文件,内容如下: 

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 

SRCPATH := lib 

LOCAL_CFLAGS := -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 

LOCAL_MODULE_TAGS := optional 

LOCAL_MODULE    := libfuse_exfat 

LOCAL_SRC_FILES := $(SRCPATH)/buffer.c 

LOCAL_SRC_FILES += $(SRCPATH)/cuse_lowlevel.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_kern_chan.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_loop.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_loop_mt.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_lowlevel.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_mt.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_opt.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_session.c 

LOCAL_SRC_FILES += $(SRCPATH)/fuse_signals.c 

LOCAL_SRC_FILES += $(SRCPATH)/helper.c 

LOCAL_SRC_FILES += $(SRCPATH)/mount.c 

LOCAL_SRC_FILES += $(SRCPATH)/mount_util.c 

LOCAL_SRC_FILES += $(SRCPATH)/ulockmgr.c 

LOCAL_SHARED_LIBRARIES := libdl 

LOCAL_PRELINK_MODULE := false 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include 

include $(BUILD_SHARED_LIBRARY) 

include $(CLEAR_VARS) 

SRCPATH := libexfat 

LOCAL_CFLAGS := -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26  -D__GLIBC__=1 

LOCAL_MODULE_TAGS := optional 

LOCAL_MODULE    := libexfat 

LOCAL_SRC_FILES := $(SRCPATH)/cluster.c 

LOCAL_SRC_FILES += $(SRCPATH)/io.c 

LOCAL_SRC_FILES += $(SRCPATH)/log.c 

LOCAL_SRC_FILES += $(SRCPATH)/lookup.c 

LOCAL_SRC_FILES += $(SRCPATH)/mount.c 

LOCAL_SRC_FILES += $(SRCPATH)/node.c 

LOCAL_SRC_FILES += $(SRCPATH)/time.c 

LOCAL_SRC_FILES += $(SRCPATH)/utf.c 

LOCAL_SRC_FILES += $(SRCPATH)/utils.c 

LOCAL_SHARED_LIBRARIES := libdl libfuse_exfat 

LOCAL_PRELINK_MODULE := false 

include $(BUILD_SHARED_LIBRARY) 

include $(CLEAR_VARS) 

LOCAL_CFLAGS    := -D_FILE_OFFSET_BITS=64 -D__GLIBC__=1 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexfat 

LOCAL_MODULE    := dumpexfat 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := dump/main.c 

LOCAL_SHARED_LIBRARIES := libexfat 

include $(BUILD_EXECUTABLE) 

include $(CLEAR_VARS) 

LOCAL_CFLAGS    := -D_FILE_OFFSET_BITS=64 -D__GLIBC__=1 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexfat 

LOCAL_MODULE    := fsck.exfat 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := fsck/main.c 

LOCAL_SHARED_LIBRARIES := libexfat 

include $(BUILD_EXECUTABLE) 

include $(CLEAR_VARS) 

LOCAL_CFLAGS    := -D_FILE_OFFSET_BITS=64 -D__GLIBC__=1 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexfat 

LOCAL_MODULE    := exfat.label 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := label/main.c 

LOCAL_SHARED_LIBRARIES := libexfat 

include $(BUILD_EXECUTABLE) 

include $(CLEAR_VARS) 

LOCAL_CFLAGS    := -D_FILE_OFFSET_BITS=64 -D__GLIBC__=1 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexfat 

LOCAL_MODULE    := mkfs.exfat 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := mkfs/main.c mkfs/cbm.c mkfs/fat.c mkfs/rootdir.c mkfs/uct.c mkfs/vbr.c mkfs/mkexfat.c mkfs/uctc.c 

LOCAL_SHARED_LIBRARIES := libexfat 

include $(BUILD_EXECUTABLE) 

include $(CLEAR_VARS) 

LOCAL_CFLAGS    := -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -D__GLIBC__=1 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/libexfat 

LOCAL_MODULE    := mount.exfat 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := fuse/main.c 

LOCAL_SHARED_LIBRARIES := libfuse_exfat libexfat 

include $(BUILD_EXECUTABLE) 

d.在相应产品的device.mk文件里添加如下语句: 

PRODUCT_PACKAGES += \ 

fsck.exfat mount.exfat mkfs.exfat 

我们现在只需要上面3个工具即可,而添加的Android.mk里还有其他工具,如果也想编译进来,可直接加到该配置项后面。 

e.跟库相关配置添加好了,接下来就是编译和处理编译异常了,刚开始编译,出现如下错误: 

target thumb C: libfuse_exfat <= external/exfat-fuse/lib/buffer.c 

In file included from external/exfat-fuse/lib/buffer.c:12:0: 

external/exfat-fuse/lib/fuse_i.h:35:2: error: unknown type name 'pthread_mutex_t' 

external/exfat-fuse/lib/fuse_i.h:82:2: error: unknown type name 'pthread_mutex_t' 

external/exfat-fuse/lib/fuse_i.h:84:2: error: unknown type name 'pthread_key_t' 

external/exfat-fuse/lib/fuse_i.h:130:23: error: unknown type name 'pthread_t' 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_write': 

external/exfat-fuse/lib/buffer.c:48:35: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c:51:34: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_read': 

external/exfat-fuse/lib/buffer.c:82:34: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c:85:33: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_fd_to_fd': 

external/exfat-fuse/lib/buffer.c:146:11: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_splice': 

external/exfat-fuse/lib/buffer.c:171:19: error: 'SPLICE_F_MOVE' undeclared (first use in this function) 

external/exfat-fuse/lib/buffer.c:171:19: note: each undeclared identifier is reported only once for each function it appears in 

external/exfat-fuse/lib/buffer.c:173:19: error: 'SPLICE_F_NONBLOCK' undeclared (first use in this function) 

external/exfat-fuse/lib/buffer.c:185:3: warning: implicit declaration of function 'splice' [-Wimplicit-function-declaration] 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_copy_one': 

external/exfat-fuse/lib/buffer.c:232:27: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c:233:27: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c:236:15: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c:236:41: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith] 

external/exfat-fuse/lib/buffer.c: In function 'fuse_buf_copy': 

external/exfat-fuse/lib/buffer.c:313:11: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

看到是跟多线程与splice相关的,从相关资料了解到Android的bionic里面对pthread相关函数支持不佳,故而将相应功能先通过宏屏蔽掉: 

a).将./include/config.h文件的#define HAVE_SPLICE 1注释掉; 

b).修改./lib/fuse_mt.c文件,在fuse_loop_mt_proc函数中,将res = fuse_session_loop_mt(se);一句使用#ifdef __MULTI_THREAD和#endif括起来; 

在同一文件中的fuse_loop_mt函数中,将如下语句也使用上面的宏括起来: 

int res = fuse_start_cleanup_thread(f); 

if (res) 

return -1; 

res = fuse_session_loop_mt(fuse_get_session(f)); 

fuse_stop_cleanup_thread(f); 

并在该函数的第一句前加上int res = -1;一句。 

修改./lib/cuse_lowlevel.c文件,在cuse_lowlevel_main函数中,将如下语句使用上面的宏括起来: 

if (multithreaded) 

res = fuse_session_loop_mt(se); 

else 

修改./lib/fuse.c文件,使用上面的宏将fuse_start_cleanup_thread和fuse_stop_cleanup_thread两函数(包括函数体)括起来; 

修改./lib/fuse_loop_mt.c文件,使用上面的宏将整个文件内容括起来; 

修改./lib/helper.c文件,在fuse_main_common函数中,将如下语句使用上面的宏括起来: 

if (multithreaded) 

res = fuse_loop_mt(fuse); 

else 

c).修改./include/fuse_common.h文件,添加#include 定义。 

此时再次编译,有如下提示: 

external/exfat-fuse/lib/fuse.c: In function 'fuse_fs_read_buf': 

external/exfat-fuse/lib/fuse.c:1804:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

external/exfat-fuse/lib/fuse.c: In function 'mtime_eq': 

external/exfat-fuse/lib/fuse.c:2427:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

external/exfat-fuse/lib/fuse.c:2428:3: error: 'struct stat const' has no member named 'st_mtim' 

external/exfat-fuse/lib/fuse.c: In function 'update_stat': 

external/exfat-fuse/lib/fuse.c:2455:24: error: 'struct stat const' has no member named 'st_mtim' 

external/exfat-fuse/lib/fuse.c: In function 'fuse_lib_setattr': 

external/exfat-fuse/lib/fuse.c:2810:17: error: 'struct stat' has no member named 'st_atim' 

external/exfat-fuse/lib/fuse.c:2815:17: error: 'struct stat' has no member named 'st_mtim' 

external/exfat-fuse/lib/fuse.c:2825:20: error: 'struct stat' has no member named 'st_atim' 

external/exfat-fuse/lib/fuse.c:2827:20: error: 'struct stat' has no member named 'st_mtim' 

没有相应的成员,做如下修改: 

a).修改./include/config.h文件,将#define HAVE_STRUCT_STAT_ST_ATIM 1屏蔽掉; 

b).修改./lib/fuse.c文件,在fuse_lib_setattr函数中的#ifdef HAVE_UTIMENSAT宏判断里做如下修改: 

将tv[0] = attr->st_atim;修改为tv[0].tv_nsec = attr->st_atime; 

将tv[1] = attr->st_mtim;修改为tv[1].tv_nsec = attr->st_mtime; 

再次编译,出现如下错误: 

external/exfat-fuse/lib/mount.c: In function 'exec_fusermount': 

external/exfat-fuse/lib/mount.c:142:8: error: 'FUSERMOUNT_DIR' undeclared (first use in this function) 

external/exfat-fuse/lib/mount.c:142:8: note: each undeclared identifier is reported only once for each function it appears in 

external/exfat-fuse/lib/mount.c:142:23: error: expected ')' before string constant 

external/exfat-fuse/lib/mount.c:142:23: error: too few arguments to function 'execv' 

修改./lib/mount.c文件,在合适的位置添加如下语句: 

#ifndef FUSERMOUNT_DIR 

#define FUSERMOUNT_DIR "/system/bin/bin" 

#endif 

再次编译,出现如下错误: 

external/exfat-fuse/lib/mount_util.c: In function 'mtab_needs_update': 

external/exfat-fuse/lib/mount_util.c:37:19: error: '_PATH_MOUNTED' undeclared (first use in this function) 

external/exfat-fuse/lib/mount_util.c:37:19: note: each undeclared identifier is reported only once for each function it appears in 

修改./lib/mount_util.c文件,在合适的位置添加如下语句: 

#ifndef _PATH_MOUNTED 

#define _PATH_MOUNTED "/etc/mtab" 

#endif 

再次编译,出现如下错误提示: 

/home/guochongxin/rk/3188/new/SDK4.2.2/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: error: symbol __fuse_process_cmd has undefined version 

/home/guochongxin/rk/3188/new/SDK4.2.2/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: error: symbol fuse_lowlevel_new has undefined version FUSE_2.5 

/home/guochongxin/rk/3188/new/SDK4.2.2/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: error: symbol fuse_chan_new has undefined version FUSE_2.4 

/home/guochongxin/rk/3188/new/SDK4.2.2/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: error: symbol fuse_teardown has undefined version FUSE_2.2 

collect2: ld returned 1 exit status 

修改lib/fuse_misc.h文件,将#define FUSE_SYMVER(x) __asm__(x)修改为#define FUSE_SYMVER(x) 

再次编译,出现如下错误: 

In file included from external/exfat-fuse/libexfat/exfat.h:33:0, 

from external/exfat-fuse/libexfat/cluster.c:23: 

external/exfat-fuse/libexfat/compiler.h:28:2: error: #error C99-compliant compiler is required 

修改./libexfat/compiler.h文件,将如下语句屏蔽掉: 

#if __STDC_VERSION__ < 199901L 

#error C99-compliant compiler is required 

#endif 

再次编译,此时编译通过了,那么继续接下来的修改吧。 

f.相应的库和工具编译好了,剩下上层来调用了,修改vold相关文件来实现: 

a).在Android源码的system/vold目录下添加exFat.h和exFat.cpp文件,相应的源码如下: 

exFat.h: 

#ifndef _EXFAT_H 

#define _EXFAT_H 

#include  

class exFat { 

public: 

static int doMount(const char *fsPath, const char *mountPoint, bool ro, int ownerUid); 

static int unMount(const char *mountPoint); 

static int format(const char *fsPath, unsigned int numSectors); 

}; 

#endif 

exFat.cpp: 

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#define LOG_TAG "Vold" 

#include  

#include  

#include "exFat.h" 

static char EXFAT_PATH[] = "/system/bin/mount.exfat"; 

extern "C" int logwrap(int argc, const char **argv, int background); 

extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *); 

int exFat::doMount(const char *fsPath, const char *mountPoint, bool ro, int ownerUid) { 

int rc = 0; 

do { 

if(!ro){ 

const char *args[3]; 

args[0] = EXFAT_PATH; 

args[1] = fsPath; 

args[2] = mountPoint; 

rc = logwrap(3, args, 1); 

SLOGI(" %s %s %s", EXFAT_PATH, fsPath, mountPoint); 

if(!rc){ 

SLOGI("Mount EXFAT device form %s to %s OK",fsPath,mountPoint); 

char *lost_path; 

asprintf(&lost_path, "%s/LOST.DIR", mountPoint); 

if (access(lost_path, F_OK)) { 

/* 

* Create a LOST.DIR in the root so we have somewhere to put 

* lost cluster chains (fsck_msdos doesn't currently do this) 

*/ 

if (mkdir(lost_path, 0755)) { 

SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); 

free(lost_path); 

return 0; 

}else{ 

SLOGE("Mount EXFAT device form %s to %s failed",fsPath,mountPoint); 

return -1; 

}else{ 

const char *args[5]; 

args[0] = EXFAT_PATH; 

args[1] = fsPath; 

args[2] = mountPoint; 

args[3] = "-o"; 

args[4] = "ro,uid=1000"; 

rc = logwrap(5, args, 1); 

if(!rc){ 

SLOGI("Mount EXFAT device form %s to %s OK.(Read-only)",fsPath,mountPoint); 

return 0; 

}else{ 

SLOGE("Mount EXFAT device form %s to %s failed.(Read-only)",fsPath,mountPoint); 

return -1; 

} while (0); 

return rc; 

int exFat::unMount(const char *mountPoint) { 

int rc = 0; 

do { 

const char *args[3]; 

args[0] = "umount"; 

args[1] = mountPoint; 

args[2] = NULL; 

rc = logwrap(2, args, 1); 

if(!rc){ 

SLOGI("unMount EXFAT device %s OK",mountPoint); 

return 0; 

}else{ 

SLOGE("unMount EXFAT device %s failed",mountPoint); 

return -1; 

} while (0); 

return rc; 

int exFat::format(const char *fsPath, unsigned int numSectors) { 

return 0; 

b).修改system/vold/Android.mk文件,在common_src_files量中将exFat.cpp添加进去; 

c).修改system/vold/Volume.cpp文件,进行如下修改: 

添加#include "exFat.h"一句; 

修改int Volume::mountVol()函数中的如下语句: 

if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false, 

AID_SYSTEM, gid, 0702, true)) { 

SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); 

continue; 

为 

if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false, 

AID_SYSTEM, gid, 0702, true)) { 

SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); 

if(exFat::doMount(devicePath, "/mnt/secure/staging", false, 1000)){ 

SLOGE("%s failed to mount via EXFAT (%s)\n", devicePath, strerror(errno)); 

continue; 

至此,上层也修改好了,继续编译。 

g.编译好后烧录运行,Android跑起来后,插入64GB的exFAT文件系统的TF卡,其中logcat信息中有如下错误提示: 

I//system/bin/mount.exfat(  118): FUSE exfat 1.0.0 

I//system/bin/mount.exfat(  118): ERROR: failed to get size of `/dev/block/vold/179:1'. 

该问题从https://groups.google.com/forum/#!msg/exfat/Iei35MqkRGk/UeGSjnbzgQsJ可得知是一个已知问题,主要是fuse-exfat使用的LFS在Android native中没有提供相应的API函数,根据上面的提示,查找到该提示是在exfat-fuse目录中的./libexfat/io.c文件中的exfat_open处理,该函数会调用到exfat_seek,通过其来获得整个文件的大小,但该函数返回小于0的值,继续跟踪,该函数会调用到lseek函数,从http://fred-zone.blogspot.com/2011/02/io-offset.html了解到可通过两种方法处理,我们Android.mk里面包含了第一种方法,但无法处理,现在直接使用第二种方法来处理: 

修改exfat-fuse目录里的./libexfat/io.c文件,添加如下内容: 

#define  lseek   lseek64 

#define  pread  pread64 

#define  pwrite pwrite64 

#define  fcntl  __fcntl64 

并将exfat-fuse目录里的所有.c和.h文件中的off_t替换为off64_t,重新编译烧录后,插上64GB的T卡后,有如下提示: 

I//system/bin/mount.exfat(  116): FUSE exfat 1.0.0 

I//system/bin/mount.exfat(  116): WARN: volume was not unmounted cleanly. 

I/Vold    (  116):  /system/bin/mount.exfat /dev/block/vold/179:1 /mnt/external_sd 

I/Vold    (  116): Mount EXFAT device form /dev/block/vold/179:1 to /mnt/external_sd OK 

挂载成功了,测试可以读写卡,但拔掉卡后有如下提示: 

I/DEBUG   (  119):          becae628  408f0940  [heap] 

I/DEBUG   (  119):          becae62c  401b81b4  /system/lib/libc.so 

I/DEBUG   (  119):          becae630  400e3602  /system/lib/libexfat.so 

I/DEBUG   (  119):          becae634  0001c000 

I/DEBUG   (  119):          becae638  00000252 

I/DEBUG   (  119):          becae63c  401b81b4  /system/lib/libc.so 

I/DEBUG   (  119):          becae640  400e3602  /system/lib/libexfat.so 

I/DEBUG   (  119):          becae644  4018879c  /system/lib/libc.so (__pthread_clone) 

I/DEBUG   (  119):     #01  becae648  883d068a 

I/DEBUG   (  119):          becae64c  400e0457  /system/lib/libexfat.so (exfat_bug+82) 

I/DEBUG   (  119):     #02  becae650  becae66c  [stack] 

I/DEBUG   (  119):          becae654  becae66c  [stack] 

I/DEBUG   (  119):          becae658  04d00000 

I/DEBUG   (  119):          becae65c  04d00000 

I/DEBUG   (  119):          becae660  00000000 

I/DEBUG   (  119):          becae664  400e0095  /system/lib/libexfat.so (exfat_pread+36) 

I/DEBUG   (  119):          becae668  400e3602  /system/lib/libexfat.so 

由此可以看到是libexfat的问题,从打印出来的栈信息,初步判断是exfat_bug涉及到影响,修改./libexfat/exfat.h文件,将如下语句: 

void exfat_bug(const char* format, ...) PRINTF NORETURN; 

void exfat_error(const char* format, ...) PRINTF; 

void exfat_warn(const char* format, ...) PRINTF; 

void exfat_debug(const char* format, ...) PRINTF; 

替换为 

#define exfat_debug(x...) 

#define exfat_bug(x...) 

#define exfat_warn(x...) 

#define exfat_error(x...)    exfat_errors++ 

再次编译,有如下错误提示: 

target thumb C: libexfat <= external/exfat-fuse/libexfat/log.c 

external/exfat-fuse/libexfat/log.c:34:1: error: expected identifier or '(' before '{' token 

external/exfat-fuse/libexfat/log.c:56:6: error: expected '=', ',', ';', 'asm' or '__attribute__' before '++' token 

external/exfat-fuse/libexfat/log.c:80:1: error: expected identifier or '(' before '{' token 

external/exfat-fuse/libexfat/log.c:101:1: error: expected identifier or '(' before '{' token 

修改./libexfat/log.c文件,将#include "exfat.h"屏蔽掉,再次编译,有如下错误提示: 

external/exfat-fuse/libexfat/lookup.c: In function 'exfat_split': 

external/exfat-fuse/libexfat/lookup.c:225:1: error: control reaches end of non-void function [-Werror=return-type] 

cc1: some warnings being treated as errors 

修改./libexfat/lookup.c文件,在exfat_split函数最后加上return 0;语句,再次编译,有如下错误提示: 

external/exfat-fuse/mkfs/mkexfat.c: In function 'get_position': 

external/exfat-fuse/mkfs/mkexfat.c:162:1: error: control reaches end of non-void function [-Werror=return-type] 

cc1: some warnings being treated as errors 

修改./mkfs/mkexfat.c文件,在get_position函数中最后加上return 0;语句,再次编译,未发现错误,烧录后,插拔TF卡未见明显异常信息。至此,移植告一段落了,待后期使用测试了。 

参考网址: 

http://zh.wikipedia.org/wiki/ExFAT 

http://zh.wikipedia.org/wiki/FUSE 

http://fuse.sourceforge.net/ 

http://ask.zol.com.cn/q/26385.html 

http://www.baike.com/wiki/exFAT 

http://linuxtoy.org/archives/fuse-exfat-1-0.html 

http://blog.csdn.net/xiaoqinpeng/article/details/7050182 

http://blog.csdn.net/darkengine/article/details/7106207 

http://www.cnblogs.com/lihaibo19891007/p/3144228.html 

http://src.chromium.org/svn/trunk/src/net/base/file_stream_context_posix.cc 

https://android.googlesource.com/platform/frameworks/base/+/1542af35976ce121b8a69812ab8dec7b71a0b283%5E1..1542af35976ce121b8a69812ab8dec7b71a0b283/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容