进程概念:
课本概念: 程序的⼀个执⾏实例,正在执⾏的程序等
**内核观点:**担当分配系统资源(CPU时间,内存)的实体。进程 = 内核数据结构(task_struct ) + 代码和数据
什么是PCB?基本概念:
进程信息被放在⼀个叫做进程控制块的数据结构 中,可以理解为进程属性的集合。
课本上称之为PCB (process control block),Linux操作系统下的PCB是:task_struct
操作系统管理任何东西,都一定是遵循着 "先描述,再组织" 的策略,使用结构体对一个对象进行描述,然后将它用一个数据结构组织起来,这样就能达到一种状态:在操作系统中,管理任何对象,最终都可以转化成为对某种数据结构的增删查改。
这里就采用了先描述,再组织,为了更好的描述进程,使用了一个task_struct结构体来把进程的属性数据描述起来,为了更好的组织使task_struct的结构体相互连接。
task_struct 内容分类
- **标示符:**描述本进程的唯一标示符,用来区别其他进程
- **状态:**任务状态
- **优先级:**相对于其他进程的优先级
- **程序计数器:**程序中即将被执行的下一条指令的地址
- **内存指针:**包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块指针
- **上下文数据:**进程执行时处理器的寄存器中的数据
- **I/O状态信息:**包括显示的I/O请求,分配给进程的I/O设备和被进程使用的- - - 文件列表
- **记账信息:**可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
- 其他信息:...
1.查看进程
我们使用ps的命令时。能查看进程的信息。
当我们启动myproc这个进程时候(myproc是个常驻进程) 我们使用下面的语句就能查看myproc进程的信息。
ps ajx | head -1 ; ps ajx | grep myproc
ps ajx | head -1 && ps ajx | grep myproc
这里有个问题,为什么这里显示了myproc的这常驻进程的信息还显示了grep进程的信息?
因为grep本身是一个进程,grep关键字里面有myproc所以会有grep的进程。另外像ps,head这些进程为瞬时进程,命令执行完以后就结束进程。
进程的PID标识符,不是唯一不变的。我们ctrl + c(kill -9 PID)杀死进程后再次启动myproc这个进程,发现PID改变。
如果我们想知道这个进程更多的信息,应该如何操作?
我们可以查看根目录的proc。
ps其实就是打开proc在proc中进行文本分析。
这里目录下面会有很多数字。这些数字就是进程的PID。
例如:进入进程PID:1。我们可以进入进程1的目录下查看更多的信息。
为了验证proc中的数字是进程的PID我们可以做个实验。
当我们杀死进程27567后,我们再次ls /proc/发现27567这个进程就不在了。
另外./proc不是磁盘级别的文件
也就是说当我们关机的时候proc就被自动释放不会存留在磁盘当中,只是把内存的信息展示到磁盘当中。
2.进程cwd与exe
exe:
当我们删除myproc后发现进程还在跑为什么?
因为可执行程序加载到内存了,删除的是磁盘的myproc
exe表示myproc磁盘中的路径位置
cwd:
current work dir当前工作目录
我们执行程序后。我们发现了在当前路径下,形成了一个log.txt可执行程序。
什么叫做当前路径下呢?
当我们启动myproc这个程序时候,会默认记录自己所启动执行程序的路径,紧接着cwd会记录下来。也就是说我们fopen("log.txt","w");会默认把/home/zxw/112/lesson6路径添加到log.txt前。
所谓当前路径就是进程的CWD
如何改变当前路径?
在myproc.c里添加一个chdir
此时更改了当前目录。
3.ppid
ppid是获取自己的父进程的PID。
在linux系统中,启动之后,新创建的任何进程的时候,都是由自己的父进程创建的。
我们每次终止程序后再次启动程序后,发现自己的PID改变但是PPID始终是没有改变的。
这个PPID是谁 --- bash
当我们执行命令/执行程序,本质是bash这个进程创建的子进程执行我们的代码。
如何创建的子进程?
使用系统调用创建进程
1.fork
父:子 = 1 :n(一个父进程可以有多个子进程)
父进程:子进程 = 1:n, 给父进程返回孩子的PID,给子进程返回0,方便父进程的管理。
加了fork()后发现打印两个分支,一个是另一个进程父进程,一个是另一个进程的子进程,代码运行结果如下。
2.函数的特点
fork()-->两个进程-->父子关系
一般而言,代码是共享的,但是数据各自私有一份。
怎么理解代码是共享的呢?
当磁盘中的myproc加载到内存当中,操作系统为了管理这份内存,也创建了对应的PCB。当CPU执行fork这个语句,新创建了一个PCB为子进程,这个子进程只有内核数据结构,没有对应的代码和数据,系统就要求他去和父进程共享一个代码,myproc没有从磁盘二次加载。
数据各自私有一份,先这个当成结论记住。然后先看看如何各自私有一份的。
这里我们在myproc.c这个代码添加一个全局变量int gval = 0;然后在子进程中gval++
进程具有很强的独立性,多个进程之间,运行时,互不影响,即便是父子。
子进程若想修改父进程数据里面的值,系统会给子进程单独开一个空间,放修改的数据(写实拷贝)这样不会影响到父进程。
fork函数的返回值:
一个函数(系统提供的),fork,怎么会有两个返回值呢?
按理来说一个函数只有一个返回值,但是在fork函数内部已经执行了父子进程,所以各自返回相应的id。