[linux]程序和进程浅析

Linux 程序、进程和线程 程序、进程和线程一、程序、进程和线程的概念程序和进程的差别Linux环境下的进程进程和线程二、进程产生的方式进程号进程复制fork()函数system()函数方式进程执行exec()函数系列所有用户态进程的产生进程init三、进程间通信和同步半双工管道命名管道消息队列消息队列的一个例子信号量共享内存信号四、 Linux下的线程多线程编程实例Linux下线程创建函数pthread_create()线程的结束函数pthread_join()和函数pthread_exit()线程的属性线程间的互斥线程中使用信号量 阅读详情

我们都运行过程序,但是程序到底是什么,程序是如何运行的?

程序只是一段可执行的代码文件,通俗的说在linux上就是文件。

然后程序运行时就被称为进程,即进程是运行状态的程序。

程序储存了一系列信息的文件,这些信息描述如何在运行时创建一个进程。包含如下:

二进制格式标示:描述可执行文件的元信息,内核利用该信息解释文件中的其它信息。

机器语言指令:对程序进行编码。

程序入口地址:标示程序开始执行的起始指令位置。

数据:程序所包含变量的初始值和程序所使用的字面常量值。

符号表和重定位表:描述程序中函数和变量的位置及位置。

共享库和动态链接信息:列出程序运行时需要使用的共享库以及加载共享库的动态链接器的路径名。

其它信息:描述如何创建进程。


内核在加载程序的时候会为其分配一个唯一标识符即进程号,linux内核限制进程号需要小于等于32767.

每当创建一个进程的时候内核会顺序将下一个可用进程号分配给其时候。

当进程号大于32767时,内核会重置进程号计数器。然后从下位开始重新分配。

因为内核会运行一些守护进程和系统进程,所以一般会预留一些进程号给这些程序使用,所以一般从300开始重置。就类似于端口号1-1024之间时不会被分配给程序。

在64位系统中进程号可以更大。


每个进程都有一个父进程,除了一个叫做init的系统进程(进程号为1),该进程由内核负责初始化

该进程是所有进程的始祖,如果一个用户程序启动时,那么由init负责其初始化。

可以使用pstree来查看进程树

父进程和子进程呈现出一种树状关系,这是在mac os下执行pstree的结果,mac os下的初始进程为launchd等同于init



进程的内存布局:

进程内存由多部分组成:

text(文本段):程序代码

data:包含了初始化的全局数据和静态数据

bss:未初始的全局数据和静态数据

heap:用户分配的内存区 由 malloc分配

stack:包含栈帧,每个栈帧中存储了函数的局部变量。



注意这里说的是虚拟地址,实际进程的地址空间并不是真正的物理地址空间,而是采用了虚拟空间映射产生的。

在linux32位操作系统中,会为每个进程分配4G的独立内存空间,这里就出现一个问题,计算机的虚拟内存只有4G那么多个进程的话不是早被用光了

解决这一问题的方式通过页表映射到实实际的物理内存中去。

在上表中,进程的内存空间按照text,data,bss,heap,stack分布有低到高分配地址空间。但是只增长到0xC00000000,这是因为最后的一部分内存被分配给了内核。0~3G内存被分配给用户使用称为用户内存,3~4G内存为系统内核内存区。

图中非灰色部分都会创建页表来管理虚拟内存。


系统定义了三个全局符号可以获得text,data,bss段结束处下一字节地址。

extern etext,edata,end;

#include <stdio.h>
/*
*	etext:end of text address
*	edata:end of init data address
*	end: end of uninit data address
*/
extern char etext, edata, end;

int doCal(int x) {
	return square(x, x);
}

int square(int x, int y) {
	return x * x;
}


int main(int argc,char** argv) {
	int i = 2;
	printf("calculate:%d\n", doCal(i));
	printf("etext:%ld\tedata:%ld\tend:%ld\n",(unsigned long)&etext,
						(unsigned long)&edata,(unsigned long)&end);
	return 0;
}

结果如下:

calculate:4
etext:4195917	edata:6295616	end:6295624

为了进行对比,我们增加bss中的未初始化变量的个数,可以看到,确实是增长了的。

