波奇学Linux:父子进程和进程状态

vim编辑器,编写一个程序模拟进程

波奇学Linux:父子进程和进程状态_第1张图片

 在vim中查看sleep函数

底行模式输入

 写个Makefile自动运行波奇学Linux:yum和vim-CSDN博客

波奇学Linux:父子进程和进程状态_第2张图片

运行程序

 PID和PPID

查看进程目录信息

实际有过滤出来有两个,一个进程本身一个是grep程序,通过 -v grep过滤走含grep的进程。

 目录中的PID相当于进程的唯一标识符。就是给进程分配一个号码,这个数字和进程之间是一一对应的。

PID是进程的属性,那么PID是在 struct task_struct结构体中。

task_struct(波奇学Linux:冯诺依曼和进程-CSDN博客)

 ​​​​​​​波奇学Linux:父子进程和进程状态_第3张图片

 ps ajx本质是就是遍历双向链表。

 而PPID是该进程的父进程的编号

查看父进程信息,可知父进程是-bash命令行

当xhell打开时会运行bash进程,而每个命令行command都是bash的子进程 。

因此当make 时命令行会创建子进程来启动程序。

kill 指令 关闭进程

输入指令kill -9 PID 关闭进程

波奇学Linux:父子进程和进程状态_第4张图片 

 getpid()和getppid()返回进程的PID和PPID,证明PID确实是进程PCB的属性

查看函数信息可以用命令行!man查看

波奇学Linux:父子进程和进程状态_第5张图片

PID和PPID刚好吻合 

波奇学Linux:父子进程和进程状态_第6张图片 

波奇学Linux:父子进程和进程状态_第7张图片

fork创建子进程

波奇学Linux:父子进程和进程状态_第8张图片 

编写程序

波奇学Linux:父子进程和进程状态_第9张图片

波奇学Linux:父子进程和进程状态_第10张图片

第二号的after line打印两遍的原因是fork创建了一个子线程,子线程运行了一遍printf("after line\n"); 

fork会返回两次,创建子进程成功,返回子进程的PID给父进程,返回0给子进程

波奇学Linux:父子进程和进程状态_第11张图片 波奇学Linux:父子进程和进程状态_第12张图片

说明确实父子进程同时运行 。

初步理解fork的原理

代码的执行流是从上往下的,遇到fork函数时一份为二。

波奇学Linux:父子进程和进程状态_第13张图片

 fork函数内部构拷贝一份父线程的task_struct,子线程指向父线程的代码,因此子父线程共享代码。

子父线程相对独立,不共享数据。因此父线程写时拷贝数据给子线程。当子线程要修改父线程的变量时,会把变量拷贝一份,开辟空间给子线程。既避免了浪费空间还避免子线程修改父线程的变量。

fork return两次,因此一般fork下要分流,分出父子线程。

父进程和子进程谁先运行是由调度器决定的。

bash创建子进程,底层调用了fork

进程状态:运行,阻塞,挂起

波奇学Linux:父子进程和进程状态_第14张图片

运行

运行一个进程会把进程放入一个运行队列 runqueue 

波奇学Linux:父子进程和进程状态_第15张图片

波奇学Linux:父子进程和进程状态_第16张图片

通过控制task_struct指针来控制进程的运行先后,每个进程都有一个时间片的概念

并且有个时间片如10ms,比如这个进程一可能运行10ms。

并发执行:在一段时间内所有的在队列中的进程都会运行。

处于运行队列的进程为R态:随时被调度。
把进程从cpu上拿下来或者放上去,进程切换。

阻塞:离开运行队列,进程进入等待队列。

波奇学Linux:父子进程和进程状态_第17张图片

某个进程(比如含有scanf的语句)必须从外设从获取 数据输入时,才能继续运行,那么他就进入阻塞状态,如果同时有其他进程也要获得数据,他们会从运行队列中脱离出来进入等待队列中,知道获取数据。阻塞就是暂停,直到某个条件达成后再继续运行。

等待队列的进程处于阻塞状态,阻塞队列有n个,运行队列只能有一个(1个cpu)

唤醒:就是从阻塞状态转为R态,重新进入运行队列。

挂起:数据暂时进入磁盘中

阻塞挂起:当操作系统内存严重不足时,处于等待队列的进程会把数据从内存加载到磁盘,只留下pcb。此时进程被挂起,当进程唤醒时。又从磁盘加载数据到内存。

你可能感兴趣的:(Linux,linux,运维,服务器)