热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux进程current,Linux——不同体系结构下获取current

current的含义:内核代码可以引用当前进程,通过存取全局项current,它在中定义,它产生一个指针指向结构task_struct,在定义.current指针指向

current的含义:

内核代码可以引用当前进程, 通过存取全局项 current, 它在 中定义, 它产生一个指针指向结构 task_struct, 在 定义. current 指针指向当前在运行的进程. 在一个系统调用执行期间, 例如 open 或者 read, 当前进程是发出调用的进程. 内核代码可以通过使用 current 来使用进程特定的信息, 如果它需要这样. 实际上, current 不真正地是一个全局变量. 支持 SMP 系统的需要强迫内核开发者去开发一种机制,

在相关的 CPU 上来找到当前进程. 这种机制也必须快速, 因为对 current 的引用非常频繁地发生. 结果就是一个依赖体系的机制, 常常, 隐藏了一个指向 task_struct 的指针在内核堆栈内. 实现的细节对别的内核子系统保持隐藏, 一个设备驱动可以只包含 并且引用当前进程.

在X86体系中如何获取current的:

在asm/current.h中我们看到代码如下方式实现:

10 DECLARE_PER_CPU(struct task_struct *, current_task);

11

12 static __always_inline struct task_struct *get_current(void)

13 {

14     return percpu_read_stable(current_task);

15 }

16

17 #define current get_current()        在上述代码中我们能过看到其实current其实是一个宏,真实的调用为get_current(),而在get_current()中又调用percpu_read_stable(current_task),下面看一下percpu_read_stable(current_task)的实现:(注:在上述代码中第10行的DECLARE_PER_CPU宏用于在编译时候声明一个perCPU变量该变量被放在一个特殊的段中,原型为DECLARE_PER_CPU(type,name),主要作用是为处理器创建一个type类型,名为name的变量)

在asm/percpu.h中我们找到了percpu_read_stable(current_task)的实现:

361 #define percpu_read_stable(var)     percpu_from_op("mov", var, "p" (&(var)))

在这里很清晰,我们继续跟中percpu_from_op("mov", var, "p" (&(var)))

在asm/percpu.h中我们找了percpu_from_op("mov", var, "p" (&(var)))的实现如下:

180 #define percpu_from_op(op, var, constraint)     \

181 ({                          \

182     typeof(var) pfo_ret__;              \

183     switch (sizeof(var)) {              \

184     case 1:                     \

185         asm(op "b "__percpu_arg(1)",%0"     \

186             : "=q" (pfo_ret__)          \

187             : constraint);          \

188         break;                  \

189     case 2:                     \

190         asm(op "w "__percpu_arg(1)",%0"     \

191             : "=r" (pfo_ret__)          \

192             : constraint);          \

193         break;                  \

194     case 4:                     \

195         asm(op "l "__percpu_arg(1)",%0"     \

196             : "=r" (pfo_ret__)          \

197             : constraint);          \

198         break;                  \

199     case 8:                     \

200         asm(op "q "__percpu_arg(1)",%0"     \

201             : "=r" (pfo_ret__)          \

202             : constraint);          \

203         break;                  \

204     default: __bad_percpu_size();           \

205     }                       \

206     pfo_ret__;                  \

207 })        percpu_from_op宏中根据不同的sizeof(var)选择不同的分支,执行不同的流程,因为这里是x86体系,所以sizeof(current_task)的值为4,在每个分支中使用了一条的內联汇编代码,其中__percpu_arg(1)为%%fs:%P1(X86)或者%%gs:%P1(X86_64),将上述代码整理后current获取代码如下:

asm(movl "%%fs:%P1","%0" : "=r" (pfo_ret__) :"p" (&(var))

即:将fs段中P1偏移处的值传送给pfo_ret__变量,那么fs段中P1偏移处存放的是什么呢?

注:本文没有写完,前面这块写了好多天了,接下来的内容还没有分析,求简单的指导:在我的记忆中应该是内核栈的分配的问题,以及thread_info在内核栈中的位置的问题,然后就能够找到task_struct了,求指导相关模块的内核源码位置

总结:

以前是通过如下汇编指令实现的:movl $-8192,%eax; andl %esp, %eax来实现的,执行完这两条指令后,eax中存放的就是thread_info的地址。而现在的代码中再也找不到这样的指令了,以前SMP共享数据很多依靠自旋锁来达到目的,自旋锁是一种忙等锁,在一定程度上造成了进行自旋的CPU上CPU利用率的下降,随着内核的不断发展,更多的使用每个CPU数据(per_cpu_data)的概念,在每一个处理器中各自维护一个以前在多个CPU之间进行共享的数据,如当前运行的任务结构体,以前就是在多个CPU之间共享的。



推荐阅读
author-avatar
_MIN_Y
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有