什么是进程?进程的概念是什么?
对于操作系统来说:
进程是正在运行的程序
进程是可以分配处理器并由处理器执行的实体
而对于Linux内核来说:
进程是可担当分配系统资源的实体
如何描述一个进程
这里我们要介绍一下PCB了
PCB,全称为 进程控制块
PCB是用来标识一个进程的,它包含了该进程的各个信息
在Linux内核下,linux下的PCB是task_struct这个结构体
task_struct里面有哪些内容呢?
主要有以下几个:
进程的控制符
所谓的进程控制符,全称为Process Identifier,就是标识进程唯一的身份标识,所以也成为进程标识符
进程控制符有pid和ppid
pid表示进程的id
ppid表示父进程的id
每个进程都有非负的整数来表示唯一的进程ID,当一个进程终止后,其进程的ID就又可以被其他进程进行使用
每个进程除此之外还有其他的标识符
下列函数可以返回这些标识符
Linux下,C语言文件main.c是如何一步步成为进程的
Linux下的C语言成为可执行程序需要经历过四个步骤
分别是,预处理---编译---汇编---链接
(1)预处理要做的事情 --- 生成main.i 文件
- 1 、宏替换
- 2 、#include包含文件的展开
- 3 、去掉注释
- 4 、添加行号
- 5 、进行条件编译
(2)编译需要做的事情 --- 生成main.s文件
检查语法错误
(3)汇编需要做的事情 --- 生成main.o 文件
转化成二进制的机器码
(4)链接需要做的事情 --- 生成main.exe文件(按照Windows下可理解为.exe)
符号表的合并
从符号表中找到函数地址
程序转化为进程的过程
(1)内核将程序装入内存,为程序分配内存空间
(2)内核为该进程赋予PID以及各种信息,将进程放入运行队列中等待执行
什么是进程的内存映像
进程的内存映像是指内核在内存中如何存放可执行程序
布局如下:
进程的状态
进程具有七种状态
分别是RTSDZX和t
进程的优先级
进程的cpu资源的分配就是进程的优先级
如何查看进程的优先级?
首先呢,需要介绍如何查看系统进程
用指令
ps -l
之后,屏幕会输出以下几个内容
UID 表示当前的用户身份情况(现在我的UID是500,切换到root下,UID为0)
PID 表示该进程的进程号
PPID 表示进程的父进程号
PRI 表示进程的优先级
NI 表示nice值,通俗的说,就是我们可以通过设置NI值来改变优先级PRI,当然,不是想改多少就改多少的
如何修改nice值?
如何创建一个进程
fork函数
头文件 #include<unistd.h>
pid_t fork(void);
作用:一个现有的进程调用fork函数可以创建一个子进程
返回值:子进程返回0,父进程返回进程的ID,出错会返回-1
说明:子进程是父进程的副本
注意:父进程不共享存储空间的部分,但是共享正文段
这里用到了写实拷贝,当父进程或者子进程进行修改的时候,内核只为要修改的区域的地方的内存制作一个副本
父进程和子进程的一些区别
1、fork()的返回值的不同,子进程返回0;父进程返回子进程的ID2、进程的ID不同,其各自的父进程的ID不同
3、子进程的tms_utime,tms_stime,tms_cutime和tms_ustime均被设置为0
4、父进程的文件锁,不会被子进程继承
5、子进程的未处理闹钟会被清理
6、子进程的未处理信号集被设置为空值
什么是孤儿进程
所谓孤儿进程,就是在父进程创建子进程后,父进程先结束(进入X死亡状态)后,其创建的子进程便成了孤儿进程
我们都知道,当一个进程死亡时,其父进程会调用wait()或者waitpid()系统调用来处理子进程的信息
然而,孤儿进程由于其父进程率先死亡,因此必须要人领养
这个领养人是谁呢?
是1号进程,也就是init进程
孤儿进程的验证
测试代码
#include<stdio.h>
#include<sys/types.h>
int main()
{
//利用fork()创建一个子进程
pid_t id = fork();
//根据返回值判断是子进程还是父进程
if(id == 0)//child
{
//令进程一直执行,直到手动杀死
while(1)
{
sleep(1);
printf("I'm child ... ");
printf("child pid : %d , father : %d \n",getpid(),getppid());
}
}
else//father
{
//运行过程中,手动杀死父进程
while(1)
{
printf("I'm father!!!");
printf("father pid : %d , grandfather : %d \n",getpid(),getppid());
sleep(1);
}
}
return 0;
}
令该程序跑起来
杀死父进程2260
观察子进程的信息变化
进程等待
wait()和waitpid()函数
函数作用:父进程用来获取已终止进程的退出状态,并彻底清除该进程
wait函数调用后的情况
1、若该进程的所有子进程都在运行,则wait阻塞
2、若该进程的一个进程结束了,则获取该结束进程的死亡信息,返回
3、若该进程没有子进程,则出错返回
什么是僵尸进程
僵尸进程指的是,在父进程没有死亡的时候,子进程死亡了,但是父进程还没处理子进程的死亡信息
此刻,子进程就是僵尸进程
僵尸进程的验证
测试代码
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
//创建子进程
pid_t id = fork();
if(id == 0)//child
{
printf("child ... %d father ... %d\n",getpid(),getppid());
exit(0);//子进程退出,成为僵尸进程
sleep(20);//等待20秒,等待结束后从僵尸进程被真正灭亡
}
else//father
{
while(1)
{
printf("father ... %d gfather ... %d\n",getpid(),getppid());
sleep(1);
}
}
return 0;
}
查看子进程和父进程的PID
查看子进程的状态