Linux系统编程(进程基础知识讲解)

news2025/1/17 13:56:54

文章目录

  • 前言
  • 一、进程的概念
  • 二、进程的生命周期
  • 三、进程树
  • 四、进程的创建
  • 五、一个进程可以执行几个程序?
  • 六、子进程中调用execve函数
  • 总结


前言

本篇文章来讲解Linux中的进程,进程在Linux中是非常重要的一个知识点,掌握好进程是非常重要的。

一、进程的概念

在计算机科学中,进程(Process)是操作系统对正在运行的程序的一种抽象概念。进程可以被看作是一个正在执行的程序的实例。

每个进程都有自己的内存空间(包括代码、数据和堆栈等),它们独立地运行,并且相互之间不会干扰或访问彼此的内存。进程是操作系统进行资源分配和管理的基本单位,它拥有自己的一组系统资源,如处理器时间、内存、文件描述符、打开的文件等。

进程的主要特征包括:

独立性:每个进程都是相互独立的,它们运行在自己的内存空间中,相互之间不干扰,互不影响。

资源拥有:每个进程拥有一组资源,包括处理器时间、内存、文件描述符等。操作系统负责为进程分配和管理这些资源。

执行状态:进程可以处于运行、等待、就绪或终止等不同的执行状态。运行状态表示进程正在执行,等待状态表示进程暂时无法继续执行,就绪状态表示进程已准备好运行但尚未被调度,终止状态表示进程已经完成任务或异常终止。

进程间通信(IPC):进程可以通过各种方式进行通信和协作,如共享内存、文件、管道、消息队列、套接字等方法,实现数据交换和同步。

操作系统通过进程调度算法来管理和调度进程,以便公平地分配系统资源,并确保系统的稳定性和高效性。进程的创建、销毁、通信和同步是计算机系统中重要的组成部分,它们为应用程序提供了一个多任务执行的环境,并支持并发性和多用户操作。

二、进程的生命周期

在Linux中,进程的生命周期包括四个主要阶段:创建(Creation)、运行(Running)、等待(Waiting)和退出(Termination)。下面是对每个阶段的详细描述:

1.创建(Creation): 进程的创建是通过调用 fork 系统调用来实现的。fork 调用会创建一个新的进程(子进程),该子进程是原始进程(父进程)的副本。在创建过程中,子进程获得了父进程的代码、数据和打开的文件描述符等信息。

2.运行(Running): 进程在创建后进入运行阶段。在这个阶段,进程处于活动状态,执行其指定的任务。进程可以占用 CPU 资源并执行相应的操作。进程可能会在执行过程中被抢占或者主动放弃 CPU 资源,以便让其他进程执行。进程可以在用户空间或内核空间运行。

3.等待(Waiting): 进程可以由于某些条件不满足而暂时进入等待状态。在等待状态下,进程停止执行,并将 CPU 资源让给其他进程。进程可以等待多个事件,如等待信号、等待 I/O 完成等。当等待事件发生时,进程将被唤醒并重新进入运行状态。

4.退出(Termination): 进程在完成任务、显式终止或出现异常情况时会退出。进程可以通过调用 exit 系统调用来正常终止,并返回一个退出状态码给父进程。进程的退出时,它的资源(如内存、文件描述符)会被释放,同时系统记录进程的退出状态。

此外,进程的生命周期还受到其他因素的影响,如进程间通信(IPC)和信号处理等。进程可以与其他进程进行通信,共享资源,并根据特定事件或信号做出相应的处理。

需要注意的是,进程的生命周期可能因为特定需求或操作系统策略而有所变化。例如,守护进程(daemon process)通常会在后台长时间运行,而临时进程(ephemeral process)可能只在短暂的时间内存在。此外,进程的创建、运行、等待和退出可以在多个线程执行的上下文中发生,从而创建出多线程的进程。

三、进程树

进程树(Process Tree)是指在一个操作系统中,进程之间的层级关系形成的树状结构。在进程树中,每个进程都有一个父进程,除了根节点(通常是操作系统内核进程或init进程)的父进程为null,其他进程都有且只有一个父进程。而每个进程也可以有多个子进程。

进程树的形成是由于进程的创建和终止操作。当一个进程创建另一个子进程时,子进程成为新创建进程的子节点,而原始进程成为其父进程。这种方式创建了进程的层级结构,以及父子关系。当一个进程终止时,其子进程也可能会随之终止,进一步影响整个进程树。

