Linux进程控制(1)

简介: Linux进程控制(1)

零、前言


前篇我们讲解学习了关于进程的概念知识,本章主要讲解关于进程的控制,深入学习进程


一、进程创建


1、fork函数


  • 概念:


在linux中fork函数从已存在进程中创建一个新进程(子进程),而原进程为父进程


  • fork函数原型:


pid_t fork(void);


注意:

使用fork()函数需要包含头文件<unistd.h>;pid_t类型需要包含头文件<sys/types.h>


fork成功后对子进程返回0,对父进程返回子进程id,fork出错返回-1


内核视角看待fork:

进程调用fork,内核分配新的内存块和内核数据结构给子进程


将父进程部分数据结构内容拷贝至子进程(例如PCB进程控制块,进程地址空间,页表等)


添加子进程到系统进程列表当中,当fork返回后开始调度器调度进程


示图:


fork后执行问题:

当一个进程调用fork之后,父子进程共享同一份代码,也就是说整个代码父子进程都可以看到,但是此时父子进程的执行位置都是相同的,也就是说fork返回后子进程也是往fork之后的代码执行(并非再从头执行)


示例:


#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    printf("Before fork: pid is %d\n", getpid());
    pid_t pid=fork();
    if (pid== -1 )//fork错误
    {
    perror("fork fail");
        exit(1);
    }
    printf("After fork:pid is %d, fork return %d\n", getpid(), pid);
    sleep(1);
    return 0;
}


结果:


示图:


2、fork返回值


返回值:

fork成功对子进程返回0,对父进程返回子进程的pid


写时拷贝


概念:

fork成功之后父子代码共享,当父子不写入数据时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本


为什么数据要进行写时拷贝:

进程具有独立性,多进程运行,需要独享各种资源,多进程运行期间互不干扰,不能让子进程的修改影响到父进程


为什么不在创建子进程的时候就进行数据的拷贝:

子进程不一定会使用父进程的所有数据,并且在子进程不对数据进行写入的情况下,没有必要对数据进行拷贝,我们应该按需分配,在需要修改数据的时候再分配(延时分配),这样可以高效的使用内存空间,提高fork效率,以及fork的成功率


代码会不会进行写时拷贝:

90%的情况下是不会的,但这并不代表代码不能进行写时拷贝,例如在进行进程替换的时候,则需要进行代码的写时拷贝


示图:


fork函数为什么要给子进程返回0,给父进程返回子进程的PID:


一个父进程可以创建多个子进程,而一个子进程只能有一个父进程。因此,对于子进程来说,父进程是不需要被标识的;而对于父进程来说,子进程是需要被标识的,因为父进程创建子进程的目的是让其执行任务的,父进程只有知道了子进程的PID才能很好的对该子进程进行深入操作


为什么fork存在“两个”返回值:


父进程创建子进程时,子进程以父进程为模板构建进程,代码数据父子共享,返回时也是父子进程进行修改数据时,由页表发现该数据是父子进程共享的,所以系统会找到另一个物理空间进行拷贝数据,拷贝数据后再修改数据,达到数据各有一份互不干扰的目的,保证进程的独立性

3、fork用法


我们创建子进程并不是为了父进程执行一样的代码,而是为了使父子进程同时执行不同的代码段


例如:父进程等待客户端请求,生成子进程来处理请求


#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
int main()
{
    pid_t id=fork();//创建子进程
    if(id==0)
    {
        //child
        int cnt=0;
        while(1)
        {
            printf("I am child: pid:%d ppid:%d\n",getpid(),getppid());
            sleep(1);
            if(cnt==8)
                break;
            cnt++;
        }   
        exit(1);//终止进程
    }
    else if(id>0)
    {
        //father
       int cnt=0;
        while(1)
        {
            printf("I am father: pid:%d ppid:%d\n",getpid(),getppid());
            sleep(1);
            if(cnt==8)
                break;
            cnt++;
        }   
    }
    return 0;
}


image.png


  • 用法2:fork返回后调用exec函数替换进程


注:在下文有着重讲解


4、fork失败


fork本质就是向系统要资源,当某个资源不够时则会发生fork失败


  • 失败原因:


1.系统中有太多的进程



2.实际用户的进程数超过了限制



用法1:fork返回后分流执行不同代码


示例:


相关文章
|
17天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
43 1
|
2月前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
48 0
|
5天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
47 13
|
12天前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
20天前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
1月前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
138 4
linux进程管理万字详解!!!
|
25天前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
1月前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
78 8
|
1月前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
72 1
|
1月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?