第七章 进程控制与进程间通信

进程控制

进程的基本概念

进程与程序

  • 进程,就是程序的一次执行
  • 进程是系统中的一个对象,它对应一个程序的执行流并且是一个资源分配的单位
  • 操作系统以进程为单位,管理这个执行流和它占用的内存等资源,并负责做到多个进程之间互不影响
  • 程序:是一个由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相等的进程是会晤组首进程
上一篇:Docker进入容器命令


下一篇:漏洞复现篇——命令执行漏洞