Linux创建进程


一、命令行创建进程

在命令行执行指令其实就是在执行进程,我命令行下创建出来的进程,我命令行创建出来的进程就是想让别的进程来实现不同的功能,指令是一个个二进制可执行程序。几乎所有在命令行上执行的指令都是bash的创建子进程,就是我创建的子进程去给我做其他工作,不论做的如何,当子进程执行功能完毕,反正都要将子进程所做的工作结果返回给创建它的那个进程,这是一个父进程,在命令行下的子进程,他们的父进程都是bash进程。
在这里插入图片描述
这些是bash下创建的进程然后执行。
运行一个可执行程序,然后查看发现它的父进程是13638
在这里插入图片描述
ps axj查看进程发现13638这个pid进程是bash
在这里插入图片描述
这个可执行程序退出,然后再重新运行,他们的pid不同,这个也是理所应当的,就像高考填报志愿,第一年填的某某学校,然后这个学校会给你分配一个学号,但是呢这个学生有些不满意,所有他又回去复读,但是第二年他又考上了这所大学,此时学校再给他分配学号又是另外一个,是不相同的进程pid也同样如此,所有退出之后又给它分配pid,尽管这个程序pid不同,但是它的父进程pid还是没有变得 ,就表明它的父进程还是原先那个
在这里插入图片描述
还是bash,这也表明了在命令行下执行的指令就是它创建的子进程。

二、系统接口fork创建子进程

系统接口fork可以创建子进程,查看man手册
在这里插入图片描述
它是一个系统接口,会创建一个子进程,然后会有返回值类型为pid_t
在这里插入图片描述
创建子进程成功返回值有两个,一个进程pid会返回给它的父进程,也就是创建它的那个进程,还会将0返回给他自己(创建好的子进程),若是失败,那么就会返回-1
对于进程来说,要在代码层面就知道它的PID或者PPID有两个系统接口可以获取:getpid()可以获取当前进程的PID,getppid()可以获取当前进程它的父进程的PPID
在这里插入图片描述
调用fork之后,原本的代码会被执行两次

在这里插入图片描述
这是为什么,man 手册里详细介绍了fork成功会有两个返回值,也就注定了他又两个执行流。
在这里插入图片描述
通过实验测试发现,fork创建子进程之后会有两个返回值,然后接下来的程序会进入两个执行流执行两个死循环,fork调用之后的代码被执行了两次,fork之前只有一个执行流fork之后变为了两个执行流。正常情况下代码是从上往下执行为什么会出现这样的情况?因为fork而引发的现象。有以下几个问题搞懂之后就可以理解了!
为什么fork要给子进程返回0,给父进程返回子进程的PID?
因为父进程要关心自己的孩子是谁,但是他又可能有很多子进程,所以要拿到能唯一能标识自己子进程的,也就是要拿到子进程的pid,有时候要对子进程进行管理,这样得到子进程pid就足够了,而对于子进程来说,它只有一个父亲,所以要知道自己父进程是谁,只需要调用getppid就可以了,而进程pid几乎没有为0的,所以自己成拿到的是返回值为0的,判断返回值大于0的就是父进程执行的执行流。
fork之后可以根据不同返回值判断,执行不同的分支从而执行不同代码片段,返回不同的返回值,就让不同执行流执行不同的代码片段,一般而言fork之后父子进程的代码是共享的,两个都可以看见,所有要通过一定的区分,然后达到让子进程执行不同的功能。
fork干了什么事情?
fork它会根据原来的父进程为模板,然后创建出一个子进程,除了拥有自己的pid和父进程对应的ppid之外,task_struct其他属性字段都是从父进程上拿下来初始化子进程的字段信息,没有fork之前只有一个进程,fork之后变为了两个进程
而进程=内核数据结构对象+代码和数据,刚开始创建出来的子进程什么都没有,几乎所有都是从父进程拷贝下来的,它的代码和数据都是从父进程那里来,它会和父进程一样访问同样的代码共享(fork是一个函数,那么它里面的代码父子进程都是可以看见并行能够运行)代码加载到内存之后,代码就变得不可修改了,所以代码共享,但是数据共享又是怎么回事?当父子进程里面的数据都不修改的话,就可以共享,但是若要修改父进程指向的数据时候,操作系统要在内存中找一块内存空间,然后将父进程的数据拷贝过去之后再修改,这是一种写时拷贝技术!
在这里插入图片描述
所以fork之后父子进程执行同一份代码,所以代码会被执行两次!
为什么要创建子进程?
创建子进程就是为了让子进程和父进程执行不同的事情,然后给父进程进行反馈,也就要让子进程和父进程执行不同的代码块,id有两个不同的值,然后后续代码执行不同分支流实现让父子进程执行不同功能。
fork如何具有两个返回值?
而要让父子进程执行不同的代码块,也就要让fork具有了不同的返回值,那么一个函数是如何让返回值返回两次的?因为fork是一个函数,父子进程共享同一份代码,所以父进程和子进程都会执行fork这个函数,而fork有return 语句,return 语句也是代码所以会被执行两次,所以会有两个返回值,会被返回两次。此时代码是共享的,然后当子进程也返回时,对于pid_t id要写入数据,此时就要修改父进程的数据,所以要发生写时拷贝(操作系统单独开空间拷贝这个数据)所以id有两个不同的值,然后后续代码执行不同分支流实现让父子进程执行不同功能。正如上述,fork创建子进程之后子进程啥也没有,所以它的代码和数据也是父进程的,代码不可以修改,共享也就算了,但是数据是会被修改的,此时父子进程若是再用同一份数据,那么一个进程对其修改两者都会被受到影响。而这也就要保证他们之间的独立性,任何平台,进程在运行的时候,是具有独立性的各个进程之间相互独立(当我修改数据之后要能不影响其他进程)。所以父子进程也是相互独立的,他们不能共享同一份数据,对于数据的拷贝也不至于将父进程数据全部拷贝因为有可能全部拷贝下来一次都用不到,浪费了空间资源,操作系统是不会允许这样的情况发生,反正操作系统就会观察,当子进程要对某份数据资源进行写入修改时,那么操作系统就在内存中单独开辟一块空间,然后将这个数据从父进程那里拷贝到新开空间中,这样叫做写时拷贝,按需申请空间用来存放需要修改的数据。所以pid_t id = fork():创建完毕会有两个返回值,是代码共享,同一份代码执行两次,然后返回的值父进程对数据进行写入给id没做什么,但是子进程返回的值要写入id时,要对数据进行修改,此时操作系统察觉到了要修改数据,所以就由操作系统为他再开一块空间,然后将子进程代码返回的值写入这个空间中,所以fork具有两个不同返回值!

总结

创建进程两个方式:"./"运行我们的程序(指令层面)
fork:在代码运行期间(代码层面)

  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值