操作系统
在说进程之前,我们先要了解操作系统的相关概念。
一、操作系统的概念:任何计算机系统都包含一个基本的程序集合,称为操作系统,笼统的理解,操作系统包括:内核(进程 管理、内存管理、文件管理、驱动管理)其他程序(例如shell程序等等)。
简单来说,操作系统是一款搞管理的软件,管理的是计算机上的软硬件资源。
二、操作系统存在的原因:操作系统可以与硬件交互,管理所有的软硬件资源,并且给应用程序提供一个好的执行环境。
操作系统是对软硬件管理的,而管理者与被管理者并不直接打交道。
进程也是由操作系统管理的。
三、操作系统如何管理进程: ①把进程描述起来 ②把这些描述的进程组织起来 (先描述,再组织)
进程
一、进程的概念
①用户角度:运行起来的程序就是进程,它占有着系统资源(CPU时间,内存等),程序运行起来需要被加载到内存。
②操作系统角度:进程就是操作系统对进程的描述,这个描述有一个名字叫PCB(进程控制块)。
在Linux操作系统下它的PCB是:task_struct.
二、task_struct
task_struct是Linux内核的一种数据结构,它会被装载到内存里并包含着进程的信息,其内容有很多主要有:
- 标示符:描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,进程不管在什么情况下都有其状态,退出代码,退出信号等。
- 优先级:进程在运行的时候也是要遵循优先级顺序的。
- 程序计数器:程序中即将被执行的下一条指令的地址,类似于EIP的作用。(保存下一步要执行的命令操作)
- 内存指针:程序代码和进程相关数据的指针。
- I / O 状态信息:包括显示I/O的请求,分配给进程的I/O设备和被进程使用的文件列表。
- 其他信息
三、操作系统如何管理进程
使用task_struct结构体描述进程,使用了双向链表将这些结构体组织起来进行管理。
四、查看进程信息
Linux平台下进程的信息可以通过 /proc 系统文件夹里面查看,里面存储着各个进程的ID。
进程的ID又叫做PID,父进程的ID叫做PPID.
还可以通过 ps -ef 、ps aux(可以查看并显示所有进程信息 )、 getpid()(在代码中获取进程pid)等查看进程信息。
五、通过系统调用创建进程
fork()函数:fork函数是产生子进程的函数,他有两个返回值,其中返回给父亲的是子进程的PID,返回给子进程为0。 并且在fork之后,子进程与父进程共享一份代码,但是数据各自私有一份。
示例:
图解:
综上,我们知道了如何创建进程:
- 使用 fork系统调用 通过 复制调用 创建一个子进程,调用进程为父进程,创建出来的新进程称为子进程,fork函数有两个返回值。父进程返回子进程的进程PID,子进程返回0.
- 父进程创建了子进程,所以父子进程的代码段是完全一样的,即他们运行的程序是一样的,但是他们的数据并不共用,数据是各自开辟空间,私有一份。
- 通过返回值判断分辨父子进程,来进行代码分流。
进程状态
一、 进程的不同状态
- R:运行状态,并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S:浅度睡眠状态,意味着进程在等待事件完成,但是这个睡眠状态是可以被中断的。
- D:磁盘休眠状态,也叫作深度睡眠状态,这个状态无法被中断,在这个状态的进程通常会等待IO的结束。
- T:停止状态,可以通过发送SIGSTOP信号给进程来停止进程,这个被暂停的进程可以通过发送SIGCONT信号让进程 继续运行。
- Z:僵尸状态,也就是进程在非正常运行结束以后,这个进程的父进程需要去维护这个进程,即读取这个进程结束的原 因,如果父进程一直不去维护和读取,那么这个进程就会变成僵尸进程,僵尸进程会造成一定程度的内存泄漏。
二、进程状态修改
通过kill指令杀死进程,改变进程的状态。
三、Z(zombie) - 僵尸进程
- 概念:只要子进程退出,父进程还在运行且没有读取子进程状态,子进程就进入Z状态。
- 产生原因:子进程先于父进程退出,他要保留退出原因在pcb中,因此退出后不会自动释放所有资源。子进程退出后操作系统会通知父进程说子进程退出了,此时需要父进程获取一下原因然后释放。假如父进程不管子进程的退出状态,子进程将进入僵尸状态,成为僵尸进程。
- 危害:资源泄露。
- 示例:
四、孤儿进程
父进程先于子进程退出,那么子进程变为孤儿进程,并进入后台运行。此时父进程变为Init进程,也就是说子进程如果后来退出了,Init进程将负责释放资源,因此孤儿进程最终不会变为僵尸进程。