初识 Linux 进程

news2024/11/18 14:53:38

问题

strace 输出中的 execve(...) 究竟是什么?

进程生命周期

操作系统内部定义了进程的不同状态

Linux 进程基本概念

进程是 Linux 任务的执行单元,也是 Linux 系统资源的分配单元

每个 Linux 应用程序运行后由一个或多个进程构成

每个 Linux 进程可以执行一个或多个程序

Linux 进程有多种不同状态 (即:Linux 进程有不同的活法)

Linux 进程生命周期

可中断状态表示进程可以接收到内核给它发出的信号,不可中断状态表示进程不接收内核给它发出的信号

僵尸状态表示进程的生命周期已经结束了,但内核还残留着这个进程的资源

我们查看下当前的命令行所运行的进程

ps ax 命令查看每个运行进程的信息,grep "pts/2" 用来筛选当前命令行所运行的进程

第一列是每个进程的进程号,第三列是每个进程的状态

下图包含了进程的状态信息

S 表示该进程处于可中断的阻塞状态,R 表示该进程处于运行或就绪状态

s 表示该进程是会话组长,+ 表示该进程在前台进程组里

Linux 进程必知必会

每一个进程都有一个唯一的标识 (PID)

每个进程都是由另一个进程创建而来 (即:父进程)

getpid() 用于获取当前进程的进程号,getppid() 用于获取当前进程的父进程号

Linux 进程树

整个 Linux 系统的所有进程构成一个树状结构

树根由内核自动创建即:IDLE (PID = 0)

系统中的第一个进程是 init / systemd (PID = 1)

0 号进程创建 1 号进程,1 号进程负责完成内核部分初始化工作

1 号进程加载执行初始化程序,演变为用户态 1 号进程

我们来查看下当前命令行进程的进程树

pstree 是查看当前系统进程树的命令,-p 参数会展示出每个进程的 pid,-s 参数表示指定查看某个进程,$$ 代表当前进程的 pid 

Linux 进程创建

pid_t fork(void); 

  • 通过当前进程创建新进程,当前进程为父进程,新进程为子进程

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

  • 在当前进程中执行 pathname 指定的程序代码

fork() 的工作方式

为子进程申请内存空间,并将父进程数据完全复制到子进程空间中

两个进程中的程序执行顺序完全一致 (fork() 函数调用位置)

不同之处:

  • 父进程:fork() 返回子进程 pid
  • 子进程:fork() 返回0
  • 通过 fork() 返回值判断父子进程,执行不同代码

fork() 初探

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

static int g_global = 0;

int main()
{
    int pid = 0;
    
    printf("Hello World!\n");
    printf("current pid = %d\n", getpid());

    if( (pid = fork()) > 0 )
    {
        g_global = 1;
        
        usleep(100);
        
		printf("child pid = %d\n", pid);
        printf("%d g_global = %d\n", getpid(), g_global);
    }
    else
    {
        g_global = 10;
        
		printf("parent pid = %d\n", getppid());
        printf("%d g_global = %d\n", getpid(), g_global);
    }
    
    return 0;
}



程序运行结果如下图所示

fork() 前,打印当前进程的 pid 为 6619

fork() 后,当前进程会创建出和自己一样的子进程,随后,父进程和子进程会同时运行,通过 fork() 的返回值可以判断出父进程和子进程,由于父进程 sleep 100us,所以子进程会先打印,然后父进程再打印

思考

如何理解 "每个 Linux 进程可以执行一个或多个程序"?

每个 Linux 进程 可以读取一个或多个程序的代码和数据,从而来执行程序

execve(...) 的工作方式

根据参数路径加载可执行程序

通过可执行程序信息构建进程数据,并写入当前进程

将程序执行位置重置到入口地址处 (即:main())

execve(...) 将重置当前进程空间 (代码 & 数据) 而不会创建新进程

execve 初探

helloworld.c

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

int main()
{
    printf("exec = %d, %s\n", 
                   getpid(), "Hello World!");
    return 0;
}


test.c

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

#define EXE "helloworld.out"

int main()
{
    char* args[] = {EXE, NULL};
    
    printf("begin\n");
    
    printf("pid = %d\n", getpid());  
    
    execve(EXE, args, NULL);
    
    printf("end\n");
    
    return 0;
}


我们将 helloworld.c 编译为 helloworld.out,将 test.c 编译为 test.out,来查看运行结果

