笔记地址:https://note.youdao.com/ynoteshare1/index.html?id=3719e28578c65407e8bb16b479491628&type=note
目录
一、进程的开始和结束
E:\Linux\3.AppNet\4.process\4.1
2019/03/16 21:29
进程状态:运行、等待、停止、就绪、僵尸
1、main函数由谁调用
(1)编译链接时的引导代码。操作系统下的应用程序其实在main执行前也需要先执行一段引导代码才能去执行main,编译连接时(准确说是连接时)由链接器将编译器中事先准备好的引导代码给连接进去和我们的应用程序一起构成最终的可执行程序。
(2)运行时的加载器。加载器是操作系统中的程序,当我们去执行一个程序时(譬如./a.out,譬如代码中用exec族函数来运行)加载器负责将这个程序加载到内存中去执行这个程序。
(3)程序在编译连接时用链接器,运行时用加载器,这两个东西对程序运行原理非常重要。
(4)argc和argv的实现实现是由于信号机制
2、程序如何结束
(1)正常终止:return、exit、_exit
(2)非正常终止:自己或他人发信号终止进程
3、atexit注册进程终止处理函数
(1)实验演示
void func(void) { printf("hello No.2\n"); }
int main(void) { printf("hello No.1\n"); atexit(func);//调用atexith函数 printf("hello No.3\n"); return 0; } |
(2)atexit注册多个进程终止处理函数,先注册的后执行(先进后出,和栈一样)atexit 其实是一个回调函数(函数指针) 用于主函数执行结束后,调用指针指向的函数。比如如下程序,调用指针指向 func函数。
void func(void) { printf("hello No.2\n"); } void func1(void) { printf("hello No.3\n"); }
int main(void) { printf("hello No.1\n"); atexit(func); atexit(func1); return 0; } |
(2)return、exit和_exit的区别:return和exit效果一样,都是会执行进程终止处理函数,但是用_exit终止进程时并不执行atexit注册的进程终止处理函数。
int main(void) { printf("hello No.1\n"); atexit(func); atexit(func1); _exit(0) ; } |
二、进程环境
1、环境变量
使用命令 export 查看环境变量
在每个进程中都有一个环境变量表,所以我们可以在进程中直接使用环境变量
注意“使用 环境变量,就注定和OS环境有关了,注意移植问题”
使用环境变量的方法:
environ
#include<stdio.h> int main(int argc,char *argv[]) { int i = 0; extern char **environ; //声明即可以引用
while(NULL != environ[i]) { printf("第%d个环境变量: %s\n",i,environ[i]); i++; }
printf("Code Access~\n"); return 0; } |
获取指定环境变量函数:getenv
2、进程运行的虚拟地址空间
【虚拟内存技术】
是Linux系统设计的技术,一个进程认为4G的内存空间中,只有自己和操作系统。
实际也许你的设备只有512M,那该怎么实现呢?
- 虚拟地址映射。
与ucos不同,linux能将虚拟地址映射到真正的物理空间中,是一种强大的内存管理方式
- 分布映射
1G的内存每次存放一部分,分步骤依次放入运行时内存
这样做的优势:
1、进程隔离,做到各个进程不使用同一段内存 ,安全高效。
2、提供多进程同时运行,便于设备的更新和维护。(旧手机不能更新系统就是这样的道理)
三、进程的正式引入
1、进程ID
getpid 获取进程id
getppid 获取父进程id
getuid 获取usrid
getgid 获取groupid
#include <stdio.h> #include <sys/types.h> #include <unistd.h>
int main(v |