进程地址空间

引入地址空间

静态变量和栈空间变量

进程地址空间_第1张图片

进程地址空间_第2张图片
进程地址空间_第3张图片

静态变量默认是被初始化的
存放在初始化和为初始化空间中
static已经变成了全局变量

命令行参数和环境变量的增长方向

这里观察的是命令行参数环境变量的地址
命令行在下,环境变量在上,向上增长
进程地址空间_第4张图片
进程地址空间_第5张图片


进程地址空间

进程地址空间_第6张图片

进程地址空间_第7张图片

如果他们是同一块儿空间,为什么打印的结果却不一样呢,我们知道肯定是父进程先跑完,在子进程进程输出的时候a应该是1才对——我们看到的只是虚拟地址空间


进程地址空间_第8张图片

1.子进程是父进程的拷贝,(父子进程代码和数据是共享的,只有在数据进行改变时才进行写时拷贝,子进程继承父进程的pcb里的大部分内容,地址空间,页表,并且继承的时候每个页表对应的权限默认为只读的状态)他们通过页表进行映射到物理内存,物理内存由操作系统进行管理
2.因为进程之间是独立的,他们本来对应的是相同的物理内存,但是当有一方进行改变的时候,就需要将发生改变的那一方进行拷贝(写时拷贝),更改页表的指向,指向新的物理空间


页表是有权限的

对数据的权限限制有r,w,rw,一般默认为r
进程地址空间_第9张图片
进程地址空间_第10张图片
字符串存在常量区,权限是只读的,操作系统检测到要修改变量,就会产生报错


进程地址空间_第11张图片

进程地址空间_第12张图片

加const是为了增强代码的安全性,错误早发现早处理


在父进程数据拷贝给子进程的时候,会将页表权限rw->r,因为子进程是父进程的拷贝,页表也会单独有一份,父进程和子进程的页表都会发生改变;当其中有一方进行修改数据,但是检测到页表对应的数据是只读的,此时os将介入,重新开辟空间,将原来的数据拷贝过来,再进行修改,完成后权限就会到了rw(缺页中断)

进程终止

进程退出状态:
1:代码执行完,结果正确
2:代码执行完,结果错误
3:代码没执行完,进程异常
只有代码执行完的退出结果才是有意义的


主函数退出——退出码

进程终止会有一个返回值(return)——表示退出情况,0表示成功,非0表示失败发生错误
使用echo $?观察最后一次退出情况

进程地址空间_第13张图片

第一次:139表示出错
第二三次:0表示正常退出
因为这个命令记录的是最后一次的退出情况,我们明白命令也是一种程序,echo是正常运行的,所以返回0


其他函数退出——错误码

调用库函数,错误码错误码保存在errno
调用自己的函数,普通函数的返回值一般表示的是函数的结果,特殊情况下,错误码需要自己设置
进程地址空间_第14张图片
进程地址空间_第15张图片
通过errno的方式观察库函数的错误码


进程异常

本质:收到异常信号
进程地址空间_第16张图片
每种信号都是一个宏,每个信号都是不一样的


exit & _exit

exit是库函数
_exit是系统调用
进程地址空间_第17张图片
exit中的参数表示返回的退出码

_exit不会刷新缓冲区
进程地址空间_第18张图片

进程地址空间_第19张图片
exit会刷新缓冲区
进程地址空间_第20张图片
进程地址空间_第21张图片

证明缓冲区不是在系统中的

进程等待

进程地址空间_第22张图片

wait

等待任意一个进程
父进程等不到就卡死
进程地址空间_第23张图片
我们能看到,父进程一直在等待,子进程一直在运行


waitpid

等待特定的pid
进程地址空间_第24张图片进程地址空间_第25张图片

exit的参数是1可是为什么status返回的是256呢
进程地址空间_第26张图片
status存的信息是错误码+信号


父进程和子进程fork之后谁先运行取决于调度器

你可能感兴趣的:(网络,服务器,java)