目录
/proc文件
基本概念:是 Unix/Linux 系统中的一个特殊的虚拟文件系统,它用于提供系统的内核、进程和其他运行时信息。/proc
文件系统本质上是一个接口,通过它用户和程序可以与操作系统内核交互,查看内核和进程的实时状态,甚至可以通过某些文件来动态修改系统配置
特点:是内存中的虚拟文件系统,并不占用磁盘空间
进程信息:
/proc
下的每一个数字目录代表一个进程的 PID(进程ID)。每个进程的相关信息都存储在其对应的/proc/<PID>
目录中。这个目录包含了该进程的详细状态信息,如内存使用、文件描述符、命令行参数等。
/proc/<PID>/cmdline
:显示进程的启动命令/proc/<PID>/status
:显示进程的状态,包括内存、用户、权限等/proc/<PID>/fd/
:显示进程打开的文件描述符系统信息:
/proc/cpuinfo
:显示 CPU 的详细信息,例如型号、频率、核心数等/proc/meminfo
:显示系统的内存使用情况/proc/loadavg
:显示系统的负载情况/proc/uptime
:显示系统启动以来的运行时间/proc/version
:显示操作系统内核版本信息内核参数和系统配置:
/proc/sys/
:这个目录包含了许多与系统配置相关的文件,用户可以通过这些文件修改系统的行为。例如,通过修改/proc/sys/net/ipv4/ip_forward
来开启或关闭 IP 转发/proc/sys/kernel/hostname
:显示或设置主机名
补充:/proc
是系统管理员、开发者在调试系统、监控性能时的一个重要工具。它为我们提供了实时的系统和进程信息,并且可以通过调整某些参数,动态地修改内核的行为
常见使用方式:
1、cd /proc,在文件中查看内存中的进程信息
- ls /proc/进程PID -d,显示指定目录信息
- ls /proc/进程PID -l,显示目录详细信息
问题:什么是当前工作路径?
答: 即进程的当前工作路径(每个进程在启动时,会记录自己是在哪个路径下启动的,这就是进程的当前路径)
问题:在当前工作路径下创建一个文件时,fopen只提供了一个文件名,系统是怎么知道当前路径是哪呢?
答:创建文件 == 启动创建文件的进程,该进程会记录下自己在哪个路径下启动的,在进程执行时,会告诉系统当前的工作路径是cwd/文件名,cwd会被之前记录的路径所填充(cwd指令用于显示当前的工作路径)
chdir函数:改变进程记录的当前工作路径
进程状态
基本概念:进程状态就是进程task_struct(linux中的PCB叫做task_struct)中的一个属性(以下内容只是为了方便理解,跟实际有区别)
linux内中对进程状态定义的源代码
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
-
R:运行状态,并不意味进程一定在运行中,而是表示进程要么在运行中要么在队列中
-
S:可中断(ctrl + c)睡眠状态,进程在等待"资源"就绪(CPU执行进程的速度极快,显示设备读取速度慢,执行好的内容就会等待输入到显示设备上)
-
T/t:停止状态,可以通过发送SIGSTOP / SIGCONT 信号让T进程停止 / 运行(t是被追踪时停止,比如调试时的打断点操作,T是纯粹的暂停状态)
- 断点的英文名称是breakpoint,所以b 10表示在第十行打断点
查看所有进程信号的指令:kill -l
向PID为25115的进程发送信号:9、19、18分别,代表杀死进程、暂停进程、继续继续进程
长时间的T状态会令进程变为S状态
-
D:磁盘(不可中断)休眠状态:该状态下进程通常会等待IO结束(Liunx特有的进程状态)
- 没有D状态时:运当行向磁盘中存入数据的进程时,若存入的数据过大,则该进程处于等待状态(等待磁盘返回存储成功的信息),此时又有很多新的进程占用了内存空间,内存空间严重不足,为了防止操作系统本身崩溃,操作系统就会寻找可以杀掉进程,然后就发现了该等待磁盘的返回信息的进程,发现它已经等了有一会儿了还在等,决定将该进程杀掉,此时磁盘返回操作的结果,如果成功存入还好,如果没有成功存入,磁盘试图将未成功存入的信息告诉进程时,会发现该进程已经被杀掉了,于是磁盘可能就会丢掉这些数据
- 有D状态时:为了防止操作系统无差别的杀进程,而向磁盘中写入关键数据的进程是不能被杀掉的,所以规定当一个进程在等待IO时(输入/出设备读写数据)要将该进程设置为D状态,操作系统不能杀掉D状态的进程
- D状态的进程恢复的方法:进程自己醒来,重启、断电
-
X:死亡状态,是一个返回状态,不会在任务列表里看到该状态
僵尸进程-Z
基本概念:指已经运行完毕的进程,但该进程需要维持自己的退出信息,即在自己的task_struct中记录自己的退出信息,便于之后父进程的读取,如果父进程没有对子进程的退出信息进行读取(父进程读取tack_struct中的数据,该进程的删除仍由操作系统完成),则该僵尸进程一直存在,僵尸进程中的task_struct不会被释放(task_struct也占据了内存),因而造成内存泄漏问题
注意事项:僵尸进程是一个已经死掉的进程,无法用kill指令杀死一个已经死掉的进程
僵尸进程的危害:
资源浪费:每个僵死(zombie)状态的子进程会占据一个唯一标识符(PID),过多的僵死子程序将消耗可用 PID 的数量
内存泄漏:虽然已经停止运行,但仍然保留着一部分内存空间
性能问题:大量存在时会影响整体系统性能,并且在极端情况下可能导致系统崩溃
避免方式:
正确处理信号:父级应该注册
SIGCHLD
信号处理函数,在该函数中调用wait()
或类似函数以回收子级退出时产生的僵尸进程
孤儿进程
基本概念:父进程提前退出,子进程就会变成孤儿进程,孤儿进程一般都会被1号进程(OS本身)进行“领养”,孤儿进程被操作系统“领养”后,子进程就可以被正常回收了
进程的阻塞、挂起和运行
运行态-R
以下内容都是基于Linux操作系统的内容,一些状态可能会与书本上描述的不一致
注意事项:
1、一个CPU对应一个运行队列
2、运行队列中存放的是多个进程(task_struct + 代码和数据)组成的链表,及相关指针
3、CPU调度一个进程时,默认情况下会将运行队列中的首个进程"结点"放入CPU中,此时该进程的代码和数据就会被CPU获取,然后CPU就会执行该进程,此时该进程的状态为运行状态R,
4、在linux中,当一个进程位于运行队列时,它的状态已经是R了,而当一个进程创建后未被放入运行队列时它的状态为就绪状态
5、一个进程进入CPU执行时,该进程并不会在运行完后才能出CPU,CPU会基于进程task_struct中的时间片信息对运行队列中的进程进行“轮转调度”
6、当一个进程被分配的时间片结束后,该进程会下CPU,并被放到运行队列的队尾,然后令链表队头的进程上CPU执行,该进程执行完后也被放入队尾......(本算法不是Linux中的调度算法,是操作系统教材中调度算法的一种)
7、让多个进程以切换的方式进行调度,在一个时间段内同时得以推进代码的方法就叫并发
8、任何时刻,都同时有多个进程在多个CPU上执行,就叫并行(并行的前提要求是多核,而并发不要求多核)
阻塞态-S/D
注意事项:
1、操作系统是软硬件资源的管理者,对于软硬件的管理方式都是先描述后组织
2、每一个硬件在操作系统中都有其对应的结构体,多个硬件设备的结构体构成链表,至此操作系统对设备的管理变为了对链表的增删改查
3、CPU有运行队列,各种硬件设备有等待队列
4、当上述进程被执行时会先现在运行队列中,等运行到scanf()后就会从运行队列中剥离,并进入指定硬件设备的等待队列中(如果还有其他进程要访问该硬件设备,则也会进入该硬件设备的等待队列中)
5、处于某个设备硬件设备的等待队列中的进程不会再被调度,该进程处于阻塞态
6、当键盘输入数据时,操作系统会捕获这一行为,并将键盘struct device中的status变为ok状态(大概是内个意思)此时处于等待队列的进程就会被放入运行队列(唤醒),当该进程再次被调度时,会继续执行scanf的后续代码,当遇到需要scanf输入的数据内容时,操作系统会为进程提供该数据
7、阻塞和运行的状态变化,往往伴随着PCB被链入不同的队列中
8、入队列的不是进程的代码和数据,而是进程的task_struct
挂起态
注意事项:
1、当操作系统的内存空间紧张时,会将一些处于阻塞状态的进程的代码和数据放入磁盘的swap交换区中(task_struct不会被移动)即唤出,待空间不紧张且该进程应处于就绪态时,会将该进程的代码和数据从交换区中拿出来,即唤入,通过这样的方式操作系统可以更合理的使用内存资源
2、挂起就是将处于阻塞态的进程的代码和数据放至磁盘的swap交换区中
3、用户感受不到挂起态,由操作系统自己进行
4、频繁唤入唤出会导致效率问题,用效率换取空间
5、一般来说磁盘中的swap分区不应该太大,防止操作系统过度依赖该交换区
6、fdisk是Linux下常用的磁盘分区工具(运维常用)
fdisk工具
基本概念:
fdisk
是 Linux 系统中常用的磁盘分区工具之一,用于管理和修改磁盘分区表。它允许你在物理磁盘上创建、删除、查看和修改分区,常用于新安装的硬盘进行初始化、格式化等操作常见功能:
- 查看磁盘分区表:可以查看磁盘上当前的分区信息
- 创建新分区:可以在未分配的磁盘空间中创建新的主分区、扩展分区或逻辑分区
- 删除分区:可以删除现有的分区,从而释放磁盘空间
- 修改分区:修改分区类型、标记为可启动分区等操作
- 写入更改:对磁盘进行更改后,可以将修改写入磁盘分区表
进程的切换
注意事项:
1、CPU中有很多寄存器
2、当进程被CPU调度时,CPU的寄存器中就会保存该进程的所有临时数据(当函数的返回值即将要给予一个变量时,该进程的时间片到了,此时返回值会被存入寄存器中)
3、进程切换时最重要的一件事就是对上下文数据的保护和恢复
4、CPU内部的所有的寄存器中的临时数据,叫做进程的上下文
5、当进程1的时间片到了后,该进程在CPU的寄存器中存放的临时数据会被打包放入该进程的task_struct中(实际是任务段,但是太复杂这里不做过多阐述)此后CPU寄存器中存放的数据为空,然后进程2调度上CPU执行,如果进程2是第一次上CPU则会从头开始向寄存器中放入数据,如果不是则会依据eip寄存器中记录的信息(应该从哪里继续运行)继续运行后续代码并向寄存器中放入数据
6、寄存器本身是硬件,具有数据的存储能力,CPU的寄存器硬件只有一套,但是CPU内部的数据可以有多套(有几个进程就有几套和该进程对应的上下文数据)
7、寄存器不等于寄存器的内容
~over~