当前位置:   article > 正文

【进程创建】

【进程创建】

进程创建的方式

1.在操作系统上输入的指令。
2.已经启动的软件。
3.程序员在代码层面上调用系统调用创建进程。
linux中第一个创建的进程是init,操作系统以后的进程创建,就可以依靠该init进程为父进程创建子进程,创建的子进程也可以做为之后进程创建的父进程。所以进程的创建是依靠父进程创建出来的。在使用linux命令行解释器执行指令创建进程中,命令行解释器bash就是父进程。

查看进程pid

top指令查看进程id
也可以ps axj | grep name查看某个名字的进程id
也可以使用系统调用getpid()获取当前运行进程的pid
ls /proc/id -l 查看进程当前目录等信息
在这里插入图片描述
在这里插入图片描述
每个进程都有自己的id编号pid,所以操作系统管理进程时,就可以找该进程对应的pid编号。

调用系统调用创建子进程

fork()是linux创建子进程的系统调用,返回值是整形,如果返回值为0,就是子进程,如果返回值大于0(父进程创建子进程的子进程pid),就是父进程,如果返回值小于0,创建子进程失败,返回值为-1,错误码被设置。
在这里插入图片描述

查看父进程可以调用getppid(),当程序被运行的时候,我们发现两个循环体尽然都有在执行,而且他们的进程pid都不一样,但是子进程的ppid和父进程的pid一样,说明子进程是由父进程创建的。这段代码看着好像只有一个执行流,但是有两个进程。他们在并行地运行,执行。进程的概念给上层用户提高了一个很好的假象,每个程序独自占用处理器的资源,独自占用一个内存资源。

fock函数做了的工作

  1. fork函数在已有的进程中创建了新的进程,即父进程创建了子进程。所以有两个返回值。
  2. fork创建成功返回的两个返回值,一个是父进程的调用fork时返回的,一个是子进程的创建的时候返回的。
  3. fork返回值给父进程为子进程pid,因为一个父进程可以创建多个子进程,父进程实际上要对子进程管理。fork给子进程返回值为0,因为子进程只有一个父进程。

子进程刚开始创建的状态

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    int pid = fork();
    printf("I am father process,my pid is: %d, my praent ppid is: %d#########\n", getpid(), getppid());
    printf("I am running: pid :%d   ppid:%d\n",getpid(),getppid());
    if (pid == 0)
    {
        while (1)
        {
            printf("I am child process,my pid is: %d, my praent ppid is: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    if (pid > 0)
    {
        while (1)
        {
            printf("I am father process,my pid is: %d, my Ppraent ppid is: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

子进程创建的时候,是根据父进程为模板创建的,和父进程的代码和数据,内存共享的。创建的子进程连接到运行队列里。因为子进程是根据父进程为模板创建的,继承了父进程的代码和数据。可以看出在fork成功后,子进程也是可以看到fork之前的代码的。

一个变量,两个不同的值

父进程创建子进程后。代码和数据共享指向的内存空间也是一样的。如果有一个全局的变量,父子进程对这个进程操作不同。数据发送了改变,哪个进程先对这个数据改变,操作系统就会申请新的内存给该进程,这是为了保证进程的独立性,互补干扰,让进程有独自的存放空间。代码的全局变量num在不同的进程中,指向不同的指令,一个自增,一个自减,互补干扰。观察到对同一变量num取地址,发现一样,其实这个地址是虚拟地址,并不是真实的物理地址。父子进程对数据改变的话,真实物理地址就会不一样。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
static num = 100;
int main()
{
    int pid = fork();
    printf("I am father process,my pid is: %d, my praent ppid is: %d#########\n", getpid(), getppid());
    printf("I am running: pid :%d   ppid:%d\n",getpid(),getppid());
    if (pid == 0)
    {
        while (true)
        {
            printf("I am child process,my pid is: %d, my praent ppid is: %d\n", getpid(), getppid());
            printf("num = %d,num address: %p\n",num++,&num);
            printf("#######################################\n");
            sleep(1);
        }
    }
    if (pid > 0)
    {
        while (true)
        {
            printf("I am father process,my pid is: %d, my Ppraent ppid is: %d\n", getpid(), getppid());
            printf("num = %d,num address: %p\n",num--,&num);
            printf("#######################################\n");
            sleep(1);
        }
    }
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

在这里插入图片描述

创建子进程的作用

创建子进程本质上是为了和父进程执行不同的任务。所以创建子进程后,一般就会指向新重新加载到内存的代码和数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/143441
推荐阅读
相关标签
  

闽ICP备14008679号