#include <stdio.h>
/*
*	etext:end of text address
*	edata:end of init data address
*	end: end of uninit data address
*/
extern char etext, edata, end;

int doCal(int x) {
	return square(x, x);
}

int square(int x, int y) {
	return x * x;
}

int a = 0;
static int b = 0;
int d;
static int e;


int main(int argc,char** argv) {
	int i = 2;
	printf("calculate:%d\n", doCal(i));
	printf("etext:%ld\tedata:%ld\tend:%ld\n",(unsigned long)&etext,
						(unsigned long)&edata,(unsigned long)&end);
	return 0;
}

结果:

calculate:4
etext:4195917	edata:6295616	end:6295640

这里看到edata并没有增长,但是我明确的给其赋值为0,所以这里就有一个概念即初始赋值0等同于未初始化对于全局变量。

同时end增长了16 考虑到 int类型的字长为32位,即4byte,那么4 * 4 = 16;校验正确。


这里再稍做改动:

#include <stdio.h>
/*
*	etext:end of text address
*	edata:end of init data address
*	end: end of uninit data address
*/
extern char etext, edata, end;

int doCal(int x) {
	return square(x, x);
}

int square(int x, int y) {
	return x * x;
}

int a = 3;
static int b = 3;
int d;
static int e;


int main(int argc,char** argv) {
	int i = 2;
	printf("calculate:%d\n", doCal(i));
	printf("etext:%ld\tedata:%ld\tend:%ld\n",(unsigned long)&etext,
						(unsigned long)&edata,(unsigned long)&end);
	return 0;
}
结果如下:

calculate:4
etext:4195917	edata:6295624	end:6295640
这里我给a,b明确赋值为3,那么这些值就会成为初始化数据段的内容,2 * 4 = 8 结果也符合校验。


这里我在给正文段text进行一些改变:

#include <stdio.h>
/*
*	etext:end of text address
*	edata:end of init data address
*	end: end of uninit data address
*/
extern char etext, edata, end;

int doCal(int x) {
	return square(x, x);
}

int square(int x, int y) {
	return x * x;
}

int a = 3;
static int b = 3;
int d;
static int e;


int main(int argc,char** argv) {
	int x = 1;
	int y = 1;
	int z = 1;
	int i = 2;
	printf("calculate:%d\n", doCal(i));
	printf("etext:%ld\tedata:%ld\tend:%ld\n",(unsigned long)&etext,
						(unsigned long)&edata,(unsigned long)&end);
	return 0;
}
结果如下:

calculate:4
etext:4195933	edata:6295624	end:6295640
这里正文段也是增长了,所以符合预期期望。


这里再来介绍一下栈,这里的栈是用户栈,栈里保存着程序的栈帧,栈帧包含变量信息。


就像之前的那个程序一样,当程序开始执行时,开始了一个main的函数调用,然后调用到doCal函数,然后doCal调用到了square函数。

这个过程中,栈是增长的,这里的增长只是逻辑上的增长,实际物理地址是减小的。

square调用结束之后,那么栈就将square的栈帧出栈。直到main函数也出栈,至此,程序运行结束。





这里说到的虚拟内存管理技术是基于以下两个局部性的基础:

1.空间局部性:程序倾向于访问最近访问过的内存地址附近的内存,因为指令是顺序的。

2.时间局部性:程序倾向于不久的将来再次访问最近访问过的内存,因为循环语句。

正是因为局部性特征,所以即是仅有部分地址存在于ram中,也依然可以执行。


这里说的物理内存和RAM都是指的的内存条上的概念

虚拟内存的规划之一就是将每个程序所使用的内存分割成小的,固定大小的“页”(page)单元,同时也将RAM划分成与虚拟页尺寸大小相同的页帧,程序当前正在执行的部分构成的驻留页帧,称之为驻留集。而未使用的页则保存在交换区。若进程要访问的内存并未驻留在物理内存中,那么将会从硬盘中载入到内存。


所以为了管理这种结构,内核需要为每一个进程维护一张页表,该页表中的每一页表示程序的虚拟内存空间位置,要么是在RAM中,要么是在硬盘中。

