Linux进程概念——第二篇

一、环境变量
1.概念:一个存储操作系统运行环境的一些功能性参数的变量。
2.如何查看环境变量:
(1)env:显示所有环境变量
(2)set显示本地定义的shell变量和环境变量
(3)echo:显示某个环境变量值(但是需要知道我们这个环境变量的名字)
环境变量在系统中具有全局特性。
3.如何获取环境变量
(1)程序运行参数
在main函数中(int argc,char *argv[],char *env[]),第三个参数就是存放我们 环境变量的。

#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
void env1(char *env[]){
int i;
for(i=0;i<env[i]!=NULL;i++){
printf("env:[%s]\n",env[i])
}
}
int main(int argc,char *argv[],char *env[]){
env1();
reurn 0;
}

(2)全局变量 extern char **environ

#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
void env2()
{
//这是一个全局变量,定义在c库中,使用的时候需要声明
extern char **environ
int i;
for(i=0;i<environ[i]!=NULL;i++){
printf("env:[%s]\n",environ[i])
}
}
int main(int argc,char *argv[],char *env[]){
env2();
reurn 0;
}

(3)getenv()

#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
void env3()
{
//char *getenv(const char *name);
//通过环境变量的名称获取环境变量的内容,内容通过返回值返回
printf("path:[%s]\n",getenv("PATH"));
}
int main(int argc,char *argv[],char *env[]){
env3();
reurn 0;
}

4.如何设置/转换/添加一个条件变量
关键字:export
ecport MYVAL:表示这个MYVAL被声明/定义成了一个环境变量。
unset MYVAL:删除一个环境变量。
5.常见的环境变量
PATH:指定命令的搜索路径
HOME:指定用户的主工作目录
SHELL:当前Shell,它的值通常是/bin/bash
二、程序地址空间(进程概念中的第三大重点)
1.程序地址空间
实际上我们进程中访问到的这些地址都是虚拟地址。
实际上这个程序地址空间更应该称作:进程的虚拟地址空间。
虚拟地址空间实际上是一个结构体:struct mm_struct
虚拟地址空间是一个假的内存地址,是用来欺骗进程的。

2.进程地址空间
我们前面说的程序地址空间是不准确的,准确来说应该是进程地址空间。下面我们就来看一下进程地址空间:
(1)地址是内存区域的编号。内存指针指向的就是地址空间。
是一个进程的虚拟地址空间——虚假的内存地址编号
(2)为什么要用虚拟内存地址而不直接使用物理内存地址:缺乏内存访问控制,内存利用率低现在使用的是分页式内存管理(虚拟地址空间+页表)。
(3)页表的功能:记录虚拟地址与物理地址映射关系,对内存访问的控制。
(4)写时复制技术:

#include <stdio.h>
 #include <unistd.h> 
 #include <stdlib.h>
 
int g_val = 0;

int main() 
{    pid_t id = fork();   
 if(id < 0){        
 perror("fork");        
 return 0;    }    
 else if(id == 0){ //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取        
 g_val=100;        
 printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);    
 }else{ //parent        
 sleep(3);        
 printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);    
 }    
 sleep(1);    
 return 0; 
 }

输出结果:
//与环境相关,观察现象即可
child[3046]: 100 : 0x80497e8
parent[3045]: 0 : 0x80497e8
在这里插入图片描述
当修改了的时候这个值g_val就会重新开辟一个空间,这个空间就是另外的一个值了。这个时候就相当于是两个变量了,对于父子进程就是不同的变量了。
实际上子进程复制父进程,其实就是子进程创建pcb,然后将父进程pcb中的数据拷贝过来这时候父子进程因为虚拟地址空间页表完全一样,因此他们的代码和数据看起来都是一样的,但是我们说了进程应该具有独立性,并且任意进程修改数据不应该对其它进程造成影响,因此子进程也需要开辟真正的物理内存来存储这些数据,但是子进程有可能根本就不用这些数据,这时候要是直接开辟内存以及更新页表,拷贝数据,就做了无用功,因此操作系统一开始并不直接开辟内存拷贝所有数据,而是等有任意一个进程修改数据的时候再重新给子进程开辟物理内存,拷贝数据。——写时拷贝技术
3.进程调度
(1)概念:操作系统切换调度进程(pcb)运行在CPU上;
如果进程非常多那么进程是一个一个运行在CPU上的;但是进程是有优先级的

猜你喜欢

转载自blog.csdn.net/ZhuiZhuDream5/article/details/86664590