嵌入式Linux------进程与线程(1 多进程基础)
进程与线程
首先,先有一个宏观认识
- 进程—是操作系统分配资源的最小单位,操作系统会对每个进程分配内存资源
- 线程—是操作系统调度的最小单位,操作系统不会给线程分配资源
进程产生
有之前的编译过程我们知道程序是需要经历 预处理–>编译–>汇编–>链接 才生成可执行文件
而进程是生成的可执行文件被调度到内存中去,才会由程序变成进程.
简单理解进程是动态的,而程序是静态的.
进程的状态转换

程序被调度到内存则变成进程进入就绪态,等待获取CPU资源,开始执行;
一旦就绪态的进程获取CPU资源则就会变成执行态的进程;
当CPU给执行态的进程分配的时间片用完, 则进程就会主动释放CPU资源,再次进入就绪队列等待CPU资源;
当执行态的进程被阻塞(如IO等待…等), 则CPU会阻塞进程,进程进入阻塞状态,等待阻塞的事件完成,再次返回就绪队列;
当执行态进程被休眠(sleep()),则CPU会使进程进入休眠队列并释放CPU资源,等待休眠完成,再次返回就绪队列;
当执行态的进程执行完毕 / 被杀死 ,则释放CPU资源,进入僵尸态,此时仅仅释放了CPU资源,其他资源并未回收;
当僵尸态的进程系统资源被完全回收,汇报死亡信息后,则会进入死亡态,此时执行完毕(根据不同的内存调度算法将其他程序调入内存进行覆盖).
多进程
先引入父进程与子进程的概念
父进程通过fork()得到一个子进程
父进程与子进程在初始状态时 整个内存空间, 打开的文件, 工作路径, 进程组, 环境变量, UID和GID都是相同的
进程PID 记录锁 挂起信号不一样
看一下linux的进程树
pstree #查看进程树

如图,在linux中所有的进程都来自于systemd这个系统进程
所以,运行状态便可以进一步优化
僵尸进程与孤儿进程
僵尸进程:子进程死亡但是父进程并没有回收子进程资源,子进程就会变成僵尸进程
孤儿进程: 父进程死亡但是子进程并未死亡,则此时子进程会交由systemd管理
来个例子
//僵尸进程
#include <stdio.h>
#include <unistd.h>
// 僵尸进程:子进程死亡但是父进程并没有回收子进程资源, 子进程就会变成僵尸进程
int main () {
pid_t pid = fork (); //创建一个子进程
if (pid == 0) {
//子进程
printf ("我是子进程\n");
sleep (10); //10s后死亡
return 0;
}
if (pid > 0) {
while (1) {
printf ("我是父进程\n");
sleep (10);
}
}
}
可以看到当子程序未死亡时,有两个进程,而子程序死亡后其进程变为defunct
在进程树中其也一直为子进程
:~$ ps -e|grep a.out
85415 pts/1 00:00:00 a.out
85416 pts/1 00:00:00 a.out
:~$ ps -e|grep a.out
85415 pts/1 00:00:00 a.out
85416 pts/1 00:00:00 a.out <defunct>
:~$ pstree
systemcd│sh├─bash───a.out───a.out
再来个例子
//孤儿进程
#include <stdio.h>
#include <unistd.h>
// 孤儿进程: 父进程死亡但是子进程并未死亡,则此时子进程会交由systemd管理
int main () {
pid_t pid = fork (); //创建一个子进程
if (pid == 0) {
//子进程
while (1) {
printf ("我是子进程\n");
sleep (10);
}
}
if (pid > 0) {
printf ("我是父进程\n");
sleep (10);
return 0;
}
}
输出
:~$ ./a.out
我是父进程
我是子进程
我是子进程
:~$ 我是子进程 #这里父进程已经退出但是子进程并没有结束所以
我是子进程
进程树
:~$ pstree |grep a.out
systemcd| sh |-bash---a.out---a.out
:~$ pstree |grep a.out
systemcd| |-a.out
再父进程没有结束时子进程属于父进程,父进程终止后子进程变成孤儿进程被systemcd管理
孤儿进程并非一定是需要避免的 我们可以利用这一个特性,在一些需要让操作系统进行管理,在后台默默执行的东西,比如挖矿(不可取,进橘子) ,比如ssh,mysql的服务.
如何避免尸进程与孤儿进程
wait 回收进程资源防止僵尸和孤儿进程的产生!
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork (); //创建一个子进程
if (pid == 0) {
//子进程
int i = 0;
while (i < 2) {
printf ("我是子进程\n");
sleep (10);
i++;
}
}
if (pid > 0) {
printf ("我是父进程\n");
int status;
wait (&status); //等待回收进程
printf ("进程回收完毕\n");
return 0;
}
}
:~$ ./a.out
我是父进程
我是子进程
我是子进程
进程回收完毕
更多推荐
所有评论(0)