进程树的一些重要特点和用途包括:

1.层级结构:进程树形成一个明确的层级结构,可以通过查找父进程和子进程来确定进程之间的关联。

2.进程组织:进程树可以将进程有序地组织起来,使操作系统能够有效地管理和跟踪进程的状态和资源。

3.资源分配:进程树中的父进程可以向其子进程分配资源,如文件描述符、内存等。

4.进程终止:当一个父进程终止时,它的子进程可能会成为孤儿进程,被操作系统接管,并由init进程接收,保证整个系统的稳定性。

5.进程通信:进程树中的父子关系可以方便地进行进程间的通信和协作,使用IPC机制进行数据交换和同步。

进程树的可视化表示通常以树状图的形式展现,根节点代表操作系统的内核进程或init进程,其下方的节点表示其他进程,子进程通过连接线与父进程相连接。

总结来说,进程树提供了一个有层级结构的视图,展示了操作系统中进程之间的父子关系。它是理解进程之间相互关联、资源分配和协作的重要工具。

使用ps -ax命令可以查看到进程树:
在这里插入图片描述
在Linux系统中,1号进程通常称为init进程。init进程是所有其他进程的祖先进程,是整个进程树的根节点。它是在系统引导时由内核创建的,负责系统初始化和启动用户空间的服务和进程。

init进程的主要任务是完成系统的初始化,并启动其他用户空间的进程和服务。在系统引导过程中,内核会首先加载并运行init进程。init进程会执行系统的初始化脚本和配置文件,设置系统环境,并启动其他一些关键的进程和服务。它是从内核态切换到用户态的第一个进程。

当init进程启动并完成初始化后,它会进入用户态运行。用户态是指进程在操作系统中以普通用户的权限进行操作和执行任务。在用户态下,进程可以访问用户的资源,执行用户的指令,并与其他用户空间进程进行通信。

四、进程的创建

进程创建的具体步骤:
1.为子进程申请内存空间,并将父进程数据完全复制到子进程空间中。
2.两个进程中的程序执行位置完全一致。

在这里插入图片描述

调用fork()函数后父进程返回子进程PID,子进程返回0。

代码示例:

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

int main(void)
{
    int pid = 0;

    if((pid = fork() != 0))
    {
        printf("praent pid :%d\n", getpid());
    }
    else
    {
        printf("praent pid :%d\n", getppid());
        printf("current pid = %d\n", getpid());
    } 


    return 0;
}

五、一个进程可以执行几个程序?

一个进程其实是可以执行一个或者多个程序的。

在Unix和类Unix系统中,通过调用execve或其他exec系列函数,一个进程可以加载并执行一个新的程序映像,将其替换当前进程的代码和数据,从而实现在同一个进程内执行多个应用程序的效果。execve函数接受一个新的程序文件路径作为参数,将该文件加载到当前进程的地址空间,并且开始执行新的程序。

当进程调用execve函数时,它的地址空间和资源将被新程序替换,包括代码段、数据段、堆栈、文件描述符等。这样,进程会开始执行新程序的入口点,原来的程序会停止执行。

需要注意的是,execve函数本身并不是创建新进程的函数,它是在已有的进程中执行一个新程序。通过在fork创建的子进程中调用execve函数,可以实现替换子进程原有程序的效果。这样,一个进程可以先通过fork创建新的子进程,然后在子进程中使用execve函数执行其他程序。

因此,通过调用execve或其他exec系列函数,一个进程可以在同一个进程内执行多个应用程序,每次调用execve都会替换当前进程的代码和数据,从而实现多个应用程序的执行。

注意:execve系统调用并不会创建新的进程

execve函数原型:

int execve(const char *filename, char *const argv[], char *const envp[]);

参数说明:

filename:要执行的程序文件的路径。

argv:一个空指针结尾的字符串数组,用于传递给执行的程序的命令行参数。数组的第一个字符串通常是程序的名称。

envp:一个空指针结尾的字符串数组,用于传递给执行的程序的环境变量。数组中的每个字符串都是一个形如"key=value"的环境变量设置。
返回值:

成功执行时,execve函数不会返回,因为它会将当前进程替换为新的程序映像。如果发生错误,execve函数返回-1,并设置errno变量来指示具体的错误信息。

execve函数的执行过程如下:

