判断指定地址空间合法之总结
前题:之前一直在纠结,怎么样在代码中判断指定逻辑地址的内存空间可以被正常读写,或许有一个API接口来判断我们来判断这个事情。但是很遗憾的是,很长时间都没有找到解决方法。最近在重新把它拿起来好好分析一下,写一下关于这个问题的自己一点总结。
现状:当一次程序来读取一个非法的内存地址的时候,程序将会报出一下异常segment fault(段错误),然后异常掉整个进程。如果我们想判读一个地址是否可以被读写,那么我们就要试一下读写这个地址看会不会异常,或者看这个逻辑地址对应的物理地址所在内存页的属性,因为我们这里主要讨论的是用户态,希望不要讨论其他的东西。如果这个地址合法,那么读写当然很正常,并且很高兴的告诉你,进程还活着。如果这个地址非法呢?那么这个进程将会收到一个异常,并死掉。这是一个赌局,非死即活。当然我们不希望这样,判断一个地址是否合法,把整个进程的小命都打上,那么我们如何能够判断当前地址合法,并保证判断成功之后,我这个进程还活着。我想到了一个方法,举一个列子,这里把未知指针指向的空间当作一个坑,父进程告诉我,我要看看这个坑我能不能过去,那么他就找了一个替身,然后让这个替身过去踩两下,然后回来告诉我,这个坑我能不能过去。
方法:这里我使用父进程创建一个子进程,利用进程之间的特性,子进程将会拷贝所有父进程中的所有空间,除了代码空间。那么可以肯定的是,子进程和父进程所使用的内存空间在物理内存肯定是不一样的,那么为什么能够使用子进程来代替父进程判断这个指针指向的空间是否是合法的呢?虽然说子进程和父进程之间所使用的内存空间并不相同,但是子进程的空间结构是继承父进程的,可以看作子进程和父进程逻辑数据空间一样。如果子进程访问这个指针指向的地址异常(收到一个SIGSEGV信号),那么将响应子进程之前注册的SIGSEGV信号处理动作,子进程将发送一个信号给他的父进程,并终结掉自己。如果父进程收到这个信号,那么可以判断,这个指针指向的内存空间有问题,不能够使用。如果子进程访问这个指针活下来了,那么子进程同样会告诉父进程,我活下来了。然后父进程就知道这个地址空间是否合法了。
测试代码: