在讲述区别之前,先说一说下面的五个问题
①什么是程序,什么是进程,有什么区别?
程序是代码的集合,完成系统的复杂任务;程序跑起来就会产生进程。程序是静态的概念,进程是动态的概念。就比如我们桌面上的这些图标,你可以认为他们不运行的时候就是程序,可是你打开它,就要运行,就会产生对应的进程。
比如说我在Windows操作系统下写博客,我打开可微信和QQ浏览器。这两个软件运行的时候就会产生对应的进程,我按ctrl+shift+Esc就可以在任务管理器中看到
②如何在linux查看系统中有哪些进程?
输入ps可以查看当前用户的进程。
输入ps -aux就可以查看所有的进程并显示详细的用户信息
输入top可以实现类似于windows的任务管理器功能
③什么是进程标识符?
进程的进程标识符就像是人类的身份证一样,每个进程标识符都有自己唯一的非负ID
④什么叫父进程,什么叫子进程?
进程A创建了进程B,那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系。这里不理解没关系,后面会在细说。
⑤C程序的存储空间是如何分配?
大家可以看一下这位大佬的博客,这是链接,我觉得说的很详细
http://t.csdnimg.cn/7woLW,下图就是他文章的东西,我之前有很多的疑惑,包括在学单片机的时候关于ROM和RAM的疑惑这里也有解释,说的很通透。
①getpid(void);获取自身的进程标识符
无参数
返回自身进程ID
②getppid(void);获取父进程的进程标识符
无参数
返回父进程ID
③pid_t fork(void);创建进程
无参数
fork函数调用成功,返回两次
返回值为0,???? 代表当前进程是子进程
返回值大于0,代表当前进程为父进程
调用失败,返回-1
1.验证getpid函数的功能以及fork函数作用,下面是代码
这是运行后的结果
那么问题来了,为啥会有这样的结果?
我们可以看到的是after fork这句话出现了两次,为什么会有这样的结果呢?
让我们回到程序首先程序运行的时候,从头开始,都没有问题,当走到fork之后,程序就又创建了一个新的进程,新的进程就叫做子进程。我们原来的进程就叫做父进程。
那么程序到底是怎么运行的呢?
你可以这样想,把程序的运行分为两节。一节是父进程,另一节是子进程。
回到程序开头,我们程序刚开始的时候也就是我们的父进程刚开始的时候,我们用getpid函数获取了父进程的ID,之后程序会一直走下去。在if里面,因为此时仍然是父进程,左移ID值不变,接着在return 0之前父进程停止;然后我们的子进程进开始工作了,这时候程序是从fork函数开始工作,而不是从头开始工作的,所以就又会开始新一轮的if else比较。
2.验证fork函数的返回值,下面是代码
这是运行的结果
从运行结果上我们可以看到父进程的返回值大于0,子进程的返回值等于0。而且不知道大家发现了没有,父进程的返回值等于子进程的ID号。这不是巧合,就是有这样的关系。
同时父进程和子进程在运行的时候是两个独立的个体,大家互不影响。老版本的linux里,子进程运行时需要完全拷贝父进程的内容,然后用啥改啥,因为是拷贝出去单独运行,所以不管是两者运行的时候对对方都是没有影响的。新版本的linux带有共享机制,如果子进程不去改变父进程的一些参数,那么就和父进程一起使用,如果需要改变参数,则会拷贝父进程对应的内容,然后修改,但是也不影响父进程的值。
3.fork函数创建子进程的简单应用,代码如下
这里想要实现的是当我们输入1的时候,我们就会使用fork函数创造一个子进程,并且让子进程不断打印自己的ID值。当我们输入其他的数字的时候,就会显示wait donothing。
运行结果
我们可以看到我们的输入和子进程的工作并不冲突,这就好比我们的服务器和客户端,无论客户端给服务器多少消息,服务器总能给客户端创造一个子进程满足你的需求,并且还不影响服务器继续接收外来请求。
1.fork与vfork很像但是也是有区别的
vfork 直接使用父进程存储空间,不拷贝;fork是需要拷贝的。
vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行;fork的父进程和子进程的运行顺序是由系统调度决定的。
pid_t vfork(void);创建进程
无参数
vfork函数调用成功,返回两次
返回值为0,???? 代表当前进程是子进程
返回值大于0,代表当前进程为父进程
2.fork与vfork区别的验证
下面的两段代码除了pid=fork();和pid=vfork();不一样以外,其余的地方都一样。但是他们运行的结果却不一样,如下图。
其中fork的运行结果如下图所示,我们可以看到子进程和父进程是在争夺进程的控制权一样,很乱,没有顺序。
而vfork的运行结果如下图所示,我们可以看到子进程不是用exit函数,父进程就不会开始。
下面我们略微修改一下程序,采用计数的方法,当cnt从0到3是调用exit函数结束子进程,父进程开始工作,程序如下图
运行结果如下