1.execve函数加载指定的程序文件(filename)到当前进程的地址空间。这通常涉及到读取可执行文件的内容到内存中,建立新的程序的代码段、数据段等内存映射。

2.execve函数设置新程序的入口地址,并将参数(argv和envp)传递给新程序,使得新程序可以访问这些参数。

3.execve函数开始执行新的程序,并取代当前进程的执行,新程序开始从入口地址开始执行。

fork.c:

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

#define EXE "test"

int main(void)
{
    int pid = 0;

    char* argv[2] = {EXE, NULL};

    printf("begin\n");

    printf("now pid : %d\n", getpid());

    execve(EXE, argv, NULL);

    printf("end\n");

    return 0;
}

test.c

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

int main(void)
{
    printf("Hello World current pid :%d\n", getpid());

    return 0;
}

这里使用execve函数来加载test这个可执行程序:
执行结果:
在这里插入图片描述
从结果上来看execve函数并不会创建出一个新的进程。

六、子进程中调用execve函数

execve函数常用于在子进程中启动新的程序,例如在使用fork函数创建子进程后,子进程通过调用execve函数来执行其他程序,实现进程的程序替换。这是实现进程间通信和程序的动态加载的重要手段之一。

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

#define EXE "test"

int main(void)
{
    int pid = 0;

    char* argv[2] = {EXE, NULL};

    printf("begin\n");

    printf("now pid : %d\n", getpid());

    if((pid = fork()) != 0)
    {
        //父进程
    }
    else
    {
        //子进程
        execve(EXE, argv, NULL);
    }
   

    printf("end\n");

    return 0;
}

执行结果:
在这里插入图片描述

总结

本篇文章就讲解到这里,下篇文章继续讲解进程的知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/678331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

postgresql源码学习(56)—— explain是如何快速估算pg表行数的

当我们需要大致知道表行数&#xff0c;但又不需要很精确时&#xff0c;可以采用以下方法 一、 统计信息 pg_class.reltuples 最简便的方法是利用pg_class.reltuples&#xff0c;类似oracle的num_rows postgres# select reltuples::numeric from pg_class where relnamepgbenc…

VUE 2X 表单数据过滤器 ⑨

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs收集表单数据过滤器 使用 C o o k i e Cookie Cookie 影响总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹…

【计算机组成原理】RISC-V模型机的有限状态控制器设计

目录 一、RISC-V模型机的目标指令集 二、RISC-V模型机的部件设计 三、运算及传送指令的数据通路设计 四、访存指令的数据通路设计 五、转移类指令的数据通路设计 六、RISC-V模型机控制单元CU的有限状态机设计 一、RISC-V模型机的目标指令集 取指令并译码&#xff1a;根据…

编译原理笔记16:自下而上语法分析(3)构造 DFA、DFA 对下一步分析的指导(有效项目)

目录 由 NFA 用子集法构造 DFA由 LR(0) 项目直接构造识别活前缀的 DFA构造 DFA求拓广文法 GCLOSURE & GO例&#xff1a; 构造 DFA DFA 指导下一步分析有效项目 看了前面的内容&#xff0c;我们已经了解到&#xff1a;分析表和驱动器算法&#xff0c;是 LR 分析器的核心。 …

实训四:索引与视图 - SQL视图(teachingdb数据库)

SQL视图的定义与操纵 第1关&#xff1a;创建视图任务描述相关知识视图的定义创建视图 编程要求测试说明参考代码 第2关&#xff1a;创建视图-练习一任务描述相关知识编程要求测试说明参考代码 第1关&#xff1a;创建视图 任务描述 本关任务&#xff1a;建立计算机系的学生的视…

团体程序设计天梯赛-练习集L1篇⑧

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

C语言scanf/fscanf/sscnaf和printf/fprintf/sprintf的区别

总结 1.scanf/printf 是标准输入输出流函数(键盘、屏幕)。 2.fscanf/fprintf 适用于所有输入输出流(文件、键盘、屏幕…)。 3.sscanf/sprintf 是把格式化的数据写入某个字符串中&#xff0c;从某个字符串中读取格式化的数据。 第一组&#xff1a;scanf/printf scanf/printf是…

Oracle数据库从入门到精通系列之十八:详细总结Oracle数据库核心知识点

