目录
- 操作系统
- 进程的基本概念
- 进程创建(fork)
- 进程状态
- 僵尸进程
- 孤儿进程
操作系统
操作系统是一个管理计算机软硬件资源的软件,它包括内核(进程管理,内存管理,文件管理,驱动管理)和其他程序(例如函数库, shell程序等等)
目的:
1.与硬件交互,管理所有的软硬件资源。
2.为用户程序(应用程序)提供一个良好的执行环境。
操作系统管理软硬件资源: 描述+组织
描述起来,用struct结构体
组织起来,用链表或其他高效的数据结构
进程的基本概念
程序是一个静态的概念,程序本质就是一个文件,是静态的,存储在磁盘当中。
进程是一个动态的概念,程序运行起来之后,就叫做进程,静态是动态的,由操作系统管理。
进程是程序的一个执行实例,正在执行的程序等,
从内核观点看,进程就是担当分配系统资源(CPU时间,内存)的实体。
进程被放到一个叫做进程控制块的数据结构中(PCB),可以看成是进程属性的集合。
Linux中PCB是task_struct ,task_struct是Linux内核的一种数据结构,它会被装载到内存里并且包含着进程的信息
task_struct包含的内容
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息
CPU通过task_struct中的内存指针来找到程序在内存中的地址,可以通过上下文数据来记录运行中程序的各种信息,通过程序计数器来找到这个程序即将执行的下一条指令的地址。
所有运行在系统里的进程都以task_struct链表的形式存在内核里
进程创建(fork)
进程的信息可以通过 /proc 系统文件夹查看
通过fork创建一个新的进程时,这个新的进程就是原先进程的子进程
fork有两个返回值
pid_t fork (void)
pid_t相当于int
失败:返回小于0的值
成功:
给子进程返回0,给父进程返回子进程的pid。
父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
写时拷贝:只有当数据发生数据修改的时候,才分配给一个物理内存,并将页表当中的映射关系改掉。
子进程创建的时候,它从父进程的PCB中复制了很多数据,如内存指针、上下文数据、程序计数器等,所以它的代码、数据以及运行的位置,都与父进程一模一样。
获取当前进程的pid,使用getpid函数
获取当前进程的父进程的pid,使用getppid函数
如果创建子进程,希望它和父进程执行不一样的操作,那么我们该怎么实现呢? 可以用 if 进行分流
插入图片描述](https://img-blog.csdnimg.cn/2bc198f986c74622b0b65f945ade4701.png)
进程状态
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping) : 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态
Z僵死状态(Zombies):进程已经退出了但是资源还没有完全被释放的一种状态。
僵尸进程
僵死状态是一个比较特殊的状态。当子进程退出的时候,如果父进程没有读取到子进程的返回值,这时子进程就进入了僵死状态。
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。
刚开始父子进程都处于休眠状态,五秒后子进程退出、但是父进程还在睡眠状态没有读取子进程退出信息,子进程就变为了僵尸进程。使用kill-9指令也无法杀死僵尸进程,只能等待父进程读取退出信息或者杀死父进程。
僵尸进程危害:维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说, Z状态一直不退出, PCB一直都要维护。当一个父进程创建了很多子进程,就是不回收,那么就会造成内存资源的浪费。
孤儿进程
父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号init进程领养,由init进程回收
init进程本身就会创建许多进程,本身Init进程创建的子进程,不能称为孤儿进程
我先让父进程退出,看到子进程的ppid为1,也就是init进程,由Init进程回收。