虚拟内存管理使得进程与RAM物理地址隔离,这就带来了以下好处:

1.进程都有独立的内存空间,都可以使用到完整的内存空间,进程与进程之间,内存与内核之间隔离。

2.适当情况下,两个进程可以共享内存。

3.无需关注实际的RAM物理布局,专注于开发。

4.驻留在内存中的仅是程序的一部分,可以加速程序加载和运行。



Linux——这一篇搞定进程和程序! 一文详解进程与程序! 阅读详情

相关推荐

VS Code配置MASM32汇编环境:从安装到调试的完整指南

本文提供了一份详尽的指南,教你如何在VS Code中配置MASM32汇编开发环境,实现从安装、环境变量设置到编写、编译和调试32位Windows汇编窗口程序的完整工作流。通过集成现代编辑器的便利性与经典汇编工具链,旨在降低学习门槛,提升底层开发效率。

nn3456的博客 483

【Linux入门】进程概念(超详解,建议收藏)

系统中,可以存在大量进程的 当我们的电脑开机的时候,启动的第一个进程是操作系统(os),而os要对之后运行起来的进程进行管理工作(进程管理)。 操作系统如何进行进程管理?? (先描述,在组织)、 当有大量程序加载到内存中时,就如同系统中同时出现大量进程,操作系统会增添大量的PCB对这些进程进行描述,并用链表的方式对PCB组织起来。 1、标示符: 前台进程,只能有一个前台进程 +& 在后台跑 +表示前台还是后台 2、优先级 什么是优先级? 谁先谁后拿到某种资源 为什么要有优先级? 资源有限。 CPU

qq_53505979的博客 8699

基于ESP32-WROOM的智能蓝牙电压电流监测与远程控制系统设计

本文介绍了基于ESP32-WROOM的智能蓝牙电压电流监测与远程控制系统设计。该系统集成了INA219传感器和OLED显示屏,通过蓝牙实现无线数据传输和远程控制,适用于智能家居能耗监控和工业设备管理,具有成本低、精度高、功耗优化等优点。

qsc901234的博客 203

Linux之进程

进程是程序的一次执行。进程是可以并行执行的计算。进程是一个程序与其使用的数据在处理机上顺序执行时发生的活动。进程是程序在一个数据集合上的运行过程。它是系统进行资源分配和调度的一个独立单位作业控制--- 一个命令行功能,允许一个shell实例来运行和管理多个命令,Shell的一个特性,使用户能在多个独立进程间进行切换命令及作用命令作用cmd&该命令在后台运行Ctrl+d终止一个正在前台运行的进程(含有正常含义)Ctrl+c终止一个正在前台运行的进程(含有强行含义)

qq_57289939的博客 3221

HTML5期末大作业:关于家乡介绍的HTML网页设计——郑州美景HTML+CSS(5页) 学生DW家乡介绍网页设计作业成品 web课程设计网页规划与设计

HTML5期末大作业:我的家乡——郑州美景HTML+CSS(5页) 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业, 可满足大学生网页大作业网页设计需求, 喜

qq_365392777 1万+

HTTPS接口测试翻车实录:为什么浏览器能访问而curl报证书错误?

本文深入分析了HTTPS接口测试中浏览器访问正常而curl报证书错误的典型问题。通过对比浏览器、Postman和curl的工具行为差异,结合Nginx日志与Wireshark抓包,揭示了问题根源在于网络架构中HTTPS请求被意外“降级”为HTTP传输,导致SSL握手失败。文章重点探讨了curl工具严格验证机制暴露的`Peer's Certificate issuer is not recognized`错误,并提供了网络配置修正方案与标准化测试流程。

u9v0w的博客 278

Linux —— 进程概念超详解!

本篇文章从最基本的操作系统理论出发,映射到Linux系统上。主要介绍的有什么是进程、进程是如何被管理的、进程状态,以及描述Linux对于进程是怎么做的。还详细介绍了僵尸进程、孤儿进程、父子进程、进程优先级以及并发、环境变量等基本概念。只要大家从头到尾仔细看,就一定能有所收获!

