./运行我们的进程——指令级别
fork()——代码层面创建的子进程
fork()函数
当我们调用fork()函数时,会产生id=0的子进程和id>0的父进程,也就是使代码进行分割。
1、为什么fork要给子进程返回0,给父进程返回子进程pid?
答:返回不同的返回值是为了区分让不同的执行流,执行不同的代码块。
一般而言fork之后的代码(代码不会被修改),父子共享。而数据不能共享(因为数据可能被修改)【理论上,子进程会把父进程的所有数据拷贝一份,这样保证了数据的独立性,但这容易造成数据冗余(因为子进程很少使用全部父进程),因此刚开始时数据是共享的,但当子进程尝试去修改父进程的数据时,会将父进程的数据拷贝到一个新的空间,修改数据时会对该新的空间内的数据进行修改】
2、一个函数是如何做到返回两次的?如何理解?
答:pid_t fork(void)——》1、创建子进程PCB;2、填充PCB对应的内容
3、让子进程和父进程指向相同的代码;4、父子进程都是有独立的task_struct,可以被CPU调度运行了
3、一个变量怎么会有不同的内容?如何理解?
答:**任何平台,进程在运行的时候,是具有独立性的。**因为数据可能被修改,不能让父进程和子进程共享同一份数据
4、fork函数,究竟在干什么?干了什么?
答:进程=内核数据结构+代码和数据
创建子进程:系统中多了一个进程,代码共享。为什么要创建子进程?——》为了让父和子执行不同的事情——》要让父和子执行不同的代码块——》让父和子由不同的返回值!!!
5、如果父子进程被创建好了,fork()后,谁先运行呢?
答:谁先运行是由调度器决定的,这是不确定的。
调度器是什么?
答:决定哪个程序去运行。
bash如何创建子进程?——》调用fork();——》fork()执行解释新命令
进程的状态
1、介绍一下一般的操作系统学科 进程状态:运行、阻塞、挂起
1、运行状态:在运行队列中,取队列的头,凡是在运行态队列中的,都是运行态(R)。一个进程只要把自己放到CPU上开始运行了,是不是一直要执行完毕,才把自己放下来?——》不是,原因(while(1)死循环)——》因此,每一个进程都有一个叫做**时间片(10ms)**的概念。
在一个时间段内,所有的进程代码都会被执行。——》并发执行。因此,代码中会有大量的把进程从CPU放上去,拿下来的动作——进程切换
2、阻塞状态:
3、挂起状态:
2、具体的Linux状态是如何维护的?
- R运行状态(Running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠状态(Sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
- D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T停止状态(stopped):可以通过发送sigstop信号给进程来停止进程。这个被暂停的进程可以通过发送SIGCONT信号来让进程继续运行。
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表中看到这个状态
- Z僵尸进程(Zombie):子进程死亡而没被父进程回收时的状态。
僵尸进程的危害
- 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样。可父进程一直不读取,那子进程就会一直处于Z状态!
- 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB就一直都要维护!
- 倘若一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。
4、孤儿进程
父子进程,父进程先退出,子进程的父进程会被改成1号进程(操作系统)
父进程是1号进程—— 孤儿进程
该进程被系统领养。
为什么要被领养???
答:因为孤儿进程未来也会退出,也要被释放。
进程优先级
1、优先级是什么?
答:优先级是对于资源的访问,谁先访问,谁后访问。
2、为什么?
答:因为资源是有限的,所以注定了进程之间是竞争关系(竞争性)。
操作系统必须保证进程之间良性竞争。
如果进程长时间得不到CPU资源,该进程的代码长时间无法得到推进——该进程的饥饿问题。
3、怎么办呢?
基本概念
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权利。。
配置进程优先权对多任务环境的linux很有用,可以改善系统性能(不一定)。 - 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
查看系统进程
命令
ps -al
其中:
- UID:代表执行者的身份
- PID:代表这个进程的代号
- PPID:代表这个进程的父进程的代号。
- PRI:代表这个进程可被执行的优先级,其值越小越早被执行
- NI:代表这个进程的nice值
PRI和NI
- PRI即进程的优先级,或者即程序被CPU执行的先后顺序,此值越小该进程的优先级别越高。
- NI即nice值,表示进程可被执行的优先级的修正数值
- PRI值越小越快被执行,加入nice值后,使PRI变为:PRI(new)=80+nice
- 因此,当nice值为负值的时候,那么该进程的优先级值将变小,即其优先级会变高,则其越快被执行。
- 所以调整进程优先级,在Linux下,就是调整进程nice值。
- nice取值范围是-20到19,共40个级别。Linux不想过多让用户参与优先级的调整,在我们对应的范围内进行优先级调整。80——》[60,99]
- 需要注意的是:进程的nice值不是进程的优先级,这两个不是一个概念,但进程nice值会影响到进程的优先级变化,可以理解nice值是进程优先级的修正数据。
当然,不建议执行修改优先级的相关命令。
其他概念
- 竞争性:系统进程数目众多,而CPU资源较少,甚至有的只有1个,所以进程之间是具有竞争属性的,为了高效完成任务,更合理的竞争资源,便有了优先级。
- 独立性:多进程运行,需要独享各种资源,多进程运行期间互不打扰
- 并行:多个进程在多个CPU 下分别、同时进行运行,这成为并行
- 并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。