execve 不会创建新的进程,而是将当前进程的进程数据替换为 helloworld.out 的进程数据,并执行,所以执行完 helloworld.out后就结束了,不会打印 end 

我们可以 fork 子进程来执行 execve,这样当前进程的进程数据就不会被替换了

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

#define EXE "helloworld.out"

int create_process(const char* pathname, char* const argv[])
{
	int ret = 0;
	
	if((ret = fork()) == 0)
	{
		execve(pathname, argv, NULL);
	}
	
	return ret;
}

int main()
{
    char* args[] = {EXE, NULL};
    
    printf("begin\n");
    
    printf("pid = %d\n", getpid());  
    
	printf("child pid = %d\n", create_process(EXE, args));
    
    printf("end\n");
    
    return 0;
}


程序执行结果如下图所示

通过 fork 子进程的方式来执行 execve,这样父进程的数据不会被替换,父进程成功打印出 end

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

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

相关文章

对称密钥【密码学】(四)

一、前言 在使用单向散列函数校验数据完整性时&#xff0c;需要保证原始的散列值不能被更改。 因此&#xff0c;在很多场景下&#xff0c;我们并不能仅仅通过单向散列函数来解决完整性问题&#xff0c;还需要其他技术来解决这个问题&#xff0c;如加密技术。 本篇博客就来介绍…

CloudFlare系列--使用第三方来自定义CSDN的IP(蓝精灵)

原文网址&#xff1a;CloudFlare系列--使用第三方来自定义CSDN的IP(蓝精灵)_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍CloudFlare的CDN如何自定义第三方IP。 概述 CloudFlare官网接入域名的方式只能是 NS 接入&#xff0c;这样默认DNS服务器只能改为CloudFlare的DNS服…

从零开始Vue项目中使用MapboxGL开发三维地图教程(七)创建一个自动旋转的地球、添加一个3D模型、实现在两个地图之间滑动和同步来比较两个地图

目录 1、创建一个自动旋转的地球地图2、添加一个3D模型3、一个页面创建两个底图之间滑动 1、创建一个自动旋转的地球地图 实现功能&#xff1a;地球仪和camera动画结合在一起&#xff0c;创建旋转行星效果。 实现思路&#xff1a;通过在动画结束时调用easeTo&#xff0c;旋转…

软考A计划-网络工程师-IP,TCP,UDP,ICMP报头

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

YOLOv5/v7 添加注意力机制,30多种模块分析⑤,SOCA模块 ,SimAM模块

目录 一、注意力机制介绍1、什么是注意力机制&#xff1f;2、注意力机制的分类3、注意力机制的核心 二、SOCA模块1、SOCA模块的原理2、实验结果3、应用示例 三、SimAM模块1、SimAM模块的原理2、实验结果3、应用示例 大家好&#xff0c;我是哪吒。 &#x1f3c6;本文收录于&…

Vue 面试题

一、对于MVVM的理解&#xff1f; MVVM 是 Model-View-ViewModel 的缩写。 1、Model 代表数据模型&#xff0c;也可以在Model中定义数据修改和操作的业务逻辑。 2、View 代表UI 组件&#xff0c;它负责将数据模型转化成UI 展现出来。 3、ViewModel 监听模型数据的改变和控制…

【分布式系统】分布式唯一ID生成方案总结

