前言
一、冯诺依曼体系结构
二、操作系统(Operator System)
(一)任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。
- 内核(进程管理,内存管理,文件管理,驱动管理)
- 其他程序(例如函数库,shell程序等等)
- 操作系统的定位是:管理软硬件资源的软件
eg:用struct结构体描述被管理对象,用链表或其他高效的数据结构组织被管理对象
(二)系统调用和库函数
- 在开发角度,操作系统对外会表现为一个整体,但会暴露自身部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
- 系统调用在使用上,功能比较基础,对用户的要求相对较高,所以,开发者对部分系统调用进行适度封装,从而形成库,更有利于更上层用户或者开发者进行二次开发。
进程
程序只是一个静态的文本文件,而进程是程序运行起来的一个实体
客观概念:程序的一个执行实例,正在执行的程序;
内核观点:担当分配系统资源(CPU时间,内存)的实体。
一、描述进程 -PCB
- 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,称之为PCB(process control block),Linux操作系统下的PCB是:
task_struct
。 - task_struct -PCB(进程控制块)之一:
①在Linux中描述进程的结构体叫做task_struct。
②task_struct是Linux内核的一种数据结构,它被装载到RAM(内存)里并且包含着进程的信息。 - task_ struct内容分类:
①标示符[pid]:描述本进程的唯一标示符,用来区别其他进程。
②状态:就绪状态,阻塞状态,运行状态。
③优先级:相对于其他进程的优先级。
④程序计数器:保存程序中即将被执行的下一条指令的地址。
⑤内存指针:包括程序代码,进程相关数据的指针,以及其他进程共享的内存块的指针。
⑥上下文数据:保存进程执行时处理器的寄存器中的数据。
⑦I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
⑧记账信息:
a. CPU密集型程序:CPU计算的时间占多;
b. IO密集型程序:和磁盘交互,进行IO占多;
c. 并行:同一时间,多进程占用多CPU计算;
d. 并发:多进程占用少CPU计算,每个进程运算一段时间要让出CPU供其他进程运算;
e. 抢占式执行。 - 组织进程:可在内核源代码里查询。所有运行在系统里的进程都以task_struct链表的形式存在内核里。
二、通过系统调用创建进程-fork初识
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() { //fork :
int ret = fork(); //1)在父进程中,fork返回新创建子进程的进程ID;
if (ret < 0) { //2)在子进程中,fork返回0;
perror("fork"); //3)如果出现错误,fork返回一个负值。
return 1;
}
else if (ret == 0) { //child
printf("I am child: %d, ret: %d\n", getpid(), ret);
}
else { //father
printf("I am father: %d, ret: %d\n", getpid(), ret);
}
return 0;
}
三、查看进程状态
ps -l 列出与本次登录有关的进程信息;
ps -aux 查询内存中进程信息;
ps aux | grep (进程名) 查询(进程名)进程的详细信息;
top 查看内存中进程的动态信息;
kill -9 pid 杀死标识符为pid的进程。
- R运行状态:并非进程一定在运行中,表明进程在运行中或是在运行队列。
① ./[可执行程序]& 将进程变为后台进程;
②fg 将进程变为前台进程。 - S睡眠状态(可中断睡眠):意味着进程在等待事件完成。
- D磁盘休眠状态(不可中断睡眠):此时进程通常会等待IO的结束。
- T停止状态:可以通过发送 SIGSTOP 信号给进程来停止(T)进程,让进程继续运行。
- X死亡状态:只是一个返回状态,任务列表没有这个状态。
- t 跟踪状态:调试的时候产生。
四、僵尸进程
- Z僵死状态:当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程,子进程以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。维护退出状态也属于进程基本信息,因为数据结构对象本身就要占用内存,所以保存在task_struct -PCB中,就会造成内存资源浪费。
- 如何处理僵尸进程?
①将僵尸进程的父进程杀掉,那僵尸进程就会变为孤儿进程,也就是会被1号进程将进程的返回状态回收掉,同时释放掉当前孤儿进程的PCB。
五、孤儿进程
父进程如果提前退出,子进程就称为孤儿进程,孤儿进程被1(Init)号进程领养,也就是会被1(Init)号进程将进程的返回状态回收掉。Init进程本身会创建很多进程,所以其本身创建的进程不能称为孤儿进程。
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork(); //创建子进程;系统调用函数fork(代码共享,数据独有)
if(pid < 0) {
perror("fork erro"); //创建PCB是需要耗费内存的,没有内存的时候,可能会导致此结果
return 0;
}
else if(pid == 0)
printf("i am child:[%d]-[%d]\n", getpid(), getppid()); //子进程
else
printf("i am father:[%d]-[%d]\n", getpid(), getppid()); //父进程
//获取当前进程的pid,我们要使用getpid
//获取当前进程的父进程的pid, 我们需要使用getppid
return 0;
}