现在的位置: 首页 > 综合 > 正文

自己实现内核中的current宏

2018年04月16日 ⁄ 综合 ⁄ 共 1895字 ⁄ 字号 评论关闭

说明:

  current宏,是一个全局指针,指向当前进程的struct task_struct结构体,即表示当前进程。

  例如current->pid就能得到当前进程的pid,current-comm就能得到当前进程的名称。

  每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间

  当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;

  当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。

  在陷入内核后,系统调用中也是存在函数调用和自动变量,这些都需要栈支持。、

  当进程因为中断或者系统调用而陷入内核态时,进程所使用的堆栈也要从用户栈转到内核栈。

 

程序一:urrent宏的使用

创建文件夹/nfsroot/kern/2012-04-16/01/。

创建文件/nfsroot/kern/2012-04-16/01/test.c,内容如下:

  说明:要使用current宏,必须声明头文件linux/sched.h。

     上面的test_exit()函数的返回值应改为void。

创建文件/nfsroot/kern/2012-04-16/01/Makefile,内容如下:

在主机端编译模块,过程如下:

在开发板端载入和卸载模块,过程如下:

  说明:

  模块运行的时候,有两种形式:

  第一种,代表其他应用程序在运行,称作进程上下文。主要是通过程序调用模块实现的。

  第二种,代表中断在运行,称作中断上下文。主要是通过(外部)硬件中断调用模块实现的。

  显然,现在此模块是通过程序调用的,属于进程上下文。

  可见current宏的使用效果表面,current就表示当前进程。

  载入模块的时候,代表insmod程序在运行,所以打印出来的程序名为insmod。

  卸载模块的时候,代表rmmod程序在运行,所以打印出来的程序名为rmmod。

 

 

程序二:实现自己的current。

参考文档:http://wenku.baidu.com/view/51337c1ab7360b4c2e3f64ce.html

每个进程运行的时候,都会分配8k的内核栈,此内核栈的分配是按8k对齐的,内核栈顶放置一个struct thread_info thread_info的结构体,而thread_info里面有个struct task_struct *task的指针,指向代表当前进程的task_struct。当进程调用模块的时候,模块声明的所有局部变量就会在此进程的内核栈中有一份,所以即使多个进程调用同一个模块,也不会造成混淆。

如果我们要获得当前进程的current宏,只要随便定义个局部变量,然后把其地址按8k对齐(即把低13bit置0),就能得到thread_info的地址,则其task指针即为current!

分析内核代码如何获取current:

current --> get_current() --> current_thread_info() --> sp & ~(THREAD_SIZE - 1),过程如下:

复制代码
1 static inline struct task_struct *get_current(void)
2 {
3         return current_thread_info()->task;
4 }
5 
6 #define current (get_current())
复制代码
1 static inline struct thread_info *current_thread_info(void)
2 {
3         register unsigned long sp asm ("sp");
4         return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
5 }
1 #define THREAD_SIZE             8192
2 #define THREAD_START_SP         (THREAD_SIZE - 8)

 

自己实现current宏:

修改上面的文件/nfsroot/kern/2012-04-16/01/test.c,内容如下:

在主机端重新编译模块,过程如下:

在开发板端,载入和卸载模块,过程如下:

  说明:可见mycurrent和current的输出完全一致,表示我们实现的自己的current宏了。

 

最后说明:

  current宏定义在<asm/current.h>,但通过<linux/sched.h>就可以使用current宏。

  thread_info结构体和汇编级操作函数定义在<asm/thread_info.h>。

  task_struct结构定义在<linux/sched.h>中。

抱歉!评论已关闭.