一.冯・诺依曼体系

输入设备:键盘,网卡这些
CPU=运算器+控制器
存储器:内存
这个体系结构的效率:由设备的"拷贝"效率决定
1.理解数据的流动:
就是两个冯・诺依曼体系的交流
二.操作系统
一个基本的程序集合,称为操作系统(OS)
操作系统是一款进行软硬件管理的软件
操作系统主要包括:
1.内核(进程管理,内存管理,文件管理)
2.其他程序(例如函数库,shell程序等等)
操作系统对上:为用户(应用程序)提供一个良好的执行环境
操作系统对下:与硬件交互,管理所有的软硬件资源(不是目的,是手段)
理解操作系统:
在这个计算机软硬件的架构中,操作系统的定位是:一款"搞管理"的软件
如何理解"管理"?这里打个比方:
校长(管理者)->操作系统
辅导员(执行)->驱动程序
学生(被管理者)->硬件
管理者要管被管理者可以不用见面,是通过"数据"来进行管理,那我们的"数据"就是从我们的执行来获取.校长手中的数据可以是一个Excl表格(链表)(里面有所有学生的基本信息)而且数量大,所以通过辅导员来进行对该表格(数据)的管理
先描述再组织是操作系统资源管理、进程管理、文件管理、设备管理的底层核心设计思想。
三.理解系统调用
操作系统就像一个银行:向上对用户提供对应的服务,但是又不相信任何用户或者人,我们需要设置系统信息都是通过系统调用来实现.
系统调用:各种接口
库函数和系统调用是上下层的关系
四.进程
先描述,再组织.
进程=内核数据对象(PCB)(Process Control Block)+自己的代码和数据!
我们称那些task_struct为进程控制块,进程的所有属性都可以直接或者间接通过task_struct找到
1.task_struct
标识符:描述本进程的唯一标识符,用来区分其他进程.
状态:任务状态,退出状态,退出信号等,
优先级:相对于其他进程的优先级
程序计数器:程序被执行的下一条指令的地址
内存指针:包括程序代码和进程相关数据的指针,还有其他进程共享的内存块的指针(就像你面简历里的电话)
我们历史上执行的所有指令,工具,自己的程序,运行起来,全部都是进程.
2.getpid(process ID)
获取当前进程的 PID
我们man查看手册可以看到getpid的相关信息.pid_t就是一个整数,成功嫉妒pid,失败就是0

找到相应的pid就可以说明她是一个进程
3.ps = process status
可以查到所有进程
ps -aux
//查看所有进程
那我们想要查看自己刚启动的进程
cpp
ps -axj | grep myprocess
//使用grep过滤信息,找到自己想要的进程

但是上面这个信息乱七八糟的,不知道是什么所以我们需要对应的属性说明
cpp
ps -axj | head -1;ps -axj | grep myprocess
//查看第一行的信息
//这里是查到了grep自己的进程

3.kill -9 +PID
就是我们平常使用的ctrl+c
通过kill就可以杀死进程
4.ls /proc/pid
可以查到对应进程的全部信息,在没有杀死进程的前提下.
cwd查看当前进程的绝对路径,每个进程的 PCB 里,都保存着
5.chdir = change directory
改变当前工作目录,会改变cwd所对应的路径
五:研究进程的父子关系
子进程都是父进程创建的


用代码创建子进程:
我们使用man命令去查找fork

子进程没有自己的代码和数据,默认共享父进程的,因为目前没有程序新加载
进程具有独立性
父子任何一方进行修改数据,OS把修改的数据在底层拷贝一份,让目标进程修改这个拷贝(写实拷贝 ),就可以保证独立性
六.进程状态
进程状态就是task_struct内的一个整数
1.运行&&阻塞&&挂起
运行:进程在调度队列中们进程的状态都是running
阻塞:等待某种设备或者资源就绪,就像一个进程需要scanf输入我们就会将它从runqueue放到waitqueue
挂起:操作系统在内存吃紧的时候,在磁盘上的swap交换分区进行换入换出操作,用磁盘扩容虚拟内存,保证系统不崩溃(阻塞挂起),当内存压力极高时,系统会选择暂时挂起部分正在运行的进程,使其转为就绪挂起状态,暂停占用物理内存,缓解内存资源紧张;
2.理解内核链表
我们的双向链表的next指针是直接指向整个节点,但是linux内核是指向节点结构体里面的一个封装的结构体成员对象(里面有next和prev)
怎么访问其他成员对象呢,即外部结构体对象?

使用offset,作用:计算某个成员在结构体中的字节偏移
cpp
offsetof(struct my_data, node);
找到外部结构体
cpp
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - offsetof(type, member))
3.linux的进程状态
cpp
// include/linux/sched.h
#define TASK_RUNNING 0 // 运行/就绪
#define TASK_INTERRUPTIBLE 1 // 可中断睡眠
#define TASK_UNINTERRUPTIBLE 2 // 不可中断睡眠
#define __TASK_STOPPED 4 // 暂停
#define __TASK_TRACED 8 // 被追踪(调试)
#define EXIT_ZOMBIE 16 // 僵尸进程
#define EXIT_DEAD 32 // 死亡进程

s是浅度睡眠,是可以被杀死的
d是深度睡眠,是不能被杀死的
僵尸进程:
子进程运行结束后,退出码、运行状态 必须保留,要交给父进程查看。
子进程都是由父进程创建的, 创建子进程的目的是为了子进程完成某种事情.完成的结果的相关信息还需要返回给父进程.进程退出的时候是有相应的信息的,信息存在进程的 PCB(进程控制块)
如果父进程一直不管,不回收,不获取子进程的提出信息,那么Z会一直存在,就会造成内存泄漏
如果进程直接退出了,内存泄漏问题是不存在的,常驻在内存的进程是比较怕内存泄漏的.
子进程代码早就跑完、退出了(没了) 但是父进程还活着,一直不调用 wait 收尸 → 子进程就变成 僵尸进程 Z
孤儿进程:
父子进程关系中,如果父进程先退出,子进程要被1号进程领养,这个被领养的进程(子进程),叫做孤儿进程,被领养只之后就会变成后台进程,ctrl+c就不能杀死了
为什么子进程会被领养?没有被领养就没有父进程
我们子进程没有父进程再子进程结束的时候没有人调用wait()来回收PCB,清理退出状态,系统就会产生大量的僵尸进程,占满PID系统就会卡死.