读 深入理解计算机操作系统(第3版) 记录


截图很好

1,文件是对i/o设备的抽象,虚拟内存是对i/o和内存的抽象,进程是对i/o和内存和处理器的抽象,处理器是除了i/o和内存之外的其他东西(在只有一个原始的计算机组成时),内存是指RAM。虚拟机是对i/o和内存和处理器和操作系统的抽象,网络可以看作是i/o设备。

读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录



读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录


读 深入理解计算机操作系统(第3版) 记录



1,大端模式与小端模式本身没有差别。inter cpu使用的是小端模式。
0x12345678
小端模式:高位存储高地址(0x12),低位存储低地址(0x78)。
大端模式:高位存储低地址(0x78),低位存储高地址(0x12)。
如下函数,c1=22,c2=11,就是小端模式,否则就是大端模式
int _tmain(int argc, _TCHAR* argv[])
{
short tmp = 0x1122;
char c1,c2;

c1 = ((char*)&tmp)[0];
c2 = ((char*)&tmp)[1];
printf("c1=%x,c2=%x ",c1,c2);

system("pause");
return 0;
}
下面的函数也可以
int check_end(){
int tmp = 0x12345678;
char* char_tmp = (char*)&tmp;
if(*(char_tmp+1) == 0x56)
return 1;
else
return 0;
}
2,先判断计算机是大端还是小端。然后按照大小端打印出某种类型每个字节数据。打印int[] arr = {1,2,3,4};时,依次打印出1000 2000
在小端模式下,int类型的4个字节也是按照小端模式打印为:1 0 0 0,1为低地址低位。

void check_end1(){
long l_1 = 0x11223344;
char* c1 = (char*)&l_1;
if(*c1==0x44)
cout<<"小端模式"<<endl;
else if(*c1==0x11)
cout<<"大端模式"<<endl;
if(((char*)&l_1)[0]==0x44)
cout<<"小端模式"<<endl;
else if(((char*)&l_1)[0]==0x11)
cout<<"大端模式"<<endl;
}

int print_byte(void* inPtr,size_t size){
char* cPtr = (char*)inPtr;
if(cPtr==NULL)
return -1;
int inPtr_size = 0;
while(inPtr_size<size)
{
printf("%x ",*cPtr);
inPtr_size++;
cPtr++;
}
}
打印数据的每一个位。如:打印int时,将int分成4个字节,由低位到高位依次打印。每个字节8个位也是按低位到高位依次打印。

int print_bit(const char c1,size_t length){
char c2 = c1;
c2>>=length;
if((c2&0x1)==1){//起初我是这样写的:c2&0x1==1,因为==的优先级大于&,所以这个就相当于:c2&true即c2&1。
printf("1");
return 1;
}else if((c2&0x1)==0){ 
printf("0");
return 0;
}
}

void print_bit_all(void* inPtr,size_t size){
char* c_ptr = (char*)inPtr;
if(c_ptr==NULL)
return;
int c_ptr_size = 0;
while(c_ptr_size<size){
for (int i = 0; i < 8; i++)
{
printf("%x",((*c_ptr)>>i)&1);
}
c_ptr_size++;
c_ptr++;
}
}

3,char与int与char[]与string。
char与int没有区别,它们之间可以相互强转,都可以赋值为整数,字符。在内存中都以2进制存储。char与int与short是一样的关系。
char c2 = 'a';
int i2 = 0x12345678;
short s2 = 'a';
for (int i = 0; i < 4; i++)
{
printf("char %d %c   ",((char*)&i2)[i],((char*)&i2)[i]);//将int作为char打印出来
}
如下的程序中,i1和i2的打印是同一个值。对于字符来说,256是它的模,很明显i1 i2的写法中,
‘A’进位了(小端模式下,至于是‘a’还是‘A’进位是由编译器还是什么决定,我也不清楚)。
int i1 = 'Aa';
int i2 = 'A'*256 + 'a';
printf(" %d %d",i1,i2);//i1和i2的打印是同一个值。

4,浮点数2进制存储。
推荐阅读:
https://zhidao.baidu.com/question/1430100495056721579.html
https://wenku.baidu.com/view/03f1871cfc4ffe473368ab98.html
http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

浮点数使用一个公式来计算值:浮点数=(−1)^S×M×2^E。
对于32位的浮点数,00000000 00000000 00000000 00000000。
[0(S)1位][0000000 0(E)8位][0000000 00000000 00000000(M)23位]
S是最高位,1为负数,0位正数。
E是最高位后的8个位。
M是其他的23位。

E:E为一个无符号整数(unsigned int)。这意味着,如果E为8位,它的取值范围为0~255;
但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再减去一个中间数,
对于8位的E,这个中间数是127;比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

M:IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。
比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

例:将10进制的-12.5存储为2进制。
12 = 1100。整数部分按照正常情况存储。
0.5 = 1。小数部分按照2^(-n)存储。小数点后第1位为0.5(1/2),低2位为0.25(1/4),第3位为0.125(1/8)。
即:小数点后的二进制.1就是十进制0.5,二进制.01就是十进制0.25,二进制.11就是十进制0.75。
-12.5 = 1100.1。左移3位就是1.1001(需要去掉前面的1),E = 3 + 127 = 130 = 1000 0010。
最后为:1(符号位) 1000 0010(E的值) 10010000000000000000000(M的值)

例:将2进制的-12.5转化回10进制。
将 1(符号位) 1000 0010(E的值) 10010000000000000000000(M的值) 转化回-12.5 。
将该2进制浮点数分成3段,知道了符号为*-1,E = 120-127 = 3 。M = 1.1001(把1加回来)
根据E的值为3,M右移3位。(如果E的值为-3,那就是左移3位)。M = 1100.1 。分成整数和小数部分后,按照相应的公式得:1100 = 12 。1 = 0.5 。

指数E还可以再分成三种情况:
浮点数=(−1)^S×M×2^E。
1,E不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),
得到真实值,再将有效数字M前加上第一位的1。
2,E全为0。这时,浮点数的指数E等于1-127,不是0-127,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。
然后再左移126位,这样做是为了表示±0,以及接近于0的很小的数字。如何出现:直接设置为0或者0.很小很小,打印出来就都为0 。
3,E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
如果有效数字M不全为0,表示这个数不是一个数(NaN)。如何出现:即使设置一个很大很大的数,也无法出现E全为1时的情况。