12.进程控制

codemagiciant / 2023-08-21 / 原文

12.进程控制

1.学习目标

  • 了解进程相关的概念

  • 掌握fork/getpid/getppid函数的使用

  • 熟练掌握ps/kill命令的使用

  • 熟练掌握execl/execlp函数的使用

  • 说出什么是孤儿进程什么是僵尸进程

  • 熟练掌握wait函数的使用

  • 熟练掌握waitpid函数的使用

2.进程相关概念

2.1 程序和进程

  • 程序,是指编译好的二进制文件,在磁盘上,占用磁盘空间,是一个静态的概念。

  • 进程,一个启动的程序, 进程占用的是系统资源,如:物理内存,CPU,终端等,是一个动态的概念

  • 程序 → 剧本(纸)

  • 进程 → 戏(舞台、演员、灯光、道具...)

同一个剧本可以在多个舞台同时上演。同样,同一个程序也可以加载为不同的进程(彼此之间互不影响)

2.2 并行和并发

  • 并发,在一个时间段内,是在同一个cpu上,同时运行多个程序。

如:若将CPU的1S的时间分成1000个时间片,每个进程执行完一个时间片必须无条件让出CPU的使用权,这样1S中就可以执行1000个进程。




  • 并行性指两个或两个以上的程序在同一时刻发生(需要有多颗)。


2.3 PCB-进程控制块

每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。

/usr/src/linux-headers-4.4.0-96/include/linux/sched.h文件的1390行处可以查看struct task_struct 结构体定义。其内部成员有很多,我们重点掌握以下部分即可:

  • 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。

  • 进程的状态,有就绪、运行、挂起、停止等状态。

  • 进程切换时需要保存和恢复的一些CPU寄存器。

  • 描述虚拟地址空间的信息。

  • 描述控制终端的信息。

  • 当前工作目录(Current Working Directory)。

  █getcwd --pwd

  • umask掩码。

  • 文件描述符表,包含很多指向file结构体的指针。

  • 和信号相关的信息。

  • 用户id和组id。

  • 会话(Session)和进程组。

  • 进程可以使用的资源上限(Resource Limit)。

  █ulimit -a

2.4 进程状态(面试考)

  • 进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段,常与就绪态结合来看。

3.创建进程

3.1 fork函数

  • 函数作用:创建子进程

  • 原型: pid_t fork(void);

函数参数:无

返回值:调用成功:父进程返回子进程的PID,子进程返回0;

调用失败:返回-1,设置errno值。

● fork函数代码片段实例

  • 调用fork函数的内核实现原理:

● fork函数总结

 ►fork函数的返回值?

   父进程返回子进程的PID,是一个大于0数;

   子进程返回0;

  特别需要注意的是:不是fork函数在一个进程中返回2个值,而是在父子进程各自返回一个值。

 ►子进程创建成功后,代码的执行位置?

​   父进程执行到什么位置,子进程就从哪里执行

 ►如何区分父子进程

  通过fork函数的返回值

 ►父子进程的执行顺序

  不一定,哪个进程先抢到CPU,哪个进程就先执行

3.2 ps命令和kill命令

  • ps aux | grep "xxx"

  • ps ajx | grep "xxx"

  ▶ -a:(all)当前系统所有用户的进程

  ▶-u:查看进程所有者及其他一些信息

  ▶-x:显示没有控制终端的进程 -- 不能与用户进行交互的进程【输入、输出】

  ▶-j: 列出与作业控制相关的信息

  • kill -l 查看系统有哪些信号

  • kill -9 pid 杀死某个线程

3.3 getpid/getppid

  • getpid - 得到当前进程的PID

pid_t getpid(void);

  • getppid - 得到当前进程的父进程的PID

pid_t getppid(void);

3.3 练习题

  • 编写程序,循环创建多个子进程,要求如下:

1.多个子进程是兄弟关系。

2.判断子进程是第几个子进程

画图讲解创建多个子进程遇到的问题

注意:若让多个子进程都是兄弟进程,必须不能让子进程再去创建新的子进程。

  • 编写程序,测试父子进程是否能够共享全局变量

重点通过这个案例讲解读时共享,写时复制