我们启动一个软件,本质就是启动一个进程
在Linux下,运行一条命令,运行的时候,其实就是在系统层面创建了一个进程
而Linux系统管理大量进程则是先描述,再组织
进程 = 对应的代码和数据 + 进程等对应的PCB结构体
PCB包含了所有进程属性,所以对进程的管理,变成了对进程PCB结构体链表的增删查改
进程控制块PCB
- 在Linux中描述进程的结构体叫做task_struct
- task_struct是Linux内核的一种数据结构, 它会被装载到RAM(内存)里并且包含着进程的信息
task_struct内容分类
- 标示符:描述本进程的唯一标示符,用来区别其他进程
- 状态:任务状态, 退出代码, 退出信号等
- 优先级:相对于其他进程的优先级
- 程序计数器:程序中即将被执行的下一条指令的地址
- 内存指针:包括程序代码和进程相关数据的指针, 还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]
- I/ O状态信息:包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表
- 记账信息:可能包括处理器时间总和, 使用的时钟数总和, 时间限制, 记账号等
- 其他信息
fork初识
- 运行
man fork
认识fork- fork 有两个返回值
- 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{int ret = fork();printf("hello proc: %d!, ret: %d\n", getpid(), ret);sleep(1);return 0;
}
有两个返回值是因为fork内部,父子各自会执行自己的return语句
但返回两次,并不意味着会保存两次
父子进程被创建出来,谁先运行并不确定。这个是由操作系统的调度器决定的
进程状态
新建:字面意思
运行:task_struct 结构体在运行队列中排队,就叫做运行态
阻塞:等待非CPU资源就绪,阻塞状态
挂起:当内存不足的时候,OS通过适当的置换进程的代码和数据到磁盘,进程的状态就叫做挂起
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 运行状态(running)
:并不意味着进程一定在运行中, 它表明进程要么是在运行中要么在运行队列里
S 睡眠状态 (sleeping)
:意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep) )
D磁盘休眠状态(Disk sleep)
:磁盘睡眠,深度睡眠,不可被中断,不可被被动唤醒,只能自己醒来或是断电
T 暂停状态(stopped)
:可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
Z 僵尸状态(Zombies)
:一个进程已经退出,但还不允许被os释放,处于一个被检测的状态就叫作僵尸状态,维持该状态,为了让父进程和os来进行回收
X死亡状态(dead)
:dead终止,瞬时性非常强,这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
孤儿进程
一般的进程都是由父进程进行回收;
如果父进程先退出,子进程还没退出
,那么这个子进程就称之为“孤儿进程”。
孤儿进程会被1号 init 进程领养,也由init进程回收(init 系统本身)
进程优先级
cpu资源分配的先后顺序,就是指进程的优先权(priority)。
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值
如果进程A正在被运行,CPU的寄存器里,一定保存的是进程A的临时数据
寄存器中的临时数据,叫做A的上下文。
其他概念
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高
效完成任务,更合理竞争相关资源,便具有了优先级
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
环境变量
常见环境变量
PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。
查看环境变量方法
echo $NAME
NAME:你的环境变量名称
env:查看系统中所有环境变量的命令
也可以配合之前学的文本行过滤工具找到想要的环境变量,如env | grep PATH
使用echo查看PATH环境变量
和环境变量相关的命令
- echo: 显示某个环境变量值
- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
通过代码如何获取环境变量
// 第三个env就是环境变量
#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{int i = 0;for(; env[i]; i++){printf("%s\n", env[i]);}return 0;
}
程序中使用函数: getenv()
获取环境变量
char* p = NULL;
p = getenv("PATH");
子进程的环境变量是从父进程来的!
默认,所有的环境变量,都会被子进程继承。
✨✨✨✨✨✨✨✨
本篇博客完,感谢阅读🌹
如有错误之处可评论指出
博主会耐心听取每条意见
✨✨✨✨✨✨✨✨