linux内核 sp什么意思,浅析基于ARM的Linux下的系统调用的实现
12: tbl .req r8 @ syscall table pointer
13: why .req r8 @ Linux syscall (!= 0)
14: tsk .req r9 @ current thread_info
.req 是伪汇编,以 scno .req r7 为例,表示scno是寄存器r7的别名。
get_thread_info tsk
其中,tsk是寄存器r9的别名,get_thread_info是一个宏定义,如下:
1: .macro get_thread_info, rd
2: mov rd, sp, lsr #13
3: mov rd, rd, lsl #13
4: .endm
即:将sp进行8KB对齐后的值赋给寄存器r9,什么意思?
这个就涉及到Linux的内核栈了。Linux为每个进程都分配了一个8KB的内核栈,在内核栈的尾端存放有关于这个进程的struct therad_info结构:
1: struct thread_info {
2: unsigned long flags; /* low level flags */
3: int preempt_count; /* 0 => preemptable, <0 => bug */
4: mm_segment_t addr_limit; /* address limit */
5: struct task_struct *task; /* main task structure */
6: struct exec_domain *exec_domain; /* execution domain */
7: __u32 cpu; /* cpu */
8: __u32 cpu_domain; /* cpu domain */
9: struct cpu_context_save cpu_context; /* cpu context */
10: __u32 syscall; /* syscall number */
11: __u8 used_cp[16]; /* thread used copro */
12: unsigned long tp_value;
13: struct crunch_state crunchstate;
14: union fp_state fpstate __attribute__((aligned(8)));
15: union vfp_state vfpstate;
16: #ifdef CONFIG_ARM_THUMBEE
17: unsigned long thumbee_state; /* ThumbEE Handler Base register */
18: #endif
19: struct restart_block restart_block;
20: };
通过上面的操作,寄存器r9中就是这个进程的thread_info结构的起始地址。
sys_call_table
entry-common.S (archarmkernel)
1: .type sys_call_table, #object
2: ENTRY(sys_call_table)
3: #include "calls.S"
4: #undef ABI
5: #undef OBSOLETE
其中,calls.S的内容如下:
1: /*
2: * linux/arch/arm/kernel/calls.S
3: *
4: * Copyright (C) 1995-2005 Russell King
5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License version 2 as
8: * published by the Free Software Foundation.
9: *
10: * This file is included thrice in entry-common.S
11: */
12: /* 0 */ CALL(sys_restart_syscall)
13: CALL(sys_exit)
14: CALL(sys_fork_wrapper)
15: CALL(sys_read)
16: CALL(sys_write)
17: /* 5 */ CALL(sys_open)
18: CALL(sys_close)
19: CALL(sys_ni_syscall) /* was sys_waitpid */
20: CALL(sys_creat)
21: CALL(sys_link)
22: /* 10 */ CALL(sys_unlink)
23: CALL(sys_execve_wrapper)
24: CALL(sys_chdir)
25: CALL(OBSOLETE(sys_time)) /* used by libc4 */
26: CALL(sys_mknod)
27: ......
28: /* 355 */ CALL(sys_signalfd4)
29: CALL(sys_eventfd2)
30: CALL(sys_epoll_create1)
31: CALL(sys_dup3)
32: CALL(sys_pipe2)
33: /* 360 */ CALL(sys_inotify_init1)
34: CALL(sys_preadv)
35: CALL(sys_pwritev)
36: #ifndef syscalls_counted
37: .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
38: #define syscalls_counted
39: #endif
40: .rept syscalls_padding
41: CALL(sys_ni_syscall)
42: .endr
关于这个部分的更多介绍参见:
http://www.cnblogs.com/pengdonglin137/p/3714981.html
bics r10, r10, #0xff000000
执行这个操作的时候,r10中存放的是SWI instruction,在我们的例子中就是(a.dis):
即:r10 为 0xEF000000
显然,bics这条指令下面的两个语句由于条件不成立,无法获得执行。这条指令的作用是获得系统调用号
可以参考这个手册,看一下svc执行的格式:
http://files.cnblogs.com/pengdonglin137/DUI0203IC_rvct_developer_guide.pdf
可以看到,[23:0]存放的就是svc指令后面的那个立即数,也即系统调用号。
不过需要注意的是:我们这里并没有这样做,我们的做法是(a.dis中可以看到):
使用的是svc 0,后面跟的并不是系统调用号,而是0,这里把系统调用号存放在了寄存器r7中(a.dis中):
可以看到,由于使用的sys_open系统调用,所以把它的系统调用号5存放到了寄存器r7当中
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
这里的scno是就是寄存器r7的别名,它的值是sys_open的系统调用号5,由于在calls.S中每个系统调用标号占用4个字节,所以这个将scno的值乘以4然后再加上tbl,tbl是系统调用表sys_call_table的基地址。然后就跳入开始执行sys_open了。
asmlinkage long sys_open(const char __user *filename,
int flags, int mode);
那么sys_open在哪呢?在内核源码中直接搜索sys_open,无法搜到它的实现代码,实际上它是在fs/open.c中实现的:
1: SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
2: {
3: long ret;
4:
5: if (force_o_largefile())
6: flags |= O_LARGEFILE;
7:
8: ret = do_sys_open(AT_FDCWD, filename, flags, mode);
9: /* avoid REGPARM breakage on x86: */
10: asmlinkage_protect(3, ret, filename, flags, mode);
11: return ret;
12: }
其中SYSCALL_DEFINE3是一个宏:
syscalls.h (includelinux)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
SYSCALL_DEFINEx也是一个宏:
syscalls.h (includelinux)
#define SYSCALL_DEFINEx(x, sname, ...)
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
__SYSCALL_DEFINEx仍然是个宏:
syscalls.h (includelinux)
#define __SYSCALL_DEFINEx(x, name, ...)
asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
所以展开后的结果就是:
asmlinkage long sys_open(__SC_DECL3(__VA_ARGS__))
其中,__SC_DECL3定义如下:
syscalls.h (includelinux)
1: #define __SC_DECL1(t1, a1) t1 a1
2: #define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
3: #define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
所以最终的结果如下:
1: asmlinkage long sys_open(const char __user *filename, int flags, int mode)
2: {
3: long ret;
4:
5: if (force_o_largefile())
6: flags |= O_LARGEFILE;
7:
8: ret = do_sys_open(AT_FDCWD, filename, flags, mode);
9: /* avoid REGPARM breakage on x86: */
10: asmlinkage_protect(3, ret, filename, flags, mode);
11: return ret;
12:
13: }
关于sys_open本身的实现这里就不深入分析了。
接下来看一下返回。
adr lr, ret_fast_syscall @ return address
当sys_open中return后,便跳入ret_fast_syscall处开始执行:
1: /*
2: * This is the fast syscall return path. We do as little as
3: * possible here, and this includes saving r0 back into the SVC
4: * stack.
5: */
6: ret_fast_syscall:
7: UNWIND(.fnstart )
8: UNWIND(.cantunwind )
9: disable_irq @ disable interrupts
10:
ldr r1, [tsk, #TI_FLAGS] @将thread_info中的flags成员存放到r1中
11: tst r1, #_TIF_WORK_MASK
12: bne fast_work_pending
13:
14: /* perform architecture specific actions before user return */
15: arch_ret_to_user r1, lr
16:
17: @ fast_restore_user_regs
18: ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
19: ldr lr, [sp, #S_OFF + S_PC]! @ get pc
[1] [2] [3] [4]
linux内核 sp什么意思,浅析基于ARM的Linux下的系统调用的实现相关推荐
- u-boot的linux内核映像加载,基于U_Boot的Linux内核映像加载与引导功能实现.pdf
基于U_Boot的Linux内核映像加载与引导功能实现 20 10 8 ( ) Aug . 2010 10 4 Journal of Langfang T eachers College( N atu ...
- Linux内核源码分析:基于最新的Linux 4.0内核(学习路线总结)
今天给大家分享的是基于最新的Linux 4.0内核学习路线总结,本文由8个专题组成,文末附上学习路线思维导图. 一.进程管理专题 1.进程原理 1.1 进程生命周期 1.2 task_struct结构 ...
- [转载]基于ARM的linux内核裁剪与移植
基于ARM的linux内核裁剪与移植 http://bbs.elecfans.com/forum.php?mod=viewthread&tid=185020 wutaimin( 楼主 ) 2 ...
- Linux内核3.0移植并基于Initramfs根文件系统启动
Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先, ...
- arm linux 工控,基于ARM和Linux通用工控平台设计 - ARM - 电子发烧友网
交叉编译 交叉编译就是在一个平台上生成另一个平台上的可执行代码.所谓平台,实际上包含两个概念:体系结构及操作系统.根据上述建立的开发环境,目标平台是基于ARM体系结构的运行嵌入式Linux操作系统,而 ...
- arm linux考勤,定稿毕业论文_基于ARM与Linux的员工刷卡考勤系统喜欢就下吧(范文1)...
<毕业论文_基于ARM与Linux的员工刷卡考勤系统.doc>由会员分享,可免费在线阅读全文,更多与<(定稿)毕业论文_基于ARM与Linux的员工刷卡考勤系统(喜欢就下吧)> ...
- OpenCV基于ARM的Linux系统的交叉编译
OpenCV基于ARM的Linux系统的交叉编译 基于ARM的Linux系统的交叉编译 先决条件 获取OpenCV源代码 获取最新的稳定OpenCV版本 从Git存储库中获取最新的OpenCV 构建O ...
- arm Linux 低成本方案,参赛作品《低成本基于ARM+Linux平台搭建web服务器的物联网学习板》...
[报名阶段需要填写的内容] 1. 参赛者姓名(必填项): 王徕泽 2. 单位或学校名称(选填项): 徕泽电子工作室 3. 当前职务或职称(选填项): 室长 4. 参赛作品的名字(必填项): 低成本基于 ...
- linux 网络对讲,基于ARM与Linux的全数字化可视对讲系统的设计与实现
摘要: 在信息化飞速发展的今天智能家居系统已越来越多的被人们所接受,从楼宇可视对讲到紧急情况报警,再到远程家电控制,智能家居系统在人们的日常生活中扮演着重要的角色.传统的可视对讲系统都是基于模拟音视频 ...
最新文章
- 使用WebDriver + Java + Junit做自动化测试教程
- Android setTag()/getTag()
- TCP/IP网络协议的通俗理解,socket,http,soap。
- phpstorm运行java项目_phpstorm的提速设置
- 解决 SSH 不能输入中文的问题
- Javascript 常见使用误区
- sliverlight3 学习 2, 布局
- 和平精英现在服务器暂时未开放,和平精英为什么登陆不进去 和平精英服务器分批登陆是什么意思...
- 怎么把文件导入云服务器,怎么把文件放到云服务器里
- Spring Boot + Prometheus + Grafana 打造可视化监控,一目了然!
- 网站刷关键词_B2B关键词调研:如何精准地定位B端客户?(下)
- Chaotica for Mac(分形艺术图形设计工具)
- win10 安装mysql 卡死_win10安装Mysql5.5卡住假死
- MUI调用照片以及裁剪和图库照片上传到服务器【后端部分Flask+MUI】
- 福岛邦彦在多少年创立了卷积神经网络
- 查看ASA日志服务器信息,Cisco ASA防火墙的日志管理
- ESP32-C3 SPI salve示例错误
- 降低电源纹波噪声的方法
- 捣鼓车间 | 学生获奖作品:戒烟帽
- 程序员软技能:职场、学习、生活,代码之外生存之南
热门文章
- 2021-09-18P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布P2058 [NOIP2016 普及组] 海港
- cesium加载geoJson格式的图斑方法
- Carsim安装失败,干啥都没用,改了许可证,加了BIA,解决见下图
- ae怎样设置gpu渲染
- matlab求解二维矩阵并画图,Matlab教程2_ 绘图 _ 二维(2)
- <if test=“state!=null and state==‘0‘ “> mybatis中使用if test判断参数值得问题
- 青蛙与蚊子(C++结构体练习题)
- 基于单片机(STC89C52)的数字频率计
- 一个测试人员的工作该怎么开展
- 使用主密钥和钱包方法加密数据