目录
查看进程
查看进程pid
系统目录查看
理解当前工作目录用途
fork创建进程
存在问题
问题解决
问题一
问题二
本文介绍进程标识符的相关知识以及创建子进程。
查看进程
指令就是可执行程序,每次运行时,都需要被加载到内存,运行起来都要变成进程。
指令执行的一瞬间,进程被创建,执行结束之后,进程被销毁。
进程是有生命的。
ps axj #查看当前所有进程(以列表的形式打印出来)
在Linux中,普通进程都有它的父进程。
当前进程是由它的父进程创建出来的。
pid是当前进程的唯一标识符。ppid是当前进程的父进程的唯一标识符。
pid是进程的唯一标识符,属于操作系统内部PCB的标识符数据,用户不可直接访问,只能通过系统调用接口进行访问。这种做法称为系统调用。
查看进程pid
需要安装man手册
yum install man #安装man手册,非root用户前面加sudo
验证一下上述理论。
ps axj | head -1 && ps axj | grep 进程pid #过滤打印出进程信息名和指定进程信息
每一次启动一个进程,进程的pid会变化,但父进程不变。
在命令行中启动的进程,都是bash创建的子进程,bash是所有进程的父进程。
系统目录查看
Linux会把进程相关的内存级别的数据会以文件系统的形式显示在/proc目录下,就是将内存中的数据放在/proc目录中。以数字命名的目录就是当前内存中的进程的目录,目录名就是当前内存中进程的pid。
也就是说,如果我创建一个进程,那么在/proc这个目录下,就会产生一个记录这个进程信息的目录,目录名是这个进程的pid。
我们来了解一下。
理解当前工作目录用途
这里的cwd是当前的工作目录,exe是可执行程序所处的目录。
exe很好理解,进程要执行这个可执行程序就是通过exe来访问的。
如果我们的可执行程序中有类似于fopen("filename","r/w")这样的函数,这种函数会检测当前工作空间是否存在filename文件,如果不存在则会创建。那么,进程如何确定当前工作目录在哪呢?就是通过cwd来确定访问的。
那么我如果把这个可执行程序删掉,会怎么样呢?
删掉之后,对应的exe就会出现闪烁,但是可执行程序还是可以继续执行的。
原因在于,可执行程序在磁盘上,可执行程序在预加载阶段就已经拷贝在内存中了,所以,可执行程序删除之后,这个进程还是依旧可以运行。
如果我们将这个cwd更改了之后,又会怎样呢?
更改工作目录空间的函数为chdir(const char* path)
测试一下
fork创建进程
我们现在知道,将指令运行起来,这个指令就会变成进程。但是,我们现在无法手动创建进程,即我们还不会用代码的方式创建进程。
fork函数即可以帮助我们创建进程。
我们发现,调用fork函数之后的代码被原进程和新进程都执行了一次,且原进程是新进程的父进程。并且fork之后的代码是共享的。
那么,这个fork函数为什么要有返回值呢?getpid/getppid函数有返回值是因为进程是一个整数,fork函数创建子进程,还需要有返回值吗?--- 结合说明文档和代码看一下
一般而言,我们可以在进程中创建子进程,让父子进程各自做不同的工作。
存在问题
这里就会存在两个问题
问题一:既然子进程是被父进程创建出来的,进程都有对应的可执行程序且具有唯一性,那么此时,父子进程只有一份可执行程序,这是怎么回事呢?
问题二:为什么父子进程可以拿到不同的返回值呢?这里只调用了一次呀。
问题解决
问题一
我们用if-else来让俩个程序执行不同的指令,然后终止掉任意一个进程,研究一下另一个进程是否还可以被正常执行。
kill -9 进程pid #终止指定进程
while :; do ps axj | head -1 && ps axj | grep 可执行程序 | grep -v grep; sleep 1; done #监控指定可执行程序的进程信息
由此可见,进程之间是具有独立性的,互相不影响。这是操作系统设计的时候必须要保证的。
那么,为什么呢?
一般而言,如果父子进程对数据没有修改的话,fork之后父子进程是代码共享的;如果父子进程对数据有修改的话,那么原来的代码和数据就会被操作系统维护起来,父子进程要修改的变量被操作系统单独的给父子进程拷贝一份,父子进程需要修改的话,就去拷贝的地方去修改。这种做法也被称为写时拷贝。
问题二
这里只调用了一次fork,为什么父子进程可以拿到不同的返回值呢?
根据上图,我们就了解到在执行return语句之前,子进程就被创建出来了,所以就返回了两次
。给父子进程返回不同的值,是为了让我们区分父子进程,让他们分别执行不同的逻辑。
至此,进程的标识符内容大致就先了解到这里。