精华内容
下载资源
问答
  • 游戏作弊-内存读写原理(一)

    千次阅读 多人点赞 2020-08-02 19:55:04
    第一课我们浅解安卓ROOT手机如何修改游戏内存 在当前流行的FPS,MOBA游戏中,我们几乎都能看到游戏外挂的身影,在FPS游戏中,可见变态功能层出不穷,例如加速,锁血 遁地,飞天,路飞,无后座,范围伤害等…,然而在...

    第一课我们浅解安卓ROOT手机如何修改游戏内存

    在当前流行的FPS,MOBA游戏中,我们几乎都能看到游戏外挂的身影,在FPS游戏中,可见变态功能层出不穷,例如加速,锁血 遁地,飞天,路飞,无后座,范围伤害等…,然而在MOBA游戏中,最常见的只有透视和自瞄。

    切入正题,如何操作内存?在安卓中,我们可直接操作/proc/${pid}/mem

    使用C语言pread函数

    ssize_t pread(int fd, void *buf, size_t count, off_t offset);
    

    简单解释下这个函数

    fd:要读取数据的文件描述符
    buf:数据缓存区指针,存放读取出来的数据
    count:读取数据的字节数
    offset:读取的起始地址的偏移量,读取地址=文件开始+offset。注意,执行后,文件偏移指针不变
    

    还有另一个函数:pread64
    很多人不知道pread64和pread的区别,其实pread64是用64位定位方式,用于对大文件的支持,与pread不同的是,pread64的偏移量参数为off64_t,而不是off_t

    读写游戏内存最重要的是获取游戏进程的PID,什么是PID?PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID。进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在android系统中一般不会把已经kill掉的进程ID重新分配给新的进程,新产生进程的进程号,一般比产生之前所有的进程号都要大。

    那么问题来了,如何获取游戏pid?

    第一种方式:
    遍历/proc/${pid}/cmdline
    cmdline文件储存的是当前进程的启动名(包名)

    直接贴代码:

    pid_t GetProcessID(const char *process_name)
    {
    	int id;
    	pid_t pid = -1;
    	DIR *dir;
    	FILE *fp;
    	char filename[32];
    	char cmdline[256];
    	struct dirent *entry;
    	if (process_name == NULL)
    	{
    		return -1;
    	}
    	dir = opendir("/proc");
    	if (dir == NULL)
    	{
    		return -1;
    	}
    	while ((entry = readdir(dir)) != NULL)
    	{
    		id = atoi(entry->d_name);
    		if (id != 0)
    		{
    			sprintf(filename, "/proc/%d/cmdline", id);
    			fp = fopen(filename, "r");
    			if (fp)
    			{
    				fgets(cmdline, sizeof(cmdline), fp);
    				fclose(fp);
    				if (strcmp(process_name, cmdline) == 0)
    				{
    					pid = id;
    					break;
    				}
    			}
    		}
    	}
    	closedir(dir);
    	return pid;
    }
    

    第二种方式:使用shell命令的pidof

    char *shell(const char *command)
    {
    	FILE *fp = NULL;
    	char line[256] = { };
    	char *result = (char *)malloc(2048);
    	memset(result, 0, sizeof(result));
    	fp = popen(command, "r");
    	while (fgets(line, sizeof(line), fp) != NULL)
    	{
    		strncat(result, line, strlen(line));
    	}
    	pclose(fp);
    	return result;
    }
    
    pid_t GetProcessID(char *process_name)
    {
        char cmd[256] = {0};
        sprintf(cmd,"su -c pidof %s",process_name);
    	char *id = shell(cmd);
    	return strlen(id) == 0 ? -1 : atoi(id);
    }
    

    如何读内存:

    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);//pid为获取到的游戏pid
    int fd = open(filename,O_RDWR | O_SYNC);//以可读写(O_RDWR)且同步(O_SYNC)的方式打开文件
    int buf = 0;
    pread(fd,&buf,sizeof(buf),内存地址);
    printf("value:%d\n",buf);
    

    学会了读取内存,那如何写入内存呢?
    这时候需要用到另一个函数:pwrite
    pwrite的参数和pread一样,我就不讲解了

    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);//pid为获取到的游戏pid
    int fd = open(filename,O_RDWR | O_SYNC);//以可读写(O_RDWR)且同步(O_SYNC)的方式打开文件
    int wbuf = 666;
    pwrite(fd,&wbuf,sizeof(wbuf),内存地址);//向指定地址写入指定值(修改地址的值)
    

    根据上两段代码,我们可以发现一个知识点:内存地址

    这个内存地址如何获取?
    在proc文件系统中,有一个内存段映射文件:/proc/${pid}/maps
    打开这个文件,我们可以得到以下结构:

    f1ed1000-f1ed9000 r--p 00000000 fc:02 3092        /system/lib/libsensor.so
    f1ed9000-f1edf000 r-xp 00008000 fc:02 3092        /system/lib/libsensor.so
    f1edf000-f1ee0000 rw-p 0000e000 fc:02 3092        /system/lib/libsensor.so
    f1ee0000-f1ee2000 r--p 0000f000 fc:02 3092        /system/lib/libsensor.so
    f1ee2000-f1ee3000 rw-p 00000000 00:00 0           [anon:.bss]
    

    关于maps文件各列解释,可以参考
    https://blog.csdn.net/lijzheng/article/details/23618365

    可以看出,第一列既为我们需要的游戏内存地址。
    现在问题来了,像gg修改器,我们如何在内存里搜索一个值呢?

    这时候又涉及一个知识点:值所在的内存范围

    为了方便,我们可以使用GG修改器的内存范围

    struct Memory
    {
    	int A = 32;
    	int As = 524288;
    	int B = 131072;
    	int Xa = 16384;
    	int Xs = 32768;
    	int Ca = 4;
    	int Cb = 16;
    	int Cd = 8;
    	int Ch = 1;
    	int J = 65536;
    	int Jh = 2;
    	int O = -2080896;
    	int Ps = 262144;
    	int S = 64;
    	int V = 1048576;
    } MemRange;
    
    
    int getMemRange(char *str)
    {
    	if (strlen(str) == 0)
    		return MemRange.A;
    	if (strstr(str, "/dev/ashmem/") != NULL)
    		return MemRange.As;
    	if (strstr(str, "/system/fonts/") != NULL)
    		return MemRange.B;
    	if (strstr(str, "/data/app/") != NULL)
    		return MemRange.Xa;
    	if (strstr(str, "/system/framework/") != NULL)
    		return MemRange.Xs;
    	if (strcmp(str, "[anon:libc_malloc]") == 0)
    		return MemRange.Ca;
    	if (strstr(str, ":bss") != NULL)
    		return MemRange.Cb;
    	if (strstr(str, "/data/data/") != NULL)
    		return MemRange.Cd;
    	if (strstr(str, "[anon:dalvik") != NULL)
    		return MemRange.J;
    	if (strcmp(str, "[stack]") == 0)
    		return MemRange.S;
    	if (strcmp(str, "/dev/kgsl-3d0") == 0)
    		return MemRange.V;
    	return MemRange.O;
    }
    
    

    如何搜索值:
    通过遍历内存段映射地址,判断值是否为搜索的值
    例如f1ed1000-f1ed9000,我们需要遍历f1ed1000到f1ed9000的所有地址的值来判断

    直接上代码:

    long start = 0xf1ed1000;
    long end = 0xf1ed9000;
    int value = 1;//我们要搜索的值
    char filename[256] = {0};
    sprintf(filename,"/proc/%d/mem",pid);
    int fd = open(filename,O_RDWR | O_SYNC);
    long size = end - start;
    int count = 0;//计数
    void *buf = calloc(1, size);
    pread64(fd,buf,size,start);
    int block_size = sizeof(int);
    for(int i = 0;i<size;i+=block_size)
    {
    	int search_value = *(int*)(buf + i);
        if(search_value == value)
        {
            //搜索到数值
            printf("index:%d address:%lx value:%d\n",i,start + i,search_value);
            count++;
        }
    }
    printf("搜索到:%d个数值\n",count);
    

    现在搜索数值会了,修改数值不就迎刃而解了吗?

    今天的教程结束,有不懂的可以私信问我。手打代码不易,看完加个关注,持续更新游戏作弊教程

    展开全文
  • 磁盘和内存读写简单原理

    千次阅读 2019-08-15 11:32:25
    当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页...

    当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页或几页载入内存中。

     


    我们在程序中的数据处理主要是操作磁盘和内存,硬盘是磁盘里面最常用的一种.以前有所谓的软盘,也是磁盘的一种,原理和硬盘是一样的.都是利用磁性物质的特性来保存信息.磁盘的原理就是利用电磁转换,学物理时我们知道电可以使物质带上磁性,而金属在磁场运动时切割磁感线时会产生电流.磁盘上有很多微粒的磁粉.当写通过磁头写数据时,磁头中的电流会导致磁粉极化,改变方向.读数据时,导体磁头经过磁粒的区域时会产生电流. 反正大概意思就是这样.

    硬盘的存储数据原理:
    我们知道信息存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片。假设,你用显微镜把盘片放大,会看见盘片表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化;凸起的地方代表数字1(磁化为1),凹的地方代表数字0。因此硬盘可以以二进制来存储表示文字、图片等信息。


    内存存储数据原理:
    而内存的原理就完全不同,内存是晶体管制作的(CPU也是晶体管做的),而晶体管的特性就是我们平时常说的用开关的开和关来表示1,0.
    通过一些门电路的组合可用来表示数字和实现复杂的逻辑功能.而内存主要是用来临时保存数据.CPU就是处理一些逻辑关系.

    晶体管由于必须得通电,然后用电流的有无状态来表示信息,充放电后电荷的多少(电势高低)分别对应二进制数据0和1,所以只有通电的时候可以保存数据,电一断内存里的晶体管状态就处未知状态就啥用处也没了.而磁盘断电后磁性物质还会一直保持原样.

    我们知道访问磁盘时就通过磁头去指到固定的地方然后读取数据.不过内存就不一样,不需要啥磁头去读取数据,它是有数据总线连接,我们是通过总线去读取内存的数据.

    磁盘的读写原理:(柱面号,磁头号,扇区号)


    确定磁盘地址(柱面号,磁头号,扇区号),内存地址(源/目):

           当需要从磁盘读取数据时,系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道,哪个扇区。

    为了读取这个扇区的数据,需要将磁头放到这个扇区上方,为了实现这一点:

             1)首先必须找到柱面,即磁头需要移动对准相应磁道,这个过程叫做寻道,所耗费时间叫做寻道时间,

             2)然后目标扇区旋转到磁头下,即磁盘旋转将目标扇区旋转到磁头下。这个过程耗费的时间叫做旋转时间。

    即一次访盘请求(读/写)完成过程由三个动作组成:
           1)寻道(时间):磁头移动定位到指定磁道 
           2)旋转延迟(时间):等待指定扇区从磁头下旋转经过 
           3)数据传输(时间):数据在磁盘与内存之间的实际传输

    内存的读写原理:(行地址+列地址)

    内存地址

    内存中的cell按矩阵形排列,每一行和每一列都会有一个对应的行地址线路(正规叫法叫做word line)和列地址线路(正规叫法是bit line),每个具体的cell就挂接在这样的行地址线路和列地址线路上,对应一个唯一的行号和列号,把行号和列号组合在一起,就是内存的地址。


    上图是Thaiphoon Burner的一个SPD dump,每个地址是一个字节。不过我们可以把这些数据假设成只有一个bit,当成是一个简单的内存地址表,左边竖着的是行地址,上方横着的是列地址。例如我们要找第七行、倒数第二列(地址为7E)的数据,它就只有一个对应的值:FD。当然了,在内存的cell中,它只能是0或者1。

    寻址

    数据要写入内存的一个cell,或者从内存中的一个cell读取数据,首先要完成对这个cell的寻址。寻址的过程,首先是将需要操作的cell的对应行地址信号和列地址信号输入行/列地址缓冲器,然后先通过行解码器(Row Decoder)选择特定的行地址线路,以激活特定的行地址。每一条行地址线路会与多条列地址线路和cell相连接,为了侦测列地址线路上微弱的激活信号,还需要一个额外的感应放大器(Sense Amplifier)放大这个信号。当行激活之后,列地址缓冲器中的列地址信号通过列解码器(Column Decoder)确定列地址,并被对应的感应放大器通过连接IO线路,这样cell就被激活,并可供读写操作,寻址完成。从行地址激活,到找到列地址这段时间,就是tRCD。

    从内存读取到磁盘预读
      由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:

      当一个数据被用到时,其附近的数据也通常会马上被使用。

      程序运行期间所需要的数据通常比较集中。

      由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

      预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

    参考:
    http://blog.csdn.net/hguisu/article/details/7408047
    硬盘的读写原理
    http://www.cnblogs.com/QQParadise/articles/2430204.html
    内存的工作原理及时序介绍
    http://blog.csdn.net/lujiandong1/article/details/44569161

    展开全文
  • 原理内存读写错误

    2009-01-14 11:03:00
    系统常常会自动弹出“xx内存不能为read或written”的错误提示,遇到这种故障信息时,我们该如何才能将它有效排除,同时确保下次运行容量较大的程序或者游戏时,系统不会再次出现系统内存读写错误呢?事实上,当我们...
     当我们在计算机系统中运行一些容量较大的程序或者游戏时,系统常常会自动弹出“xx内存不能为read或written”的错误提示,遇到这种故障信息时,我们该如何才能将它有效排除,同时确保下次运行容量较大的程序或者游戏时,系统不会再次出现系统内存读写错误呢?事实上,当我们不幸遭遇上面的故障信息时,我们可以尝试按照如下步骤进行依次排查:
      及时释放系统内存
      我们知道,在运行一些容量较大的程序或者游戏时,需要消耗相当的系统内存资源,要是此时内存空间不够时,那么系统内存读写错误的故障提示很有可能就会发生。为了有效避免这种错误提示,我们最好在运行容量较大的程序或者游戏之前,应该先将计算机系统重新启动一下,这样能够将系统内存空间充分释放出来;如果计算机内存空间本身就比较小的话,那么我们建议各位最好及时升级内存,以便拓展内存的有效使用空间,以防止由于系统内存不足而造成系统内存读写错误的发生。
      当然,在系统自身内存空间不足的情况下,我们应该先将那些随机启动的杀毒软件以及相关即时监控的程序暂时关闭掉,之后再尝试运行容量较大的应用程序或者网络游戏,因为杀毒软件及相关监控程序会在一定程度上消耗一些系统内存资源,将它们关闭可以节省不小的内存空间,从而能够有效避免内存读写错误现象的发生。当然,值得注意的是,我们在运行完大容量的程序或游戏之后,还必须记得及时将相关程序的监控功能全部打开。
      手工修复系统服务
      与系统内存读写操作有关的Windows ManagementInstrumentation服务要是发生错误的话,也会导致系统弹出内存读写错误的提示,所以当我们遇到这种错误现象时,可以尝试手工修复一下Windows Management Instrumentation服务,下面就是具体的修复步骤:
      首先用鼠标右键单击系统桌面中的“我的电脑”图标,从弹出的快捷菜单中执行“管理”命令,打开本地系统的计算机管理窗口,在该窗口的左侧显示区域,依次展开“服务和应用程序”/“服务”选项,在对应“服务”选项所在的右侧显示区域中,找到Windows ManagementInstrumentation服务,并用鼠标右键单击该服务选项,从弹出的快捷菜单中执行“属性”命令,打开如图所示的服务属性设置界面;
      其次在该设置界面的“常规”标签页面中,单击“停止”按钮,将WindowsManagementInstrumentation服务暂时停止运行。之后,打开计算机系统的资源管理器窗口,在该窗口中依次展开“Windows”、“ssystem32”、“wbem”、“repository”文件夹,然后将“repository”文件夹窗口中的所有文件进行一下备份,备份完成后将该文件夹中的所有内容全部清除掉;  
     接下来,重新启动一下计算机系统,待系统启动成功后,按前面操作打开Windows ManagementInstrumentation服务的属性设置界面,单击该界面中的“启动”按钮,相信这么一来Windows ManagementInstrumentation服务就能正常运行了。  修复系统损坏文件
      如果计算机系统不小心感染了病毒或者发生了误删除操作,那么与系统内存读写操作有关的系统文件很可能受到损坏,而这些系统文件一旦受到损坏的话,那么我们就很容易遭遇内存读写故障提示了。所以,我们一旦碰到内存读写错误的提示时,不妨按照如下步骤修复一下系统,看看系统是否存在损坏的文件:
      首先使用最新版本的杀毒软件,来对计算机系统进行彻底地病毒查杀操作,因为计算机系统一旦感染了病毒而不进行清除的话,我们即使修复了系统文件,病毒仍然有可能会继续破坏系统文件,所以及时使用杀毒软件来将计算机中的病毒全部清除干净,可以确保系统文件不会继续受到病毒的威胁。
      其次使用系统自带的“sfc”命令,来尝试将受到损坏的系统文件修复到正常状态。在修复受损系统文件时,只要依次单击“开始”/“运行”命令,在弹出的系统运行对话框中,输入字符串命令“sfc/scannow”,单击回车键后,该命令程序就会对系统每个角落处的系统文件进行搜索扫描,一旦发现系统文件的版本不正确或者系统文件已经损坏的话,它就能自动弹出提示界面,要求我们插入Windows系统的安装光盘,以便从中提取正常的系统文件来替代不正常的系统文件,从而达到修复系统文件的目的。要是系统修复操作成功的话,相信我们重新启动计算机系统时,就不会看到有什么不正常的现象了。
      移除无效插件程序
      在上网冲浪的过程中,许多插件程序会偷偷地安装到计算机系统中,而不少插件程序往往都有防删除的功能,因此这些插件很容易与其他的应用程序发生冲突,从而间接地引起系统内存读写错误的现象。为了给那些大容量的应用程序或游戏提供一个干净、稳定的工作环境,我们最好定期使用类似360安全卫士这样的程序,来查看系统是否被偷偷安装了各种无效的垃圾插件程序,一旦发现的话,那可以直接将它们从系统中及时卸载干净。
    展开全文
  • Java文件读写原理和虚拟内存 1,内核空间和用户空间 上图中的储户是没法直接从金库中存钱获取取钱的,如果这么做了,那么就非法了。这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户...

    Java文件读写原理和虚拟内存

    1,内核空间和用户空间

    在这里插入图片描述

    上图中的储户是没法直接从金库中存钱获取取钱的,如果这么做了,那么就非法了。这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户空间中的进程没法直接操作读写硬盘中的数据,我们需要通过内核空间来处理。
    空间
    在这里插入图片描述

    2,普通IO操作

    下图为普通IO的执行原理:
    在这里插入图片描述

    根据上图,当进程请求一个I/O操作,它会执行一个系统(open() , read() , writer() , close())调用将控制权移交给内核。
    当内核以这种方式被调用,它随即采取任何必要步骤,找到进程所需数据,并把数据传送到用户空间内指定的缓冲区中,这时常规进程就可以对缓冲区中的数据处理操作了,而内核试图对数据进行高速缓存或预读取,因此进程所需数据可能已经在内核空间里了,如果是这样,该数据只需简单地拷贝出来即可,如果数据不在内核空间,则进程被挂起,内核着手把数据读进内场。

    2.1 DMA是什么

    DMA(Direct Memory Access),即直接存储器存取,是一种快速传送数据的机制。数据传递可以从适配卡到内存,从内存到适配卡或从一段内存到另一段内存。

    2.2 Java实现文件读取和写入过程解析

    需求说明
    实际操作过程中,从D盘根目录下的ak.txt读取文件写入D盘根目录下的hello.txt文件内

    实现思路
    写两个方法,一个用于读取目标文件,一个用于写入目标文件–详情见代码注释

    代码内容: 文件读取和写入练习

    package con.cy.basic;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Lxy {
        /**
         * IO 测试
         *
         * @param args
         */
    public static void main(String[] args) {
        //实例化对象
        Lxy lxy = new Lxy();
        //用一个byte[]接受数据
        byte[] bytes = lxy.read("/Users/longxiangyu/Desktop/CGB2012/Three/Test1.txt");
        //将接受到的数据传入写入方法
        lxy.write("/Users/longxiangyu/Desktop/CGB2012/Three/Test2.txt", bytes);
    }
    
        //读取方法,设定传参是文件的String路径,返回一个byte[]数组
        private byte[] read(String str) {
        byte[] bytes = new byte[0];
        FileInputStream input = null;
        try {
            input = new FileInputStream(str);
            int read;
            bytes = new byte[1024];
            System.out.println("内容读取中...........");
            while ((read = input.read(bytes)) != -1) {
                for (int i = 0; i < read; i++) {
                    System.out.print((char) bytes[i]);
                }
                    System.out.println("\n内容读取完毕");
                }
                return bytes;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
                return bytes;
        }
    
    //写入方法,需要两个参数,一是写入路径,一是写入内容
    private void write(String str, byte[] bytes) {
            System.out.println("文件写入中-----");
            FileOutputStream output = null;
            try {
                output = new FileOutputStream(str);
            try {
                    output.write(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("文件写入完毕");
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    

    运行结果在这里插入图片描述

    运行前:
    在这里插入图片描述

    运行后:
    在这里插入图片描述

    2.3 Q&A

    Q:数据从内核空间拷贝到用户空间似乎多余,为什么不直接让磁盘把数据送到用户空间的缓冲区呢?

    1. 硬盘通常不能直接访问用户空间
    2. 磁盘基于块存储的硬件设备操作的固定大小的数据块,用户进程请求的可能是任意大小或者非对齐的数据块,在这两者数据交互过程中内核负责数据的分解、再组合工作,起到一个中间人的角色。

    2.4 总结

    当应用程序需要读取文件的时候,内核首先通过DMA技术将文件内容从磁盘读入内核中的buffer,然后Java应用进程再从内核的buffer(缓冲区)将数据读取到应用程序的buffer(缓冲区)。也就是有两次的文件复制

    3,虚拟内存

    3.1 什么是虚拟内存

    为了提升I/O效率和处理能力,操作系统采用虚拟内存的机制。虚拟内存意为使用虚假(或虚拟)地址取代物理(硬件RAM)内存地址。

    3.2 虚拟内存的好处

    1. 一个以上的虚拟地址可指向同一个物理内存地址。
    2. 虚拟内存空间可大于实际可用的硬件内存
      这样做的好处是省去了内核与用户空间的往来拷贝。

    3.2.1 一个以上的虚拟地址可指向同一个物理内存地址

    在进行IO操作时就可以将用户空间的buffer区和内核空间的buffer区指向同一个物理内存。这样用户空间的程序就不需要再去内核空间再取回数据,而是可以直接访问,节省内存空间。

    3.2.2 虚拟内存空间可大于实际可用的硬件内存

    当用户程序访问内存地址时,一般的操作如下:
    首先虚拟内存系统会到物理内存去查找该虚拟地址是否存在。
    如果存在,如A1,则直接从物理内存中读取;
    如果不存在,如A4则会抛出一个信号。这时虚拟内存系统会去磁盘空间中找,找到后再按一定的策略,将其置入到内存中。
    如将B2和A4交换,然后由用户程序就可以使用A4中的数据。这样就保证了用户程序可以读取一些大型的文件。

    从本质上说,物理内存充当了分页区的高速缓存;而所谓分页区,即从物理内存置换出来,转而存储于磁盘上的内存页面.
      把内存页大小设定为磁盘块大小的倍数,这样内核就可直接向磁盘控制硬件发布命令,把内存页写入磁盘,在需要时再重新装入。结果是,所有磁盘 I/O 都在页层面完成。对于采用分页技术的,现代操作系统而言,这也是数据在磁盘与物理内存之间往来的唯一方式

    3.3 虚拟内存的机制

    • 虚拟内存需要重新映射到物理内存
    • 虚拟地址映射到物理内存中的实地址
    • 每次只有进程的少量代码在物理内存中运行
    • 大部分进程代码位于存储器(交换区)中

    4,内存管理单元

    4.1 什么是内存管理单元

    负责管理计算机内存系统的计算机硬件称为内存管理单元(MMU)。现代 CPU 包含一个称为内存管理单元(MMU)的子系统,逻辑上位于CPU 与物理内存之间。该设备包含虚拟地址向物理内存地址转换时所需映射信息。

    4.2 内存管理单元的作用

    该组件充当CPU和系统内存之间的缓冲区,MMU通常是CPU的一部分,本身有少量存储空间存放从虚拟地址到物理地址的匹配表。此表称作TLB(转换旁置缓冲区)。所有数据请求都送往MMU,由MMU决定数据是在RAM内还是在大容量存储器设备内。如果数据不在存储空间内,MMU将产生页面错误中断。

    MMU的两个主要功能是:

    1. 将虚地址转换成物理地址。
    2. 控制存储器存取允许。MMU关掉时,虚地址直接输出到物理地址总线。 内存管理单元执行的功能通常可分为三个方面:
    3. 硬件内存管理
    4. 操作系统内存管理
    5. 应用程序内存管理

    虽然内存管理单元可以是一个独立的芯片组件,但它通常集成在中央处理器(CPU)中。
    操作系统利用内存管理单元能够实现以下功能:

    1. 虚拟内存:有了虚拟内存,可以在处理器上运行比实际物理内存大的应用程序。为了使用虚拟内存,操作系统通常要设置一个交换分区(通常时硬盘),通过将内存中不活跃的数据放入交换分区以腾出物理内存来为其他的程序服务。
    2. 内存保护:将特定的内存块设置为读、写和可执行属性。
      当 CPU 引用某内存地址时,MMU(内存管理单元)负责确定该地址所在页(往往通过对地址值进行移位或屏蔽位操作实现),并将虚拟页号转换为物理页号(这一步由硬件完成,速度极快)。如果当前不存在与该虚拟页形成有效映射的物理内存页,MMU会向CPU 提交一个页错误。
      页错误随即产生一个陷阱(类似于系统调用),把控制权移交给内核,附带导致错误的虚拟地址信息,然后内核采取步骤验证页的有效性。内核会安排页面调入操作,把缺失的页内容读回物理内存。这往往导致别的页被移出物理内存,好给新来的页让地方。在这种情况下,如果待移出的页已经被碰过了(自创建或上次页面调入以来,内容已发生改变),还必须首先执行页面调出,把页内容拷贝到磁盘上的分页区。
        如果所要求的地址不是有效的虚拟内存地址(不属于正在执行的进程的任何一个内存段),则该页不能通过验证,段错误随即产生。于是,控制权转交给内核的另一部分,通常导致的结果就是进程被强令关闭。
        一旦出错的页通过了验证,MMU 随即更新,建立新的虚拟到物理的映射(如有必要,中断被移出页的映射),用户进程得以继续。造成页错误的用户进程对此不会有丝毫察觉,一切都在不知不觉中进行
    展开全文
  • 内存实现功能:大家都知道安卓实现找坐标要识别数据,要制作字库找图找色,可能要很多尝试调试,还要加各种算法等一些麻烦的东西,如果用内存反而简单的,可能你在几分钟之内就能够把坐标、地图名字、...
  • 主要介绍了Go语言共享内存读写方法,实例分析了共享内存的原理与读写技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • CIH 病毒原理的应用--物理内存读写 CIH 病毒原理的应用--物理内存读写 CIH 病毒原理的应用--物理内存读写 CIH 病毒原理的应用--物理内存读写
  • 这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户空间中的进程没法直接操作读写硬盘中的数据,我们需要通过内核空间来处理,这样对于这两个概念应该会容易理解些。 空间 描述 用户...
  • GG修改器跨进程root读写内存原理(JNIRoot方案)

    千次阅读 多人点赞 2021-03-04 11:02:17
    关于跨进程读写应用内存的文章和案例我翻遍了csdn,简书,github,gitee,发现都不多且不详细,于是决定发布一篇博文来讲解一下原理。 进入话题 此技术核心用到了java反射技术和AIDL(IPC)管道通信技术。 大体逻辑 ...
  • 文件读写原理

    2019-09-22 15:04:50
    常识性的东西:任何程序的执行,都需要将数据读取到内存中! 引例:手机打电话的例子: 拨打电话需要:将声音信号转化为电磁信号,传递到卫星。。 接打电话需要;将电磁信息,转化为声音信号,才能听到声音。。。 ...
  • CIH 病毒原理的应用——物理内存读写 希望对大家有用
  • HDFS读写原理

    2019-12-15 18:58:16
    HDFS写流程 ...先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,不用担...
  • http://www.cnblogs.com/zhaoyl/p/3695517.html http://www.cnblogs.com/huxiao-tee/p/4657851.html#_label2
  • Hbase 读写 原理

    2018-02-13 16:34:00
    客户端读取信息流程 (1)client要读取信息,先查询下client 端的cache中是否存在数据,如果...设计用于读入内存频繁访问的数据,每个列族都有 (3)通过数据存在ROOT表中地址找到.META,最终找到HRegi...
  • 内存读写原理,字节的转换。  2.编写自己的内存读写类,这个类是项目中比较核心的类。  注:电脑中最基本的单位是“位”(bit),但是“位”(bit)这个单位太小,所以字节(Byte)是电脑存储容量的基本计量单位...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,141
精华内容 856
关键字:

内存读写原理