进程控制
进程的基本概念
进程与程序
- 进程,就是程序的一次执行
- 进程是系统中的一个对象,它对应一个程序的执行流并且是一个资源分配的单位
- 操作系统以进程为单位,管理这个执行流和它占用的内存等资源,并负责做到多个进程之间互不影响
- 程序:是一个由CPU指令和数据结构构成的集合,这些指令和数据存放在磁盘的一个普通文件中
- 常见的可执行文件和目标文件的格式有
EIF格式
和COFF格式
-
EIF
:可执行和链接格式 -
COFF
:普通目标文件格式 - 程序文件不允许删除,也不允许改动
- 几个同时允许的进程可以由同一程序初始化得到,然而这些进程之间并没有什么联系
进程的组成部分
-
进程是操作系统管理系统活动的基本单位
-
包括四部分:
指令段,用户数据段,用户堆栈段,系统数据段
-
指令段:
1,正文段,存放程序的CPU指令代码
2,大小固定不变 -
用户数据段: 存放程序运行所需要的数据
-
用户堆栈段: 用户程序执行所需要的堆栈空间,用于实现函数的嵌套调用
-
系统数据段:操作系统内的数据
1,每个进程对应一套数据,包括页表和进程控制块(PCB) -
UNIX是分是系统
-
未初始化的数据指未赋初值的全局或静态变量
-
UNIX的命令
size
可以列出程序文件或者编译产生的目标文件中相应段的大小 -
size filename-list
进程的状态
- 运行状态和阻塞状态(睡眠状态)
- 区别:系统总是按照优先级在分时处理运行状态的进程,而不顾那些处于阻塞状态的进程
进程状态的转换
time:进程执行的时间
-
时间包括:实际时间,系统时间和用户时间
-
vmstat:打印出整个系统,包括所有进程,近期内占用CPU的情况
忙等待
- 一个忙等到的程序是不可取的
-
sleep(sec)
: 将当前进程设置为睡眠状态,睡眠一段时间,然后醒来 ——》定时轮询
fork:创建新进程
- fork系统调用时创建新进程的
唯一方式
- fork调用唯一能出错的原因时系统中的
资源耗尽
- 新的进程叫做
子进程
,原先的进程叫做父进程
- 继承:子进程的指令段,数据段,用户堆栈段,统统是父进程一摸一样的复制,系统数据段几乎是
- 返回值用于区分父进程和子进程:例如:
int p;
p = fork();
- 这句语句可以分解为两个动作:
1,执行fork( )系统调用
2,给变量p赋值 - 在对p赋值时,父进程的p得到一个正整数(子进程的PD号),而子进程的p得到0
exec:重新初始化进程
- exec系统调用,从一个指定的程序文件重新初始化一个进程
- exec系统调用就是在就进程中运行新进程(用现在的壳执行一个指令的程序)
- exec系统调用有6种调用格式,区别在于如何从exec的参数中提供用户堆栈段的初始化状态,包括命令行参数和环境参数
wait:等待子进程允许结束
- 子进程中止后,会产生“僵尸“进程
- "僵尸"进程是进程生命期结束时的一种特殊状态,系统已经释放了进程占用的包括内存在内的系统资源,但是,仍然在内核中保留进程的部分数据结构,记录进程的终止状态,等待父进程来**“收尸”**
- 系统调用
wait
就是等待当前进程的任一个子进程终止,获取子进程终止的状态 - wait系统调用的最重要的功能是销毁子进程的僵尸,得到子进程终止状态并回收僵尸子进程占用的系统资源
- 如果执行
wait
时,还没有子进程终止,则父进程进入睡眠状态等待,直到有一个子进程终止 - 如果执行
wait
时,已经有子进程终止,则wait会立刻返回 - wait的函数原型:
#include<sys/wait.h>
pid = wait(int *status);
- 函数的返回值时已终止的子进程的PID号,status中会返回子进程终止的原因
- 子进程终止有两种情况:
1,进程自愿终止(自杀):WIFEXITED(status)
2,异常终止(被杀):WIFSIGNALED(status)
xsh0.c:最简单的shell
vfork 和 _exit
-
vfork
的基本做法是子进程临时借用父进程的数据段,指令段和用户堆栈段 - 父子进程使用相同的逻辑地址空间
-
vork
创建了子进程后,父进程睡眠等待,不再运行,一直等待子进程执行了exec
系统调用或者子进程终止之后,父进程才开始执行,以保证父子进程不会同时访问到同一个数据段或堆栈段 - 如果子进程一定要等待父进程完成某个操作后才进行exec或终止子进程,那么就会产生
死锁
- vfork后子进程不允许从调用vfork的函数返回,子程序的流程选择必须是下列两者之一:
1,必须通过_exit
终止子进程
2,通过exec
将程序流程转到新的程序
system:在程序中运行一个命令
- system可以用一个字符串串第一个shell的命令,然后执行
- 函数原型:
int system(char *string)
- 库函数system( )就是利用
fork( ), exec( ), wait( )
实现的
ps:列出进程的状态
-
ps
(process status)命令打印出系统中进程的当前状态,实际上就是将进程系统数据段中的部分进程属性有选择的打印出来
信号
信号的产生及信号类型
- 信号时送到进程的"软件中断",它通知进程在他们的环境中出现了非正常事件
- 每个信号都是一个正整数
按键产生信号
- 当用户按下某个终端键时会产生信号
1,SIGINT信号
:中断键Ctrl+C
键默认情况下会中止当前的进程
2,SIGOUT信号
:退出键Ctrl+\
,默认情况下会导致当前进程中止,但会额外生成一个记录进程的内存存储图像的core
文件,以使得调试程序可以使用core
文件检查进程在终止时的状态
3,SIGTSTP信号
:挂起键Ctrl+Z
,默认处理时暂停当前进程的执行,挂起当前进程
硬件异常产生信号
-
SIGSEGV信号
:段违例信号 -
SIGFPE信号
:浮点异常,0做除数或者浮点溢出时 -
SIGBUS信号
:总线错 -
SIGLL信号
:非法指令
事件产生的信号
-
SIGALRM信号
:闹钟信号 -
SIGPIPR信号
:向管道的写操作 -
SIGTTIN信号
:当前控制终端上的后台进程试图读终端,会导致终端向其发送~,进程终止 -
SIGHUP信号
:挂断信号,进程终止 -
SIGCLD信号
:子进程终止的时候,会产生僵尸进程,内核向父进程发送~,wait()
其他进程发送来的信号
-
kill
命令 -
SIGTERM信号
:用户直接使用kill命令,不附带任何选项,会给进程送达一个~, - 中止一个进程的方法
kill:发送信号
- 功能:将一个信号送达一个进程或者进程组内的所有进程
kill命令
- 用法:
kill -signal PID-list
会晤组和进程组
-
进程组号(PGID
):创建子进程的时候从父进程那里继承来的,PGID相同的所有进程构成一个进程组 - PGID和PID相等的进程时进程组的组长,组长进程终止后,进程组照样可以存在
- 一个会晤组有一个或多个进程组构成
-
会晤组号(SID)
:进程的SID也是创建子进程的时候从父进程那里继承来的,SID相同的所有进程构成一个会晤组 - PID和SID相等的进程是会晤组首进程