IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> binder主持与启动 -> 正文阅读

[移动开发]binder主持与启动

binder的jni方法注册

1.zygote启动

1-1.启动zygote进程

zygote是由init进程通过解析 init.zygote.rc 文件而创建的,zygote所对应的可执行程序
app_process,所对应的源文件是 app_main.cpp ,进程名为zygote

// system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --startsystem-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks

1-2.执行app_main.cpp 中的main方法

int main(int argc, char* const argv[])
{
    ...
    if (!className.isEmpty()) {
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();
        //启动
        if (startSystemServer) {
            args.add(String8("start-system-server"));
    }

    ...

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

   ...
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    
}

1-3.AndroidRuntime::start

发现AppRuntime类继承于AndroidRuntime,而AppRuntime类中是没有start()函数的,因此回到上方的main()函数中,实际上当执行AppRuntime#start()时实际上是执行了AndroidRuntime#start()

void AndroidRuntime::start(const char* className, ..., bool zygote)
{
  
    startVm(&mJavaVM, &env, 
 
    /*
     * Register android functions.注册jni
     */
    startReg(env);
 
    /*
     * We want to call main() with a String array with arguments in it.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
 
    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
 
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
        "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
 
    ...
}

根据AndroidRuntime名称和上述代码可以分析得出,该函数启动了 Android 系统运行时库,其中它主要做了三件事:

调用startVmVM()函数启动虚拟机
调用startReg()函数注册 Android 的 Java 方法,其实在这里就是 JNI 方法
反射调用 Java 类com.android.internal.os.ZygoteInit#main()方法,并把 fork zygote进程时的参数传入用来辅助初始化zygote进程

/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ...

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ...

    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
           #ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
            #endif
            return -1;
        }
    }
    return 0;
}

static const RegJNIRec gRegJNI[] = {
    ...
    REG_JNI(register_android_os_Binder),
    ...
};

binder驱动

1.binder_init

kernel/drivers/staging/android/binder.c
//设备驱动入口函数
device_initcall(binder_init);

static int __init binder_init(void)
{
	int ret;
	char *device_name, *device_names;
	struct binder_device *device;
	struct hlist_node *tmp;

    //创建名为binder的单线程的工作队列
	binder_deferred_workqueue = create_singlethread_workqueue("binder");

	while ((device_name = strsep(&device_names, ","))) {
		ret = init_binder_device(device_name);
		if (ret)
			goto err_init_binder_device_failed;
	}
	

	return ret;
}

static int __init init_binder_device(const char *name)
{
	int ret;
	struct binder_device *binder_device;
//为binder设备分配内存
	binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
	if (!binder_device)
		return -ENOMEM;
    //初始化设备
	binder_device->miscdev.fops = &binder_fops;
	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
	binder_device->miscdev.name = name;

	binder_device->context.binder_context_mgr_uid = INVALID_UID;
	binder_device->context.name = name;

	ret = misc_register(&binder_device->miscdev);
	if (ret < 0) {
		kfree(binder_device);
		return ret;
	}

	hlist_add_head(&binder_device->hlist, &binder_devices);

	return ret;
}

2.binder_open

kernel/drivers/staging/android/binder.c

static int binder_open(struct inode *nodp, struct file *filp)
//为binder_proc结构体在kernel分配内存空间
proc = kzalloc(sizeof(*proc), GFP_KERNEL);

INIT_LIST_HEAD(&proc->todo); // 初始化todo列表
init_waitqueue_head(&proc->wait); // 初始化wait队列

3.binder_mmap

1. 通过用户空间的虚拟内存大小 --- 分配一块内核的虚拟内存
2. 分配了一块物理内存  --- 4KB
3. 把这块物理内存分别映射到    用户空间的虚拟内存和内核的虚拟内存
kernel/drivers/staging/android/binder.c

static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
//保证映射内存大小不超过4M
if ((vma->vm_end - vma->vm_start) > SZ_4M)
vma->vm_end = vma->vm_start + SZ_4M;
//同步锁,保证一次只有一个进程分配内存,保证多进程间的并发访问
mutex_lock(&binder_mmap_lock);

// 采用 VM_IOREMAP方式,分配一个连续的内核虚拟内存,与进程虚拟内存大小一致
area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
//将proc中的buffer指针指向这块内核的虚拟内存
proc->buffer = area->addr;
// 计算出用户空间和内核空间的地址偏移量。地址偏移量 = 用户虚拟内存地址 - 内核虚拟内存地址
proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
mutex_unlock(&binder_mmap_lock); // 释放锁
//物理空间映射到虚拟内核空间
ret = map_kernel_range_noflush((unsigned long)page_addr,
PAGE_SIZE, PAGE_KERNEL, page);
//物理空间映射到虚拟进程空间
ret = vm_insert_page(vma, user_page_addr, page[0])

4.binder_ioctl

4-1.binder_ioctl_write_read

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:41:26  更:2021-08-24 15:42:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:36:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码