Linux C嵌入式---进程

一、进程与程序

程序链接加载和传参

c语言从main函数执行。事实上操作系统下的应用程序在运行main函数前需要执行一段引导代码,由引导代码调用main函数

编译链接时,由链接器引导代码链接到我们的应用程序当中,一起构成最终的可执行文件。

程序运行需要操作系统中的加载器(一段程序),执行程序时,加载器负责将这段程序加载到内存中执行。

终端执行程序,命令行参数由shell进程逐一解析,shell会将这些参数传递给加载器,加载器加载应用程序时会将其传递给应用程序引导代码,当引导程序调用main函数时将参数一并传递。

程序结束

就是进程终止,包括正常终止和异常终止

正常终止:

  • return返回

  • exit(),exit(),Exit()调用

异常终止:

  • abort()

  • 接收到特殊信号,比如SIGKILL

注册进程终止处理函数

atexit()

注册一个进程在正常终止时要调用的函数

int atexit(void (*function)(void));

返回值:成功返回0,失败返回非0

程序使用_exit()和 _Exit()退出不会调用终止处理函数

进程:进程就是一个可执行程序的实例,可执行程序被运行

进程时一个动态过程,不是静态文件,是程序的一个运行过程,当应用程序被加载到内存中运行之后它就是一个进程,程序运行结束意味着进程终止,这就是进程的一个生命周期。

进程号

Process ID(PID),一个正数,用于唯一标识系统中的某一个进程。可以用ps命令查看进程号

1、getpid函数

获取本进程的进程号

pid_t getpid(void);

2、getppid函数

获取父进程的进程号

pid_t getppid(void);

二、进程的环境变量

每个进程都有一组相关的环境变量,环境变量以字符串的形式存储在一个字符串数组列表中,该数组也叫环境列表。

每个字符串都以"name = value"形式定义,环境变量是名称-值的成对集合。

终端可以用env命令查看shell进程的所有环境变量

export添加环境变量 eg:export LINUX_APP=123456

删除环境变量 eg: export -n LINUX_APP

应用程序中获取环境变量

进程的环境变量是从父进程中继承过来的

环境变量存放在一个字符串数组中,应用程序中,通过全局变量environ指向它,申明即可使用

extern char **environ; // 申明外部全局变量 environ

1、getenv函数

获取指定环境变量

char *getenv(const char *name);

返回值:存在返回指针,不存在返回NULL

不要修改返回的字符串,这回导致环境变量被修改

2、putenv函数(劣)

添加环境变量

int putenv(char *string);

string: 指向name = value的字符串,不应为自动变量(在栈中分配的字符数组)

返回值:成功返回0,失败返回非0

3、setenv函数(优)

添加或者修改环境变量

int setenv(const char *name, const char *value, int overwrite);

overwrite:为0,不改变环境变量的值,非0,如果那么存在则覆盖,不存在则创建新的环境变量

setenv和putenv的区别:

  • putenv不会为name=value字符串分配内存

  • setenv可以通过overwrite控制添加和修改环境变量(setenv使用自动变量也可以)

终端向进程传参:

NAME=value ./testAPP

如果有多个环境变量要传入进程,则使用空格隔开

4、unsetenv函数

从环境变量表中移除name环境变量

int unsetenv(const char *name);

清空环境变量

1、将全局变量赋值为NULL

environ = NULL;

2、clearenv函数

int clearenv(void);

某些情况使用setenv和clearenv会导致内存泄露,setenv会为环境变量分配一块内存缓冲区,随之成为进程的一部分,调用clearenv并不知道有这块缓冲区,故而无法释放,反复调用这两个函数会造成内存泄漏。

环境变量的作用

HOME:用户家目录

USER: 当前用户名

SHELL:shell解析器名称

PWD:当前所在目录

三、进程的内存布局

堆(heap):由用户申请释放,若用户不释放,程序结束可能由OS回收

栈(stack):编译器自动分配释放,存放函数参数,局部变量的值

静态区/全局区(static):存放静态变量和全局变量,初始化的在(.rwdata or .data),未初始化的在(.bss),C++不区分data和bss

文字常量区(.rodata):常量字符串,程序结束由系统释放

代码段(.txt):存放函数体的二进制代码

Linux下的size命令可以查看文本段、数据段、bss段的段大小

四、进程的虚拟地址空间

大多数系统采用虚拟内存管理技术

每一个进程都有自己独立的地址空间。

32位系统,每个进程的逻辑地址均为4GB,用户3GB(0x00000000~0xc0000000),内核1GB(0xc0000000~0xffffffff)

Linux系统下,应用程序运行在虚拟地址空间中。

程序中读写的内存地址是虚拟地址,不是真正的地址。如应用程序读写0x80000000这个地址,并不是对应硬件的0x800000000物理地址

为什么引入虚拟地址?

如果应用程序使用物理地址:

  • 多个程序需要运行时,要保证内存总量小于实际物理内存大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值