API Caller,计算机网络和算法

来源:互联网 发布:淘宝美工装修 编辑:程序博客网 时间:2024/05/23 11:22


我只是一个高中生,对编程有深切的热情,我学习不好,但是玩编程也玩了三年多年了,最近建了一个CSDN博客,看见有个征文,于是也来凑凑热闹:)若有路过的前辈和大神望能指点一二:)

计算机程序是什么?从本质上说,程序是一段二进制机器码!本身是0和1的组合,由具体的机器来执行这些机器码,也就是说机器码是给机器读的一份指令,机器按照指令去执行操作(往往是读写寄存器或内存)。因为人们直接用机器码写程序简直是在燃烧脑细胞啊有木有,于是人们发明了汇编语言,随后,C,C++,C#,F#,JAVA,PHP等等等等语言就冒了出来,简直是各领风骚数百年啊。不知道各位看官发现没有,之所以出现了这种进步(退步?),是为了编写程序更加方便吗,那肯定是的,换一句话说,是为了让程序员能够更容易地构建自己的算法,而不必为了繁琐的语法而浪费时间和精力。

算法究竟是什么?顾名思义,算法就是解决问题的方法,要是按照这个思路,那么算法可谓是渗透到了计算机这个神奇的世界里。

例子1:API Caller
API(应用程序接口),是对各种平台编程中的核心,我看到征文那儿的评论里就有个人说,现在的程序员很多都是API Caller,我一想这话太对了,就像我一样,整天泡在MSDN资料库里翻API文档,毕竟Windows内核都有人设计的非常完善了,API又非常丰富,调用API,就能解决大部分的问题,但是我们一行代码就能调用了的API,是如何运作的呢?API的调用,难道就不是一种算法吗?如果没有算法,API也不会出现了。

(1)Windows对API的处理过程

当我们从SDK调用一个API时,我们调用的是头文件中的函数。头文件中的函数会在编译时编译成“弱符号”,连接器会把弱符号的调用定位到有导出函数的lib库中,lib中有函数的定义,函数定义已经被编译成“强符号”并导出了,所以,我们其实调用的是lib里的函数,但lib里的函数却并不是真正的API实现,它们只是进一步调用了在IAT(函数导入地址表)中的函数,也就是Win32子系统的dll动态连接库中的函数,IAT就是在PE装载器通过exe的导入表中的dll导入目标进程的虚拟内存后由系统构建的,当然,如果dll建议的装入位置与虚拟内存中现有的模块(PE文件装入内存后叫进程的一个模块)冲突了,PE装载器会通过一定的算法进行“重定向”。而调用的dll里的API还不是真正的实现。(有没有要疯的感觉)比如,调用ReadFile读磁盘上的文件,它会进一步调用ntdll.dll里的Native API(原生API,用Linux的说法就是“系统调用”),而原生API当然也不是真正的实现了啊,原生API会进入内核模式(例如int 2e中断),调用服务函数(例如SSDT,系统服务描述符表,里的函数),这里又有一系列的复杂过程,最终由系统内核的I/O管理器生成内核IRP请求并发送到设备栈最上层的设备所在驱动程序的派遣函数中,在这之前,操作系统会在内核内存虚拟空间分配一段缓冲区,并把缓冲区的地址写进IRP结构,而且由于过滤驱动的存在,上层设备派遣函数会把Irp发往下一层设备的派遣函数,最终发送到卷设备(虽然卷是一个逻辑上的概念,但Windows为其创建了设备),再发往磁盘设备,磁盘设备再调用总线驱动,最终控制磁盘从指定位置读出来应用程序需要的数据,并把数据写到缓冲区中,然后设备栈开始回卷,从下向上调用设备的完成例程函数,返回到用户模式下时,内核缓冲区中非数据被复制到应用程序提供的用户模式缓冲区之中,API调用线程解除阻塞状态,至此API调用完成!

把上述过程用一张图表示出来:

