【该文章知识来源《极客时间刘超老师-趣谈Linux操作系统》向大神致敬。
趣谈Linux操作系统(极客时间)链接:
http://gk.link/a/10iXZ
欢迎大家来一起交流学习,一起探索Linux内核的奥秘,一起修炼硬本领,升职加薪。哈哈】
1.立项服务与进程管理
立项服务,在Linux 操作系统中就是创建进程。创建进程的系统调用叫fork。
在 Linux 里,要创建一个新的进程,需要一个老的进程调用 fork 来实现,其中老的进程叫作父进程(Parent Process),新的进程叫作子进程(Child Process)。
Linux 就是这样想的。当父进程调用 fork 创建进程的时候,子进程将各个子系统为父进程创建的数据结构也全部拷贝了一份,甚至连程序代码也是拷贝过来的。
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int count = 0;
pid = fork();//fork一个进程
if(pid == 0) {//pid为0,
//子进程干活
//系统调用execve来执行另一个程序
} else if(pid > 0) {
//父进程干活
} else {
fprintf(stderr,"ERROR:fork() failed!\n");
}
return 0;
}
对于 fork 系统调用的返回值,如果当前进程是子进程,就返回 0;如果当前进程是父进程,就返回子进程的进程号。这样首先在返回值这里就有了一个区分,然后通过 if-else 语句判断,如果是父进程,还接着做原来应该做的事情;如果是子进程,需要请求另一个系统调用execve来执行另一个程序,这个时候,子进程和父进程就彻底分道扬镳了,也就产生了一个分支(fork)了。
对于操作系统也一样,启动的时候先创建一个所有用户进程的“祖宗进程”。0号进程是所有进程的父进程。
有时候,父进程要关心子进程的运行情况,这毕竟是自己身上掉下来的肉。有个系统调用waitpid,父进程可以调用它,将子进程的进程号作为参数传给它,这样父进程就知道子进程运行完了没有,成功与否。
2.会议室管理与内存管理
在操作系统中,每个进程都有自己的内存,互相之间不干扰,有独立的进程内存空间。
对于进程的内存空间来讲,放程序代码的这部分,我们称为代码段(Code Segment)。
对于进程的内存空间来讲,放进程运行中产生数据的这部分,我们称为数据段(Data Segment)。
动态分配的,会较长时间保存,指明才销毁的,这部分称为堆(Heap)。
一个进程的内存空间是很大的,32 位的是 4G,64 位的就更大了,我们不可能有这么多物理内存。就像一个公司的会议室是有限的,作为老板,你不可能事先都给项目组分配好。哪有这么多会议室啊,一定是需要的时候再分配。(需要的时候分配)
进程自己不用的部分就不用管,只有进程要去使用部分内存的时候,才会使用内存管理的系统调用来登记,说自己马上就要用了,希望分配一部分内存给它,但是这还不代表真的就对应到了物理内存。只有真的写入数据的时候,发现没有对应物理内存,才会触发一个中断,现分配物理内存。
分配内存的系统调用,brk和mmap。
当分配的内存数量比较小的时候,使用 brk,会和原来的堆的数据连在一起,这就像多分配两三个工位,在原来的区域旁边搬两把椅子就行了。当分配的内存数量比较大的时候,使用 mmap,会重新划分一块区域,也就是说,当办公空间需要太多的时候,索性来个一整