目录 UUID实现 数据库生成IDsegment号段模式美团Leaf-segment号段模式Redis生成ID实现 zookeeper生成ID实现 snowflake雪花算法实现 Leaf-snowflake雪花算法百度UidGenerator滴滴TinyID双号段缓存多DB支持tinyid-client 参考 UUID 基本方法之一。 UUID(Universally Unique Id…

Java阿里巴巴代码规范

目录 1 编程规约1.1 方法参数类型必须一致&#xff0c;不要出现自动装箱拆箱操作1.1.1 反例1.1.2 正例 1.2 SimpleDateFormat是线程不安全的1.2.1 反例1.2.2 正例 1.3 使用equals方法应该注意空指针1.3.1 反例1.3.2 正例 2 异常日志2.1 事务场景中如果异常被被捕获要注意回滚2.…

2023 年最适用于工业物联网领域的三款开源 MQTT Broker

MQTT 最初作为一种轻量级的发布/订阅消息传递协议而设计&#xff0c;如今已经成为工业物联网&#xff08;IIoT&#xff09;和工业 4.0 发展的重要基础。它的意义在于实现了各类工业设备与云端的无缝连接&#xff0c;促进了运营技术&#xff08;OT&#xff09;和信息技术&#x…

MySQL----事物与存储引擎

文章目录 一、事务介绍1.1 MySQL 事务的概念1.2 事务的ACID特点原子性一致性隔离性持久性 1.3 事务之间的相互影响1.4 设置隔离级别1.5事务控制语句1.6使用 set 设置控制事务 二、存储引擎介绍2.1查看系统支持的存储引擎2.2 修改存储引擎2.3InnoDB行锁与索引的关系 一、事务介绍…

Windows VMware安装RockyLinux9

前言&#xff0c;今天用虚拟机安装rockyLinux时碰到了一些坑&#xff0c;要么时无法联网&#xff0c;要么是无法使用ssh链 接&#xff0c;在这里记录下 准备工作 1. VMware Workstation 17 Pro 2. RockyLinux9.2阿里镜像站&#xff0c;这里无选择了最小版本Rocky-9-latest-x86…

我的内网渗透-Empire模块的使用(宏病毒主要)

目录 stager模块&#xff08;payload&#xff09; 宏病毒 理解 在word中的设置 宏病毒代码 运行 保存 监听模块 提权模块 持久化模块 stager模块&#xff08;payload&#xff09; 常用的windows类型windows/launcher_bat #生成bat类型&#xff0c;还是可以用的。但…

GPT学习笔记-Enterprise Knowledge Retrieval(企业知识检索)--私有知识库的集成

openai-cookbook/apps/enterprise-knowledge-retrieval at main openai/openai-cookbook GitHub 终于看到对于我解决现有问题的例子代码&#xff0c;对于企业私有知识库的集成。 我对"Retrieval"重新理解了一下&#xff0c;源自动词"retrieve"&#xf…

【Matlab】LM迭代估计法

简介 在最近的传感器校准算法学习中&#xff0c;有一些非线性的代价函数求解使用最小二乘法很难求解&#xff0c;使用LM算法求解会简单许多&#xff0c;因此学习了一下LM算法的基础记录一下。 LM 优化迭代算法时一种非线性优化算法&#xff0c;可以看作是梯度下降与高斯牛顿法…

【linux kernel】linux media子系统分析之media控制器设备

文章目录 一、抽象媒体设备模型二、媒体设备三、Entity四、Interfaces五、Pad六、Link七、Media图遍历八、使用计数和电源处理九、link设置十、Pipeline和Media流十一、链接验证十二、媒体控制器设备的分配器API 本文基于linux内核 4.19.4&#xff0c;抽象媒体设备模型框架的相…

day11_类中成员之方法

成员变量是用来存储对象的数据信息的&#xff0c;那么如何表示对象的行为功能呢&#xff1f;就要通过方法来实现 方法 概念&#xff1a; 方法也叫函数&#xff0c;是一个独立功能的定义&#xff0c;是一个类中最基本的功能单元。把一个功能封装为方法的目的是&#xff0c;可…

信息安全原理与技术期末复习(如学)

文章目录 一、前言&#xff08;开卷打印&#xff09;二、选择题三、简答题1、简述端口扫描技术原理&#xff08;P136&#xff09;2、分组密码工作方式&#xff08;P61&#xff09;3、木马攻击&#xff08;P176&#xff09;4、消息认证码&#xff08;P84&#xff09;5、非对称密…

华为OD机试真题B卷 JavaScript 实现【删除字符串中出现次数最少的字符】,附详细解题思路

一、题目描述 删除字符串中出现次数最少的字符&#xff0c;如果多个字符出现次数一样则都删除。 二、输入描述 一个字符串。 三、输出描述 删除字符串中出现次数最少的字符&#xff0c;如果多个字符出现次数一样则都删除&#xff0c;如果都被删除 则换为empty。 四、解题…

机器视觉初步5-1:图像平滑专题

在计算机视觉领域&#xff0c;图像平滑处理是一个重要的任务&#xff0c;用于降低噪声&#xff0c;提高图像质量。常见的图像平滑算法有均值滤波、中值滤波、高斯滤波等。本文将介绍这些算法的原理&#xff0c;并分别给出使用Python与Halcon实现的代码。&#xff08;当前版本&a…

libface 人脸检测

于老师的项目地址GitHub - ShiqiYu/libfacedetection: An open source library for face detection in images. The face detection speed can reach 1000FPS. 关于如何使用&#xff0c;于老师写得很清楚&#xff1a; 测试代码 CMakeList.txt 和 三个face开头的cpp文件都是于老…