weixin_59913110的博客 6048

vue项目表格甘特图开发

🧩 甘特图可以管理项目进度,生产进度等信息,管理者可以更直观的查看内容。

qq_35946021的博客 991

【Linux:进程】

进程相关详述

qq_46076785的博客 1569

QtQuick QML教程(2):qml语法介绍

​ qml一个普通的文本文件,后缀是.qml, 一个qml文件主要由两部分组成:(1) import语句 :这个就像C++中的头文件, 使用 import 导入qml需要的相关模块,可以查询Qt文档进行导入,注意每个版本的Qt模块声明可能都不同,相比于QWidget项目,QtQuick的变动是很大的;(2) QML对象树 :根对象是Window, 然后可以在Window中添加各种控件,例如按钮,文本,菜单等。

琅嬛福地 550

ACS运动控制器编程语言

ACS运动控制器采用SPiiPlusLanguage(SPL)作为核心编程语言,该语言基于C语法设计,内置丰富的运动控制指令,支持点位运动、插补等复杂控制。控制器提供专用开发工具SPiiPlusManager和ACSStudio,支持图形化编程与调试。同时兼容TCP/IP、EtherCAT等多种扩展接口,便于与上位机或PLC集成。使用时需注意实时性优先级、轴参数匹配等关键事项。官方文档和示例程序为开发者提供了完善的学习资源。

StevenChen的博客 614

<Linux> 进程

进程有关概念、如何创建进程、进程状态、环境变量详解、进程优先级、程序地址空间、如何控制进程以及如何替换进程

weixin_61522065的博客 4302

第8章-认知工程:构建Agent的认知飞轮与自进化《万物皆映射》

认知架构(Cognitive Architecture)是一个系统组织和运行其认知过程的整体设计。对人类而言,认知架构是大脑的结构和功能组织方式;对 AI Agent 而言,认知架构是它处理信息、做出决策、学习经验的系统设计。固定映射 vs 进化映射维度固定映射 Agent进化映射 Agent知识静态(训练时确定)动态(持续积累)策略固定(设计时确定)自适应(经验驱动)工具预定义自主发现/创建错误处理硬编码规则从错误中学习能力边界固定持续扩展在认知工程中,技能。

AI天才研究院 104

Linux 进程调度浅析

进程调度含义 进程调度决定了将哪个进程进行执行,以及执行的时间。操作系统进行合理的进程调度,使得资源得到最大化的利用。 在单片机上,常常使用的方式是:系统初始化----&gt;while(1){}。(当然,单片机也可以跑类似 FreeRTOS,也可以有进程切换) 在带操作系统的 CPU 上跑的逻辑是,允许多个进程(其实就是程序) ”同时” 跑。比如,你可以在操作鼠标的同时,进行音乐播放,文字...

StephenZhou 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Linux进程控制【进程程序替换】

子进程在被创建后,共享的是父进程的代码,如果想实现自己的逻辑就需要再额外编写代码,为了能让子进程执行其他任务,可以把当前子进程的程序替换为目标程序,此时需要用到Linux进程程序替换相关知识

北 海的博客 5078

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

linux进程调度浅析

操作系统要实现多进程,进程调度必不可少。       进程调度是对TASK_RUNNING状态的进程进行调度(参见《linux进程状态浅析》)。如果进程不可执行(正在睡眠或其他),那么它跟进程调度没多大关系。       所以,如果你的系统负载非常低,盼星星盼月亮才出现一个可执行状态的进程。那么进程调度也就不会太重要。哪个进程可执行,就让它执行去,没有什么需要多考虑的。       反之,如

ctthuangcheng 4325

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

[Linux] Linux 进程程序替换

在之前,我们已经学习了什么是进程的创建,退出,等待,以及有关进程地址空间的问题。接下来的进程程序替换依然是属于进程控制的范畴,但是在实际应用中,是非常重要的一种技术。本文不直接像书本上一样,一开始就说一大堆概念,让人摸不清头脑,而是现观察进程程序替换的现象,然后再从现象中在进一步了解进程程序替换。进程程序替换有一些专门(对口)的函数,我们可以通过man手册查到其中的一个函数:int main()return 0;

