vim编辑器,编写一个程序模拟进程
在vim中查看sleep函数
底行模式输入
写个Makefile自动运行波奇学Linux:yum和vim-CSDN博客
运行程序
PID和PPID
查看进程目录信息
实际有过滤出来有两个,一个进程本身一个是grep程序,通过 -v grep过滤走含grep的进程。
目录中的PID相当于进程的唯一标识符。就是给进程分配一个号码,这个数字和进程之间是一一对应的。
PID是进程的属性,那么PID是在 struct task_struct结构体中。
task_struct(波奇学Linux:冯诺依曼和进程-CSDN博客)
ps ajx本质是就是遍历双向链表。
而PPID是该进程的父进程的编号
查看父进程信息,可知父进程是-bash命令行
当xhell打开时会运行bash进程,而每个命令行command都是bash的子进程 。
因此当make 时命令行会创建子进程来启动程序。
kill 指令 关闭进程
输入指令kill -9 PID 关闭进程
getpid()和getppid()返回进程的PID和PPID,证明PID确实是进程PCB的属性
查看函数信息可以用命令行!man查看
PID和PPID刚好吻合
fork创建子进程
编写程序
第二号的after line打印两遍的原因是fork创建了一个子线程,子线程运行了一遍printf("after line\n");
fork会返回两次,创建子进程成功,返回子进程的PID给父进程,返回0给子进程
说明确实父子进程同时运行 。
初步理解fork的原理
代码的执行流是从上往下的,遇到fork函数时一份为二。
fork函数内部构拷贝一份父线程的task_struct,子线程指向父线程的代码,因此子父线程共享代码。
子父线程相对独立,不共享数据。因此父线程写时拷贝数据给子线程。当子线程要修改父线程的变量时,会把变量拷贝一份,开辟空间给子线程。既避免了浪费空间还避免子线程修改父线程的变量。
fork return两次,因此一般fork下要分流,分出父子线程。
父进程和子进程谁先运行是由调度器决定的。
bash创建子进程,底层调用了fork
进程状态:运行,阻塞,挂起
运行
运行一个进程会把进程放入一个运行队列 runqueue
通过控制task_struct指针来控制进程的运行先后,每个进程都有一个时间片的概念
并且有个时间片如10ms,比如这个进程一可能运行10ms。
并发执行:在一段时间内所有的在队列中的进程都会运行。
处于运行队列的进程为R态:随时被调度。
把进程从cpu上拿下来或者放上去,进程切换。
阻塞:离开运行队列,进程进入等待队列。
某个进程(比如含有scanf的语句)必须从外设从获取 数据输入时,才能继续运行,那么他就进入阻塞状态,如果同时有其他进程也要获得数据,他们会从运行队列中脱离出来进入等待队列中,知道获取数据。阻塞就是暂停,直到某个条件达成后再继续运行。
等待队列的进程处于阻塞状态,阻塞队列有n个,运行队列只能有一个(1个cpu)
唤醒:就是从阻塞状态转为R态,重新进入运行队列。
挂起:数据暂时进入磁盘中
阻塞挂起:当操作系统内存严重不足时,处于等待队列的进程会把数据从内存加载到磁盘,只留下pcb。此时进程被挂起,当进程唤醒时。又从磁盘加载数据到内存。