Arm64架构-1-上下文切换-2-相关实验
一、内核线程变用户进程
基于msm-5.4
1. 简介
本实验想参考内核init线程变成用户init进程的做法,实现驱动中创建一个内核线程,然后其装载用户程序变成用户进程。
//创建init内核线程: rest_init //init/main.c kernel_thread(kernel_init, NULL, CLONE_FS); //内核线程变用户进程 kernel_init //init/main.c ret = run_init_process("/bin"); if (!ret) return 0; //返回用户空间,成为init用户空间进程
load_elf_binary() 中会对硬件做一些初始化,比如设置 pt_regs 等,执行路径如下:
run_init_process //init/main.c do_execveat do_execveat_common //fs/exec.c __do_execve_file //fs/exec.c exec_binprm //fs/exec.c search_binary_handler //fs/exec.c fmt->load_binary(bprm); load_elf_binary
2. 实验代码
(1) 内核代码
#define pr_fmt(fmt) "KTU_K: " fmt #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/delay.h> #include <linux/sched/signal.h> #include <linux/sched/task.h> int g_val; #define MAX_USER_ARGS CONFIG_INIT_ENV_ARG_LIMIT #define MAX_USER_ENVS CONFIG_INIT_ENV_ARG_LIMIT static const char *argv_user[MAX_USER_ARGS+2] = { "user", NULL, }; const char *envp_user[MAX_USER_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; /* 参考 run_init_process */ static int run_user_process(const char *user_filename) { argv_user[0] = user_filename; pr_info("Run %s as user process\n", user_filename); return do_execve(getname_kernel(user_filename), (const char __user *const __user *)argv_user, (const char __user *const __user *)envp_user); } int ktu_test_kernel_thread(void *arg) { int ret; int val = (int)arg; ret = run_user_process("/data/local/tmp/ktu_user"); if (ret < 0) { pr_info("run ktu_user fald"); } if (val == 1) { pr_info("pid=%d enter msleep loop\n", current->pid); while(1) msleep(10); } else { pr_info("pid=%d returned\n", current->pid); return 0; //return user space } } static ssize_t ktu_test_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char buffer[64] = {0}; int ret, type, val; if (count > sizeof(buffer) - 1) count = sizeof(buffer) - 1; if (copy_from_user(buffer, buf, count)) return -EFAULT; ret = sscanf(buffer, "%d %d", &type, &val); if (ret <= 0) { pr_err("sscanf failed\n"); return -EINVAL;; } pr_info("set param: type=%d, val=%d\n", type, val); if (type == 1) { int pid = kernel_thread(ktu_test_kernel_thread, (void *)val, CLONE_FS); pr_info("cur pid=%d, kernel thread pid=%d\n", current->pid, pid); } for (;;) { if (signal_pending(current)) { pr_info("pid=%d interrupted by signal\n", current->pid); return -EINTR; } schedule_timeout_interruptible(25); } g_val = val; pr_info("pid=%d returned\n", current->pid); return count; } static ssize_t ktu_test_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { char buffer[256]; size_t len; len = snprintf(buffer, sizeof(buffer), "test pid=%d\n", g_val); return simple_read_from_buffer(buf, count, ppos, buffer, strlen(buffer)); } static const struct file_operations proc_ktu_test_fops = { .write = ktu_test_write, .read = ktu_test_read, }; static int __init ktu_test_init(void) { pr_info("init.\n"); proc_create("ktu_test", 0666, NULL, &proc_ktu_test_fops); return 0; } module_init(ktu_test_init);
(2) 用户代码
#define LOG_TAG "KTU_U" #include <errno.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <unistd.h> #include <sys/syscall.h> #include <log/log.h> int main(int argc, char *argv[]) { int i, cnt = 0; for (i = 0; i < argc; i++) { ALOGI("argv[%d]=%s", i, argv[i]); } while(1) { ALOGI("user cnt=%d", cnt++); usleep(200 * 1000); } return 0; }
Android.bp:
cc_binary { name: "ktu_user", srcs: [ "ktu_user.cpp", ], defaults: ["ktu_user_defaults"], } cc_defaults { name: "ktu_user_defaults", cflags: [ "-Wall", "-Werror", "-Wno-unused-function", "-Wno-unused-parameter", "-Wno-unused-variable", ], static_libs: [ "libc", "libcutils", "liblog", ], static_executable: true, }
3. 实验数据
实验失败,执行报错如下:
# echo 1 0 > /proc/ktu_test [363.576714] (1)[4595:sh]KTU_K: set param: type=1, val=0 [363.577035] (1)[4595:sh]KTU_K: cur pid=4595, kernel thread pid=4722 [363.577313] (0)[4722:sh]potentially unexpected fatal signal 11. [363.577494] (0)[4722:sh]CPU: 0 PID: 4722 Comm: sh Tainted: G W O 5.4.219--dirty #32 [363.577737] (0)[4722:sh]Hardware name: Qualcomm Technologies, Inc. Direwolf Single LA Virtual Machine [363.577952] (0)[4722:sh]pstate: 00001000 (nzcv daif -PAN -UAO) [363.578091] (0)[4722:sh]pc : 0000005acb162970 [363.578200] (0)[4722:sh]lr : 0000005acb162984 [363.578359] (0)[4722:sh]sp : ffffffc0100a1430 [363.578490] (0)[4722:sh]x29: 0000007fcef1b1c0 x28: 0000007fcef1b180 [363.578637] (0)[4722:sh]x27: 0000005acb188310 x26: 00000078c8ca6000 [363.578797] (0)[4722:sh]x25: b40000773491d069 x24: 0000007fcef1b1a0 [363.578938] (0)[4722:sh]x23: 0000007fcef1b198 x22: 0000005acb165bf0 [363.579081] (0)[4722:sh]x21: 0000005acb187648 x20: b40000773491ce58 [363.579236] (0)[4722:sh]x19: 0000000000000004 x18: 00000078c9cea000 [363.579415] (0)[4722:sh]x17: 00000078c49af250 x16: 00000078c49d21c8 [363.579559] (0)[4722:sh]x15: 0000005acb187f00 x14: 0000000000000000 [363.579685] (0)[4722:sh]x13: 00000000108f6ff7 x12: 0000ffff00000eff [363.579888] (0)[4722:sh]x11: 000000003491ceec x10: 000000003c2cd166 [363.580130] (0)[4722:sh]x9 : b40000773491ce58 x8 : 0000000000000040 [363.580312] (0)[4722:sh]x7 : 0000000000000000 x6 : 0000000000000030 [363.580511] (0)[4722:sh]x5 : b4000076d491822a x4 : ffffffffffffffff [363.580644] (0)[4722:sh]x3 : ffffffffffffffff x2 : 0000000000000004 [363.580783] (0)[4722:sh]x1 : b40000773491ce58 x0 : 0000000000000000 [363.581061] (1)[4595:sh]KTU_K: pid=4595 interrupted by signal [363.582931] (2)[1:init]init: Untracked pid 4722 received signal 11
用户空间一个打印也没有,根本没有得到执行。
注: init进程有 init_mm, init_task 全局变量结构, 需要进一步研究。
posted on 2026-01-20 16:45 Hello-World3 阅读(1) 评论(0) 收藏 举报
浙公网安备 33010602011771号