求助:
应用层的文件浏览器里使用的是java的FILE file; file.listFiles()函数来列出目录下的所有文件,那怎么来看这个函数不断向底层调用的过程呢?
比方说像网上很多牛人分析的发短信的流程一样,一个函数调用一个函数,最后一直到驱动层。
我就想知道这种文件浏览的过程是怎么样的。
这个说起来流程蛮多,反正大概就是:
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
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方法的实现,我这是一头雾水了哈哈。