(我尝试用画图画了下,难看至极,因此只能手绘了大笑

如果你之前没有了解过这方面的知识,或者说没有接触过驱动开发,你一定会被Windows的API调用过程所震撼了吧。试问:这些是不是算法?答案是肯定的,而且是非常复杂而完善又灵活的算法。

上面是从宏观上说的,下面来一个微观的(别闹)

(2)函数标准调用约定__stdcall

我们知道,在intel 80x86平台和WOW64(Win32 on Windows 64)平台上,API都是采用的标准调用(__stdcall),标准调用其实就是一种实参以右向左入栈,并且不用调用者手动请栈的调用约定,那么,编译器是怎么处理的stdcall呢?

例如调用 function(a,b);

首先,b入栈,a入栈(实参以右向左入栈)如图

接着,调用者把返回地址入栈,CPU执行现场跳转到函数中,如图

随后,ebp寄存器中的数据入栈,然后堆栈的栈顶指针esp的值给ebp,然后ebp的值在函数返回之前不在变化,以后函数访问局部变量和函数返回清栈时用。随后局部变量和相关寄存器入栈,然后函数中的核心指令开始执行,如图

函数最终以ret number返回。

可见API Caller上至宏观上Windows的严密处理,下到微观上的调用约定,都是无数前辈们耗尽心血设计出的又完善又灵活,效率又高的算法!如果没有这些算法,像我这样的API Caller那可就悲剧了。

例子2:以太网和Internet

计算机网络是一个充满神秘色彩的地方,而我们最常见的网络,自然就是以太网,小区网络,公司网络,学校机房网络统统都是以太网,甚至在家或者在大商场里手机用个WiFi还是以太网!说起以太网,人们首先就是吐槽它的安全性,漏洞百出的以太网,让人又恨又爱,恨它不安全而有可能损坏自己的利益,又爱它可以尽情的搞破坏,什么ARP洪泛啊,MAC欺骗啊,会话劫持啊,VLAN广播风暴啊,可以劫持或攻击别人,让人沉迷其中不能自拔(人性啊,,)。但今天的重点不在安全上,其实链路层做到很安全也不太可能。

(1)ARP协议

原谅我盗用了《TCP/IP详解 卷一》中的图(懒得再画了),ARP协议想必各位看官都知道,现在的杀软(比如360大数字)都有防ARP欺骗防火墙,懂点电脑的都知道静态绑定网关,可见这种hacker技术已经普遍到什么地步了(网上源码虽不至于烂大街,但也是有不少)。

当我们要与子网中某个IP(比如网关)通讯时,如果ARP高速缓存中没有他的MAC,就发送一份ARP请求报文,广播到以太网里的每一个接口上,若一台主机检测到请求的IP和自己收到报文的网卡的IP一样,那么就发送一份ARP回复报文给源主机,同时双方把对方加入到ARP高速缓存,之后两台主机就可以进行链路层的通信了。

看起来很简单的算法,但却是以太网链路层通信的根本啊!如果没有所谓的“漏洞百出”算法,那我们又如何尽情享受信息时代的网络呢?!

(2)路由决策

我们知道,一台主机能否与另一台主机通信,除了要求他们能够(不管是直接还是间接;不管是什么链路,以太网,令牌环,点对点等等)相连,还要求他们之间可以路由,也就是说主机和每一个跳点的路由策略必须保证他们可以被路由。我们知道,每一台主机上都保存有一张路由表,系统内核或协议驱动就是通过这个表进行路由决策的。

这是我手机现在的路由表:

U:路由可用。
G:路由是到一个网关。如果没有这个标志,说明主机和Destination是直接相连的,而通信的Gateway应该直接给出Destination的物理地址。
H:路由是到一个主机,如果没有该标志,说明Destination是一个网络,此时写成网络号+子网号,主机号为0
D:路由是ICMP重定向报文创建的
M:路由被ICMP重定向报文修改

协议驱动程序接到上层应用程序通过socket连接另一个IP时,判断完这个IP是合法的一台主机地址后,它会查询路由表,如果路由表中有这一项,那么就直接安安照这一个条目发送的指定路由,根据上面说的标志判断物理地址,通过这一条指定的网卡发出去 (因为一个主机可以有很多个网卡);否则对这个IP进行子网寻址,通过子网掩码和这个IP进行按位与运算,可以得出这个IP是不是同一个网络的IP,查阅路由表,IP的子网寻址结果在一个网络条目中,就按照这一条发送,目的IP为对方的IP,再构造整个包,通过路由表中这一条指定的网卡发送出去;如果没有这样的条目,那么就按照路由表中的默认条目发送,这样包一般发送到网关,再由网关进行路由决策,把这个包转发到哪个下级网络上。

这就是Internet的网络通信的基本,如果没有前辈们设计好的路由决策的复杂算法,那我们又如何尽情享受信息时代的互联网呢?!

小结:
所以说,算法已经渗透到底层程序编写和编程思想的每一个角落,没有对算法的研究,这些“基石”就不会但生,今天的精彩的网络时代就不会到来,我这样的API Caller也就没有了享受编程乐趣的机会。如果想要自己构建底层,自己制作系统内核,自己编写协议栈。。。。如果离开了算法,这些只能是美好的幻想,没有实现的一天。不否认没有必要要让每一个程序员或编程爱好者都掌握复杂的算法,但是如果想在这方面取得很高的成就,离开了算法,恐怕可难喽。

但是,我想说明的一点是,有很多人认为只有高深的算法才是算法,这么认为也无可厚非,但是他们往往把问题看得太“死”,就认那些有名的算法才是算法,我最讨厌这种观点了,算法是可以灵活使用的,而某些人净把算法当作“公式”对待,我也看过一些算法的书和文章,通常那里面把每种问题都用一些固定的算法来写,还说是这个问题是xxx算法,那个问题是xxx算法,xxx有几种写法,还有用递归的,每次看见他们这么肆无忌惮地用递归,我都满怀恶意的想如果写驱动里面不知到得蓝屏多少次,更让人无法忍受的是,对算法这么写的解释和思想往往只是一笔带过,或者说压根没有。我只能说,他们根本就没有认识到精髓,只会套公式一般地使用算法,我也下载了试读本《算法的乐趣》,读了一下,觉得比较不错,至少不像上面说的那种书一样无聊 。算法是灵活掌握问题的前提下,高度灵活的一种东西,试问:这种“会算法”和API Caller还有何区别?!

谢谢!

0 0
原创粉丝点击