android的应用层代码到底层代码的流程

求助:
应用层的文件浏览器里使用的是java的FILE file; file.listFiles()函数来列出目录下的所有文件,那怎么来看这个函数不断向底层调用的过程呢?
比方说像网上很多牛人分析的发短信的流程一样,一个函数调用一个函数,最后一直到驱动层。
我就想知道这种文件浏览的过程是怎么样的。

:wink: 这个说起来流程蛮多,反正大概就是:
1. android的java实现是在libcore/luni中,file.listFiles()在libcore/luni/src/main/java/java/io/File.java中,
public File[] listFiles() {
return filenamesToFiles(list());
}
这里的list()是各个file的信息集合,方法如下:
public String[] list() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (path.isEmpty()) {
return null;
}
return listImpl(absolutePath);
}
这里看到调用到listImpl方法,这是个native方法:private static native String[] listImpl(String path);在libcore/luni/src/main/native/java_io_File.cpp中:

static jobjectArray File_listImpl(JNIEnv* env, jclass, jstring javaPath) {
// Read the directory entries into an intermediate form.
DirEntries files;
if (!readDirectory(env, javaPath, files)) {
return NULL;
}
// Translate the intermediate form into a Java String[].
jobjectArray result = env->NewObjectArray(files.size(), JniConstants::stringClass, NULL);
for (int i = 0; files.size() != 0; files.pop_front(), ++i) {
ScopedLocalRef<jstring> javaFilename(env, env->NewStringUTF(files.front()));
if (env->ExceptionCheck()) {
return NULL;
}
env->SetObjectArrayElement(result, i, javaFilename.get());
if (env->ExceptionCheck()) {
return NULL;
}
}
return result;
}
这里调用到readDirectory方法,实现如下:
static bool readDirectory(JNIEnv* env, jstring javaPath, DirEntries& entries) {
ScopedUtfChars path(env, javaPath);
if (path.c_str() == NULL) {
return false;
}

ScopedReaddir dir(path.c_str());
if (dir.isBad()) {
return false;
}
const char* filename;
while ((filename = dir.next()) != NULL) {
if (strcmp(filename, ".") != 0 && strcmp(filename, "..") != 0) {
if (!entries.push_front(filename)) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return false;
}
}
}
return true;
}

最后可以看到使用ScopedReaddir dir(path.c_str());来读取dir信息.
ScopedReaddir是个class,其构造函数如下:
ScopedReaddir(const char* path) {
mDirStream = opendir(path);
mIsBad = (mDirStream == NULL);
}
可以看到,最后是调用了linux文件操作方法opendir,这个在dirent.h中能找到
实现在libc里面(android的glibc实现是在bionic/libc下)的unistd/opendir.c中找到
DIR* opendir( const char* dirpath )
{
DIR* dir = malloc(sizeof(DIR));

if (!dir)
goto Exit;

dir->_DIR_fd = open(dirpath, O_RDONLY|O_DIRECTORY);
if (dir->_DIR_fd < 0)
{
free(dir);
dir = NULL;
}
else
{
dir->_DIR_avail = 0;
dir->_DIR_next = NULL;
pthread_mutex_init( &dir->_DIR_lock, NULL );
}
Exit:
return dir;
}
这个open最终又会调用到内核的open函数,然后继续调用内核相关方法,找不到了
又找了下:反正要调用到系统调用open,这些显然用汇编写的,比如arch-arm/systcalls/_open.S
.type __open, #function
.globl __open
.align 4
.fnstart

__open:
.save {r4, r7}
stmfd sp!, {r4, r7}
ldr r7, =__NR_open
swi #0
ldmfd sp!, {r4, r7}
movs r0, r0
bxpl lr
b __set_syscall_errno
.fnend

这就是系统调用的open方法的实现,我这是一头雾水了哈哈。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值