石墨博客 1879

【Linux】进程程序替换

进程程序替换顾名思义,就是将其他程序替换过来继续执行,主要是通过exec* 这类函数来帮助我们替换,直接来学这类函数。刚刚好我们一共提到了6个函数,其实这些函数都是C语言封装的函数,这些函数都是由一个叫execve的函数封装而来。execve这个函数是系统调用接口,感兴趣的可以自己查一下。

2301_79181030的博客 2155

Linux程序和进程的关系

今天与大家讲一下进程和程序的关系,连带讲一下linux中的部分操作。 程序和进程的关系1.程序2.进程3.静态查看进程统计信息ps命令:ps aux命令ps - elf4.动态查看进程统计信息top5.查看进程信息pgrep6.查看进程信息pstree7.进程的启动方式8.进程的前后台调度9.终止进程的运行Ctrl+C组合键kill、killall命令pkill命令10.计划任务管理at11.计划任务管理crond管理crontab计划任务12.crontab任务配置的格式run-parts工具 1.程序

肥猫警长的博客 2171

【Linux】—— 进程程序替换

详解进程的程序替换

m0_56069910的博客 1050

Linux程序与进程

2)deb包:.deb为后缀,debian系列操作系统(debian,Ubuntu,kali)主要的软件包封装格式,已经做好默认设置,如安装路径,配置文件存放路径等,需要手动的解决依赖关系。1)rpm包:.rpm为后缀,红帽系列操作系统(RedHat,CentOS,OpenSUSE)主要的软件包封装格式,已经做好默认设置,如安装路径,配置文件存放路径,需要手动的解决依赖关系。:是运行着的程序,是操作系统执行的基本单位,是程序运行的过程, 是动态的,是有生命周期及运行状态的。rpm -qc 软件名;

Mrdaliang的博客 827

Linux系统程序和进程

注:若通过 top 排名工具发现某个进程 CPU 占用率非常高,需要终止该进程的运行,可以在 top 操作界面中按 k 键,然后在列表上方将会出现“PID to signal/kill [default pid = 3180]:” 的提示信息,根据提示输入指定进程的 PID 号并按 Enter 键, 出现“Send pid 5597 signal [15/sigterm]”的二次确认的提示信息,然后按Enter 键确认即可终止对应的进程。-a:显示当前终端下的所有进程信息,包括其他用户的进程。

yangye2424637628的博客 864

进阶学习——Linux系统——程序和进程

程序与进程的区别;进程管理命令ps、top、pgrep、pidof、pstree、lsof、Vmstat、free、lostat、iotop、iftop、UPtime、mpstat、dstat、Webmin、&、jobs、fg、bg、kill、killall、pkill、at、Crontab

一坨小橙子的博客 1553

linux进程状态浅析

众所周知,现在的分时操作系统能够在一个CPU上运行多个程序,让这些程序表面上看起来是在同时运行的。linux就是这样的一个操作系统。       在linux系统中,每个被运行的程序实例对应一个或多个进程。linux内核需要对这些进程进行管理,以使它们在系统中“同时”运行。linux内核对进程的这种管理分两个方面:进程状态管理,和进程调度。本文主要介绍进程状态管理,进程调度见《linux进程调度

ctthuangcheng 2861

【Linux系统】进程控制(进程创建、进程终止、进程等待 和 进程程序替换)

本文介绍了Linux进程管理的核心概念。在进程创建方面,详细解析了fork系统调用的工作原理,包括父子进程共享代码数据的机制、写时拷贝技术(仅修改时才复制物理内存页)及其性能优势。进程终止部分阐述了退出码机制,系统化整理了0-255的退出码含义及其应用场景(如0表示成功,127为命令未找到),并提供了查看退出码的echo $?实用命令。文章通过代码示例和图表清晰地展示了进程创建与终止的关键技术原理。

无限进步!!! 1515
上一篇: [linux]文件描述符再探
下一篇: [Spring]new ClassPathXmlApplicationContext("application.xml")做了些什么
HeapStackk
博客等级 码龄12年 11粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值