进程
课本概念:程序的一个执行实例,正在执行的程序等
内核观点:担当分配系统资源(cpu时间,内存)的实体
描述进程—PCB
进程信息被放在一个叫做进程控制块的数据结果中,可以理解为进程属性的集合。
Linux操作系统下的PCB的进程的数据结构是:task_struct,task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。
task_strcut内容分类
标识符:描述本进程的唯一标识符,用来区别其他进程
状态:任务状态,退出代码,退出信号等
优先级:相对于其他进程的优先级
程序计数器:程序中即将被执行的下一条指令的地址
内存指针:包括程序代码和进程相关数据的指针,还要和其他进程共享的内存快指针
上下文数据:进程执行时处理器的寄存器中的数据.
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息
查看进程
Linux下 通过ps命令观察进程,ps相当于任务管理器,能够查看系统上有哪些进程,敲下的命令,在命令过程中,也是一个进程。
ps aux | less查看进程信息更全面点
通过系统调用获取进程标示符
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("pid:%d\n",getpid());
printf("ppid:%d\n",getppid());
return 0;
}
通过系统调用创建进程fork
fork有两个返回值,父子进程代码共享,数据各开辟空间,私有一份(写时拷贝)
为0是执行子进程的代码,为>0执行父进程的代码。
父进程值返回子进程的pid,子进程返回值为0!!
通常让父子进程执行不同的逻辑。
执行过程:父子进程都是紧接着fork继续执行
先后顺序:不确定,取决于操作系统的调度。
2 #include<unistd.h>
3 int main()
4 {
5
6 // printf("pid:%d\n",getpid());
7 // printf("ppid:%d\n",getppid());
8 int ret=fork();
9 if(ret<0)
10 {
11 perror("fork");
12 return 1;
13 }
14 else if(ret==0)
15 {
16 //child
17 printf("I am child :%d,ret:%d\n",getpid(),ret);
18 }
19 else{
20 //father
21 printf("I am father:%d,ret:%d\n",getpid(),ret);
22 }
23 sleep(1);
24 //while(1);
25 return 0;
26 }
使用ctrl+z回到命令行界面(程序还在运行),fg命令返回程序运行界面,ctrl+c结束程序。
进程状态
R运行状态:并不是意味着进程一定在运行中,它表明进程要么是在运行中要么是在运行队列里。
S睡眠状态:意味着进程在等待事件完成(这里的睡眠有时候也叫做中断睡眠)
D磁盘休眠状态:有时候也叫不可中断睡眠状态,在这个状态的进程通常会等待IO的结束
T停止状态:可以通过发送SIGSTOP信号给进程来停止T进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行。
X死亡状态:这个状态只是一个返回状态,你不会在任务列表里看到这个状态
zombie—僵尸进程
僵尸状态是一个比较特殊的状态。当子进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。
僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
所以只有子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进程z状态。
一个30s僵尸进程的程序
1 #include<iostream>
2 #include<unistd.h>
3 #include<cstdio>
4 using namespace std;
5 int main()
6 {
7 pid_t id=fork();
8 if(id<0)
9 {
10 perror("fork()");
11 }else if (id>0)
12 {
13 //parent
14 printf("parent[%d] is sleeping ...\n",getpid());
15 sleep(30);
16 }
17 else {
18 //child
19 printf("child[%d] is begin Z...\n",getpid());
20 //sleep(5);
21 //exit(EXIT_SUCCESS);
22 }
23 return 0;
24 }
僵尸进程的危害
- 父进程如果一种不读取,那子进程一直处于Z状态
- z状态一种不退出,pcb一直都要维护(维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(pcb))
- 父进程创建了很多子进程,就是不会收,会造成资源的浪费
- 内存泄漏(主要)
处理办法
kill掉父进程,此时子进程变成孤儿进程,被1号进程所领养,1号进程进行回收。
孤儿进程
父进程提前退出,子进程就称之为“孤儿进程”。