Oracle数据库从入门到精通系列之十八&#xff1a;详细总结Oracle数据库核心知识点 一、Oracle数据库核心概念二、Oracle非容器数据库三、Oracle容器数据库四、容器数据库和非容器数据库的区别五、Oracle数据库多租户六、Oracle数据库多租户数据库模型七、Oracle数据库类型八、O…

实训四:索引与视图 - MySQL开发技巧 - 索引

MySQL开发技巧 - 索引 任务描述相关知识索引是什么索引的分类索引的创建和删除查询表中索引 编程要求测试说明代码参考&#xff1a; 任务描述 本关任务&#xff1a;按照要求完成索引的创建。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 索引是什么&#…

【Leetcode60天带刷】day31回溯算法——455.分发饼干 ,376. 摆动序列 , 53. 最大子序和

​ 题目&#xff1a; 455. 分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块…

Android 13(T) - binder阅读(3)- binder相关的类

原先准备在binder阅读&#xff08;3&#xff09;中记录ServiceManager的使用&#xff0c;但是写着写着发现&#xff0c;如果不了解和binder相关的类&#xff0c;那么阅读起来将会由很多困惑&#xff0c;所以就先来记录binder相关的类了。记录完发现特别凌乱…先就这样吧。 1 UM…

【致敬未来的攻城狮计划】打卡3:点亮LED

点亮LED 本文主要参考文章&#xff1a;【致敬未来的攻城狮计划】— 连续打卡第十一天&#xff1a;FSP固件库开发点亮第一个灯。_嵌入式up的博客-CSDN博客 在32阶段我们已经接触过类似做法了。初始化引脚模式&#xff08;可以手动库函数&#xff0c;或者在工具包图形化界面里配…

实训四:索引与视图 - MySQL开发技巧 - 视图

MySQL开发技巧 - 视图 任务描述相关知识视图的定义创建视图操作视图删除视图 编程要求测试说明参考代码 任务描述 本关任务&#xff1a;通过学习视图&#xff0c;创建一个单表视图和一个多表视图。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 视图的定义…

工地扬尘智能监测系统 yolov7

工地扬尘智能监测系统通过yolov7网络算法模型技术&#xff0c;实时监测工地施工中的扬尘情况。工地扬尘智能监测系统利用AI视频智能分析技术&#xff0c;并将数据传输到数据中心进行分析。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队希望它能够同时支…

数据库管理-第八十四期 X10M来了(20230624)

数据库管理 2023-06-24 第八十四期 X10M来了1 Intel -> AMD2 PMEM -> XRMEM3 DDR4 -> DDR54 Flash cards总结 第八十四期 X10M来了 在第四十三期的时候&#xff0c;我曾经憧憬过Exadata X10M的到来&#xff0c;Oracle于6月22日正式公布Exadata X10M系列。其实5月已经…

chatgpt赋能python:Python在电气行业中的应用——从数据分析到自动化控制

Python在电气行业中的应用——从数据分析到自动化控制 介绍 Python语言作为一种高级编程语言&#xff0c;越来越受到电气行业的关注。随着互联网、物联网以及大数据时代的到来&#xff0c;电气行业需要将传统的工业控制与现代化的数据分析、智能决策等技术相结合&#xff0c;…

Java——《面试题——Dobbo篇》

前文 java——《面试题——基础篇》 Java——《面试题——JVM篇》 Java——《面试题——多线程&并发篇》 Java——《面试题——Spring篇》 Java——《面试题——SpringBoot篇》 Java——《面试题——MySQL篇》​​​​​​ Java——《面试题——SpringCloud》 目录…

springboot+mybatis笔记学习

1.环境搭建 1.引入pom依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version> </dependency> <dependency><groupId>org…

人工智能(2):机器学习算法分类

根据数据集组成不同&#xff0c;可以把机器学习算法分为&#xff1a; 监督学习无监督学习半监督学习强化学习 1 监督学习 定义&#xff1a; 输入数据是由输入特征值和目标值所组成。 函数的输出可以是一个连续的值(称为回归&#xff09;&#xff0c;或是输出是有限个离散值&…

07- c语言字符串 (C语言)

一 字符串的定义及基本使用 1、什么是字符串 被双引号引用的字符集合&#xff01;例如&#xff1a;”hello” 、”world”&#xff0c;或者是以 \0 结尾的字符数组&#xff01;&#xff01;&#xff01; 比如&#xff1a;char ch[] {h, e, \0} 注意&#xff1a;”hello” 中…