招聘网站建设工作汇报,wordpress自定义前端,孝感市建设网站,如何得知网站有没有做推广目录
一、进程的基本概念
二、pid#xff0c;ppid#xff0c;fork函数
三、进程的状态讲解
四、进程的优先级
五、完结撒❀ 一、进程的基本概念
概念#xff1a; ● 课本概念#xff1a;程序的一个执行实例#xff0c;正在执行的程序等 ● 内核观点#xff1a;担当…目录
一、进程的基本概念
二、pidppidfork函数
三、进程的状态讲解
四、进程的优先级
五、完结撒❀ 一、进程的基本概念
概念 ● 课本概念程序的一个执行实例正在执行的程序等 ● 内核观点担当分配系统资源 CPU 时间内存的实体 描述进程 —— PCB ● 进程信息被放在一个叫做进程控制块的数据结构中可以理解为进程属性的集合。 ● 课本上称之为 PCB process control block 内核数据结构 Linux 操作系统下的 PCB 是 :task_struct task_struct —— PCB 的一种 ● 在 Linux 中描述进程的结构体叫做 task_struct 。 ● task_struct 是 Linux 内核的一种数据结构它会被装载到 RAM( 内存 ) 里并且包含着进程的信息 下面我们讲解一下要完成一个进程的运行计算机设备以及操作系统所运作的整体逻辑能使大家对进程有更深刻的理解
首先比如我们所敲的一些代码或者是Linux中的命令pwdls等运行起来其实就都是一个进程而我们没有运行的时候这些代码文件是存放在磁盘上的当我们将一个程序运行起来之后需要将这些代码文件加载到内存里面 加载到内存里面的就是对应运行程序的代码和数据但这还并不是一个进程
在Linux中存在许多的命令如果运行一个程序只是将其代码和数据加载到内存中的话那么在Linux中有那么多的指令并且同一时间可能有许多进程同时在运行我们又该如何进行管理
这就变成了一个面向对象操作的问题面向对象操作的精髓就是先描述再组织
所以我们就有了PCB在Linux中PCB叫做task_struct
通过结构体task_struct对对象先进行描述下面是task_struck里面的部分信息 task_ struct 内容分类 ● 标示符 : 描述本进程的唯一标示符用来区别其他进程。 ● 状态 : 任务状态退出代码退出信号等。 ● 优先级 : 相对于其他进程的优先级。 ● 程序计数器 : 程序中即将被执行的下一条指令的地址。 ● 内存指针 : 包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针 ● 上下文数据 : 进程执行时处理器的寄存器中的数据 [ 休学例子要加图 CPU 寄存器 ] 。 ● I O 状态信息 : 包括显示的 I/O 请求 , 分配给进程的 I O 设备和被进程使用的文件列表。 ● 记账信息 : 可能包括处理器时间总和使用的时钟数总和时间限制记账号等。 ● 其他信息 现在我们只需要知道task_struct里面有一个task_struct* next指针用来连接各个task_struct结构体和内存指针用来指向对应进程在内存中的数据代码即可 这样就可以同时运行多个进程并且对每个进程进行管理操作
那么进程到底是什么
进程 PCB 自己的代码和数据
而PCB内核数据结构又是从哪里来的呢 各位不要把操作系统给忘了操作系统的功能之一是为用户提供良好高效稳定安全的运行环境所以这里按理来说一定有操作系统的参与。
在我们的电脑或是手机关机开机的时候就是在加载操作系统开机之前操作系统是以一堆二进制文件存放在磁盘中开机过程中将二进制文件加载到内存中而PCB就是在操作系统内部存储的
所以当我要运行一个程序的时候首先将在存在磁盘中的数据拷贝到内存中再在操作系统中开辟出一块对应空间用于存储PBC 组织进程 可以在内核源代码里找到它。所有运行在系统里的进程都以 task_struct 链表的形式存在内核里。 二、pidppidfork函数
上面我们讲解了进程的基本概念对进程也已经有所了解
在同一时间内操作系统可能会同时运行多个进程这我们在上面也讲过那么问题来了
我们是如何区分在同一时段内每一个不同的进程的呢
在Linux中是以pid进程标识符进行区分的
每一个进程都要有自己的唯一标识符叫做进程pid
查看进程 进程的信息可以通过 /proc 系统文件夹查看 ● 如要获取 PID 为 1 的进程信息你需要查看 /proc/1 这个文件夹。 ● 大多数进程信息同样可以使用 top 和 ps 这些用户级工具来获取 我们以运行下面代码为例
#include stdio.h
#include sys/types.h
#include unistd.hint main()
{while(1){printf(this a process\n);sleep(1);}return 0;
}命令ps ajx就是显示当前所有进程head -1表示获取进程头一行的内容是将两个命令进行连接一起执行后面grep就不进行解释了
那么我们运行上面代码查看所对进程显示信息如下
可以看到出现有两个进程第一个就是我们所运行的进程在第一行上面所显示的就是每个进程所对应的数据信息可以看到第一列表示ppid即每个进程所对应的ppid第二列表示pid
那么我们在程序中如何访问其进程的pid值呢 ppidpid等都是存储在操作系统内部的数据而作为用户我们不能直接对操作系统进行访问但是我们可以通过调用其对应所连接系统调用接口的库函数进行对pid的访问 通过系统调用获取进程标示符 ● 进程idpidgetpid() ● 父进程idppidgetppid() #include stdio.h
#include sys/types.h
#include unistd.hint main()
{printf(pid: %d\n, getpid());printf(ppid: %d\n, getppid());return 0;
}
这里再提一下Ctrl c可以在用户层面终止进程kill -9 pid可以直接杀掉进程
下面我们再来认识一下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 之后通常要用 if 进行分流 #include stdio.h
#include sys/types.h
#include unistd.h
int main()
{int ret fork();if(ret 0){perror(fork);return 1;}else if(ret 0){ //childprintf(I am child : %d!, ret: %d\n, getpid(), ret);}else{ //fatherprintf(I am father : %d!, ret: %d\n, getpid(), ret);}sleep(1);return 0;
} 在一个进程A运行中在创建一个进程B那么进程A就是进程B的父进程进程B的ppid为进程A的pid并且进程B是可以看到并调用进程A的代码但进程A和进程B的储存和运行又是相互独立存在的。
三、进程的状态讲解
为了弄明白正在运行的进程是什么意思我们需要知道进程的不同状态。一个进程可以有几个状态在Linux内核里进程有时候也叫做任务。 下面是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 运行状态 running : 并不意味着进程一定在运行中它表明进程要么是在运行中要在运行队列里。 S 睡眠状态 sleeping): 意味着进程在等待事件完成这里的睡眠有时候也叫做可中断睡眠 interruptible sleep 。 D 磁盘休眠状态 Disk sleep 有时候也叫不可中断睡眠状态 uninterruptible sleep 在这个状态的 进程通常会等待 IO 的结束。 T 停止状态 stopped 可以通过发送 SIGSTOP kill 信号给进程来停止 T 进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。 X 死亡状态 dead 这个状态只是一个返回状态你不会在任务列表里看到这个状态。 进程状态查看 ps aux / ps axj 命令 在上面所提到的ps ajx | head -1中的STAT表示的就是当前进程状态 Z(zombie)- 僵尸进程 ● 僵死状态 Zombies 是一个比较特殊的状态。当进程退出并且父进程使用 wait() 系统调用 , 后面讲 没有读取到子进程退出的返回代码时就会产生僵死 ( 尸 ) 进程 ● 僵死进程会以终止状态保持在进程表中并且会一直在等待父进程读取退出状态代码。 ● 所以只要子进程退出父进程还在运行但父进程没有读取子进程状态子进程进入 Z 状态 下面是维持30s的僵尸进程例子大家可以手动实验一下
#include stdio.h
#include stdlib.hint main()
{pid_t id fork();if(id 0){perror(fork);return 1;}else if(id 0){ //parentprintf(parent[%d] is sleeping...\n, getpid());sleep(30);}else{printf(child[%d] is begin Z...\n, getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
} 僵尸进程危害 ● 进程的退出状态必须被维持下去因为他要告诉关心它的进程父进程你交给我的任务我办的怎 么样了。可父进程如果一直不读取那子进程就一直处于 Z 状态 ● 维护退出状态本身就是要用数据维护也属于进程基本信息所以保存在 task_struct(PCB) 中换句话 说 Z 状态一直不退出 PCB 一直都要维护 ● 那一个父进程创建了很多子进程就是不回收就会造成内存资源的浪费因为数据结构 对象本身就要占用内存想想 C 中定义一个结构体变量对象是要在内存的某个位置进行开辟空 间 ● 引发内存泄漏 孤儿进程 ● 父进程如果提前退出那么子进程后退出进入 Z 之后那该如何处理呢 ● 父进程先退出子进程就称之为 “ 孤儿进程 ” ● 孤儿进程被 1 号 init 进程bash领养当然要有 init 进程回收喽。 四、进程的优先级 基本概念 ● cpu 资源分配的先后顺序就是指进程的优先权 priority 。 ● 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的 linux 很有用可以改善系统性能。 ● 还可以把进程运行到指定的 CPU 上这样一来把不重要的进程安排到某个 CPU 可以大大改善系统整体性能。 查看系统进程 在 linux 中用 ps –l 命令则会类似输出以下几个内容 我们很容易注意到其中的几个重要信息有下 ● UID : 代表执行者的身份 ● PID : 代表这个进程的代号 ● PPID 代表这个进程是由哪个进程发展衍生而来的亦即父进程的代号 ● PRI 代表这个进程可被执行的优先级其值越小越早被执行 ● NI 代表这个进程的 nice 值 PRI and NI ● PRI 也还是比较好理解的即进程的优先级或者通俗点说就是程序被 CPU 执行的先后顺序此值越小 进程的优先级别越高开始一般默认数值为80 ● 那 NI 呢 ? 就是我们所要说的 nice 值了其表示进程可被执行的优先级的修正数值 ● PRI 值越小越快被执行那么加入 nice 值后将会使得 PRI 变为 PRI(new)PRI(old)nice ● 这样当 nice 值为负值的时候那么该程序将会优先级值将变小即其优先级会变高则其越快被执行 ● 所以调整进程优先级在 Linux 下就是调整进程 nice 值 ● nice 其取值范围是 -20 至 19 一共 40 个级别。 PRI vs NI ● 需要强调一点的是进程的 nice 值不是进程的优先级他们不是一个概念但是进程 nice 值会影响到进 程的优先级变化。 ● 可以理解 nice 值是进程优先级的修正数据 查看进程优先级的命令 用 top 命令更改已存在进程的 nice ● top ● 进入 top 后按 “r”– 输入进程 PID– 输入 nice 值 其他概念 ● 竞争性 : 系统进程数目众多而 CPU 资源只有少量甚至 1 个所以进程之间是具有竞争属性的。为了高 效完成任务更合理竞争相关资源便具有了优先级 ● 独立性 : 多进程运行需要独享各种资源多进程运行期间互不干扰 ● 并行 : 多个进程在多个 CPU 下分别同时进行运行这称之为并行 ● 并发 : 多个进程在一个 CPU 下采用进程切换的方式在一段时间之内让多个进程都得以推进称之为 并发 五、完结撒❀
如果以上内容对你有帮助不妨点赞支持一下以后还会分享更多编程知识我们一起进步。 最后我想讲的是据说点赞的都能找到漂亮女朋友❤