
获得徽章 0
- x86 架构的实模式与保护模式的区别在于,在实模式下,CPU 的寻址方式为:直接从段寄存器中获取内存地址,称为「基址」,然后将基址左移 4 位(即乘以 16),再加上通用寄存器中的偏移量,就得到了它要访问的内存地址;而在保护模式下,CPU 的寻址方式为:段寄存器中的基址被放到了内存中某个地方,类似于一个表格,表格中的每一项是一个基址,叫做「段描述符」,段寄存器中保存的是在这个表格中的哪一项,称为「选择子」,CPU 先是从段寄存器中获取选择子,然后去内存中找到对应的基址,然后再用这个基址加上偏移量,才最终得到了它要访问的内存地址。
简单点来说,实模式是直接寻址,保护模式是间接寻址。
或许 x86 架构在设计实现上不如 ARM 或者 MIPS 优雅,但是就因为它推出的早,所以迅速占领了市场,再加上其完全向前兼容的优势(到现在为止,即使最新的 x86 CPU,一开始在电源打开处于实模式下,也能够运行针对先前任何芯片所撰写的软件),使得服务器和 PC 领域成为 x86 架构的天下。展开赞过43 - 这张图是 MIPS 分配内存的约定。栈由内存高端开始并向下增长。内存低端的第一部分是保留的,之后是代码段,存储程序指令,程序计数器中存的便是这部分内存的地址;代码段之上是静态数据段,是存储常量和其他静态变量的空间。再往上是动态数据区,习惯上称为堆,在程序运行中如果需要动态申请内存,就是在这个区域内给程序分配内存。堆和栈的大小是不固定的,他们两个相互增长,在此消彼长的过程中达到高效的使用。
C 语言通过显式的函数调用在堆上分配和释放空间,malloc() 在堆上分配空间并返回指向它的指针,free() 释放指针指向的堆空间。内存分配完全由 C 程序控制是很多错误产生的根源,忘记释放空间会导致“内存泄漏”,它会逐渐耗尽大量内存以至于操作系统可能崩溃,而过早地释放空间会导致“悬摆指针”(dangling pointer),会造成指针指向程序不想访问的位置。Java 的自动内存分配和垃圾回收机制避免了类似错误的发生。展开赞过33 - 将有符号数作为无符号数来处理,是一种检验 0 ≤ x ≤ y 的低开销方法,常用于检查数组的下标是否越界。
下面这条指令的含义是,将 $s1 和 $t2 作为无符号数来处理,如果 $s1 < $t2,则将 $t0 的值置为 1,否则保持初始值 0 不变。
sltu $t0, $s1, $t2
($t0、$s1、$t2 分别代表 3 个不同的寄存器,在这里姑且把他们当做变量来看待)
因为 $t2 是数组的长度,所以一定是正整数,最高位是 0(因为是补码表示),如果 $s1 是负数,那么它的最高位一定是 1 (同样是因为补码),那么把 $s1 作为无符号数一定比 $t2 大,所以上述指令执行之后 $t0 为 0;如果 $s1 中存的是比 $t2 大的正整数,那上述指令的执行结果肯定也是 $t0 = 0。
所以使用无符号比较 x < y,只用一条指令,就可以实现在检查 x 是否小于 y 的同时,也检查 x 是否为一个负数。展开赞过评论2 - 如图一所示,反向器的输出也是它的输入,这种电路我们称之为振荡器。由于从输出到输入有一定的时间间隔,所以振荡器输出端的输出信号呈周期性变化,即一会儿输出电压,一会儿不输出电压,也可以说是要么输出 0,要么输出 1,其输出序列如图二所示。有了振荡器,就可以实现电路的自动开关,从而使计算机自发地工作。因为随着时间的变化,振荡器的输出在 0 和 1 之间周期性变化,所以振荡器也被称为始终,这个变化的周期叫做时钟周期,周期的倒数就是振荡器的频率,也就是我们常说的主频。
所以为什么提高主频会使计算机运行速度变快,就是因为主频决定了计算机执行指令的频率,主频越大,单位时间内计算机执行的指令就越多,响应速度也就变快了。同样地,提高主频导致计算机功耗增大也是因为这个。展开赞过评论3 - 如图一所示,反向器的输出也是它的输入,这种电路我们称之为振荡器。由于从输出到输入有一定的时间间隔,所以振荡器输出端的输出信号呈周期性变化,即一会儿输出电压,一会儿不输出电压,也可以说是要么输出 0,要么输出 1,其输出序列如图二所示。有了振荡器,就可以实现电路的自动开关,从而使计算机自发地工作。因为随着时间的变化,振荡器的输出在 0 和 1 之间周期性变化,所以振荡器也被称为始终,这个变化的周期叫做时钟周期,周期的倒数就是振荡器的频率,也就是我们常说的主频。
所以为什么提高主频会使计算机运行速度变快,就是因为主频决定了计算机执行指令的频率,主频越大,单位时间内计算机执行的指令就越多,响应速度也就变快了。同样地,提高主频导致计算机功耗增大也是因为这个。展开评论点赞 - 一次性替换多个文件中的指定字符串
假设有三个文本文件,file1.txt,file2.txt,file3.txt,我想把这三个文本文件中的「good」替换成「nice」,可以用这个命令:
sed -i '.bak' 's/good/nice/g' file1.txt file2.txt file3.txt
其中,「'.bak'」是指定备份文件的后缀名,为了防止误操作,sed 要求修改文件内容时要备份,如果不想备份,可以用空字符串代替「'.bak'」,即:
sed -i '' 's/good/nice/g' file1.txt file2.txt file3.txt
s 前面可以指定行号,从而实现对文件局部的修改。比如「2,8s/good/nice/g」就是只把第 2 行到第 8 行的 good 替换成 nice。还有另外几种方式指定行号,见图一。如果把最后面那个「g」去掉,就只会替换每行中第一次出现的 good。
其实 s 命令是匹配正则表达式并替换,所以可以用「s/a\db/nice」将匹配到「a\db」的字符串都替换成 nice。
最后的文件列表,也可以用通配符匹配,比如把「file1.txt file2.txt file3.txt」改成「 *.txt」,就是替换所有以「.txt」结尾的文件中的内容。展开赞过评论1 - 命令选项和参数的区别
Linux 命令后面经常会跟一个或多个选项,这些选项会改变命令的行为,再后面可能会有一个或多个参数,这些参数是命令作用的对象。所以大多数命令看起来都是这样的:
command -options arguments
大多数选项都是以一个「-」开头,后面跟一个字母,比如「-l」,这种选项叫做短选项。还有很多来自 GNU 项目的命令,支持长选项,长选项是以「--」开头,且选项名往往是一个单词,比如最常见的「--help」。在下面这个命令中,我们给了 ls 两个选项,选项 l 是让 ls 以长格式的形式输出,选项 t 是让输出结果以文件的修改时间排序。
ls -lt
而下面这个命令中的长选项「--reverse」则是让「ls -lt」的输出结果逆序排列。
ls -lt --reverse
需要注意的是,Linux 命令选项和文件名一样,都是区分大小写的。展开等人赞过评论4 - 当我们使用带图形界面的 Linux 时,需要一个叫做“终端模拟器”的程序去和 shell 进行交互,通常在桌面菜单中就能找到。虽然桌面系统一般都简单地称之为“终端”,但其实这并不是真正的终端。KDE 使用的终端模拟器是 konsole,而 GNOME 使用的是 gnome-terminal,除此之外,Linux 上还有很多其他的终端模拟器可选。别看终端模拟器花样繁多,其实他们基本上只干一件事,就是给我们提供访问 shell 的通道。
图为 Ubuntu 上的终端模拟器。
PS:KDE 和 GNOME 为 Linux 桌面环境,Ubuntu 的桌面环境使用的便是 GNOME。展开评论点赞