前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内核开发知识第二讲,编写Kerner 程序中注意的问题.

内核开发知识第二讲,编写Kerner 程序中注意的问题.

作者头像
IBinary
发布2018-08-30 17:13:54
4190
发布2018-08-30 17:13:54
举报
文章被收录于专栏:逆向技术逆向技术

一丶函数多线程的安全问题

什么是函数多线程安全. 简单来说就是 ,一个函数在调用过程中.还没有返回的时候.再次被其他线程调用了.但是函数执行的结果是可靠的.就可以了说这个函数是安全的.

比如我们在用户层编写程序.用到多线程的时候.都会注意同步问题. 因为这样我们的线程才是安全的.

在内核中其实是一样的.但是我们要注意.

1.可能运行在多线程中的函数.必须保证线程安全. 而如果运行在单线程中.那么不需要线程安全性.因为没有操作线程.

2.如果 A 调用B B 调用C. 而C的所有调用者(A B)都运行在同一单线程中. 那么C也要保证运行在单线程中.

3.如果 A -> B -> C 而 BC可能在多线程环境中. 那么函数A也可能运行在多线程环境中. 意思就是说 有可能多线程调用A了.但是A会调用BC.所以BC在多线程环境中.

4.A - > B -> C 如果B运行在多线程环境中.那么都有多线程序列化诚单线程的强制措施.在函数B是运行在单线程中.

上面所说,就是内核程序中的"多线程序列化诚单线程的强制措施" 互斥体.自旋锁.

5.只是用函数内部资源.不使用全局变量.静态变量.或者其他全局性资源的函数.是多线程安全的.

6.如果使用全局,静态.等变量.那么我们需要使用同步函数来进行同步.

 二丶中断级别.

总的来说这篇博客讲的理论偏多.都是注意的问题.在内核中. Kerner API 都有中断级别一说.

在用户层,代码都是同级别运行.所以不需要关心.但是在Kerner内核中.就需要关心一下.否则可能一个问题.导致一直出问题.

现在中断级别有两个级别

1.Passive 级别.

2.Dispatch级别.

关于两种级别.在内核博客中的刚开始两课有简单的说过本质.其实我们只需要知道两种界别注意一下就行.

简单的函数运行在Dispatch级别中. 所以我们在调用任何一个kernerAPI之前,都要查询一下中断级别.

Dispatch级别比 Passive级别高.

怎么判断?

调用路径: A - B - C  那么 C的调用路径就是A 跟 B.因为是一条线.

调用源:  A - B - C    那么一次一次的递推.一直到A. 那么 C的调用源则是A

判断:

1.调用路径上没有特殊情况.(特殊情况指 导致中断级的提高或者降低) 那么则这个函数执行时的中断级和它的调用源级别相同,

2.如果调用路径上面有获取自旋锁.则中断级别随之提高.如果有释放自旋锁.那么中断级别降低.

内核中中断级别.

调用源

级别

DriverEntry DriverUnload

Passive级别

各种分发函数

Passive 级别

完成函数

Dispatch 级别

各种NDIS回调函数

Dispatch 级别.

如果我们查询下Kerner API 那么也会发现有说明这个API是在什么级别使用.

例如:

可以看到中断级别是 <= DISPATHCH级别的.

疑问?

  如果当前代码运行在DISPATCH中,但是又必须调用PASSIVE级别的API怎么办.可以利用内核API降低当前中断级别吗?

答:

  不可以.Windows代码都是在规范的级别上运行的.任意的降低或者提高都会影响代码的执行.所以我们要调用这种API的时候.可以创建一个专门的线程来执行PASSIVE级别的代码.

  解决方法很多.不止这些. 可以网络上搜下资料. 博主也是自学.所以暂时还没接触到.

三丶内核中宏代码代表的意思

在内核中我们看API的时候.可以看到好多宏.而这些宏都是空宏, 是用来说明的.

比如:

  IN

  OUT

一个参数前边加上IN  代表这个参数是传递进去的.

一个参数前边带有OUT 代表这个参数是传出参数.

__in_bcount(StatusBuffsize) IN PVOID statusBuffer; 

这里的参数代表了. statusBuffer的大小依赖于StatusBuffsize这个参数来制定的.

四丶指定函数位置的预编译指令.

本来这个小主题可以放到第三个问题中说.单独说说明有点重要.

代码语言:javascript
复制
#pragma alloc_text()

上面这个宏表示我们的函数的可执行代码编译出来之后再.sys文件中的位置.

什么意思那..sys文件本质上其实就是PE文件.我们知道PE文件都有段.也有节.不同的节加载到内存中会有不同的处理情况.

而我们需要关心的有三种.

1.INIT节.  这个节的特点就是初始化完毕之后就会释放.不在占用内存空间.

2.PAGE节 这个节的特点是可以进行分页交换的内存空间.什么意思.其实就是我们的内存不够了.可以临时放到磁盘上.

3.PAGELK节. 这个节是默认的.如果我们不指定代码放在那里.那么就会放在这个节中. 特点是不能进行内存交换.也就是说不可以和磁盘交互.

而我们可以指定我们的代码放到哪个节当中.

比如我们的入口函数.这个函数只会调用一次.那么我们可以放到INIT节中.这样初始化完之后就没有了.不占用内核内存.因为内核内存是共享的.用完就没了.

例如:

代码语言:javascript
复制
#pragma alloc_text(INIT,DriverEntry)

注意的问题:

  如果我们将函数放入PAGE节中.那么代表我们这个函数运行中可以放到磁盘上.如果这样就会产生缺页中断. 所以如果放到PAGE节中的函数.那么不能调用DISPATCH级别的函数.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一丶函数多线程的安全问题
  •  二丶中断级别.
  • 三丶内核中宏代码代表的意思
  • 四丶指定函数位置的预编译指令.
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档