【进程创建】

目录

进程创建的方式

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,因为子进程只有一个父进程。

子进程刚开始创建的状态

c 复制代码
#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;
}

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

一个变量,两个不同的值

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

c 复制代码
#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;
}

创建子进程的作用

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

相关推荐
韩楚风3 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学3 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO3 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu73 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我3 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、3 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程3 小时前
Linux中环境变量
linux
挥剑决浮云 -4 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
小O_好好学5 小时前
CentOS 7文件系统
linux·运维·centos
x晕x6 小时前
Linux dlsym符号查找疑惑分析
linux·运维·服务器