linux:环境变量,进程地址空间

一.命令行参数

main的参数:int argc,char*argv[],char*env[]

1.参数意义:

argc是命令行调用次程序时传递的参数

例: ls -l -a 传递了三个参数,"ls" "-l" "-a"三个字符串

argv是传递的参数的字符串指针,最后传完了传个null。

例: ls -l -a ,argv内"ls\0" "-l\0" "-a\0" NULL

env是存bash调用此程序给的环境变量,存储结构同argv

2.传参完整过程:

如bash调用程序,先记录调用命令时命令行传参的argv,打散空格记录字符串,放入自己的命令行参数表中,子进程(执行的程序)指向父进程bash的此只读数据(父进程的数据部分如果是只读的子进程也能直接看到,而不是拷贝修改),得到argc,argv....然后start_main函数(调用main的函数)判断argc大小,为0直接调用main,其余调用main(int argc,char*argv[],char*env[]);

3.使用:

给程序封装不同功能,通过命令行参数分别调用,如 ls -a..

cpp 复制代码
#include<stdio.h>
#include<string.h>
int main(int argc,char*argv[])
{
    
    if(strcmp(argv[1],"-a")==0)
    {
        printf("功能1\n");
    }
    else if (strcmp(argv[1],"-s")==0)
    {
        printf("功能2\n");
    }
    else{
        printf("使用说明:-a 功能1 -s 功能2\n");
        
    }
  return 0;   

}
cpp 复制代码
#include<stdio.h>
#include<string.h>
int main(int argc,char*argv[],char*env[])
{
    if(argc<2)
    {
        printf("基础功能\n");
        return 0;
    }
    if(strcmp(argv[1],"-a")==0)
    {
        printf("功能1\n");
    }
    else if (strcmp(argv[1],"-s")==0)
    {
        printf("功能2\n");
    }
    else if(strcmp(argv[1],"-e")==0)
    {
        char**begin=env;
        while(begin!=NULL)
        {
            printf("%s\n",*begin++);
        }
    }
    else{
        printf("使用说明:-a 功能1 -s 功能2\n");
        
    }
  return 0;

}

(每个进程都有环境变量表,都继承于它的父进程,层层继承)

二.环境变量

0.环境变量的加载

用户登录加载环境变量(login等进程加载HOME变量,系统启动shell,去HOME路径自己家目录下,shell读取家目录下.bashrc .bash_profile等环境变量的配置文件(磁盘中的),加载环境变量(内存级的) bash维护的一张环境变量表,shell创建子进程时直接给子进程

1.常见的环境变量

1.1. PATH当前默认搜索指令的路径集合

1.1.1.作用

问:bash为什么默认从/usr/bin搜指令的可执行文件

其实是读的PATH路径,从PATH路径找

1.1.2.更改方式

a.短暂修改bash内的(内存级的),重启会失效: PATH=是覆盖式的, 用PATH=$PATH:你的路径

例:

b.更改.bash_profile .中修改PATH=....:你的路径 。如果没有立刻生效,使用指令source 文件名,使配置文件生效

1.2.HOME家目录

1.2.1.home变量来源

在 Linux 系统中,每个用户的家目录路径都存储在 /etc/passwd 文件中,登录进程(如 loginsshd)会读取 /etc/passwd 文件,并将 HOME 变量设置为用户的家目录路径。不在全局配置文件中,也不在某个用户的配置文件中,由登录进程设置。

1.2.2.作用

系统创建shell,shell读取HOME,读取全局配置文件等,进入家目录,再读取用户配置文件。

1.3.其余

SHELL:指定启动的shell路径

PWD:当前的工作路径(shell的,其余的子进程继承)

USER:当前用户。用处:限制程序只能某些用户访问其他用户访问不了(if(getenv("USER")==))

OLDPWD:旧路径。cd -就是通过找这切换到最近路径

2.环境变量的意义

1.环境变量可以被进程层层继承(具有全局属性),本地变量只能本进程跑(如bash中,不能继承意义不大),

就可以被程序定义判断是不是第一次启动这个程序(相当于ifndef define..),然后分叉执行。

2.让所有配置信息生效(信息被所有进程看到)

3.可以进程间传递数据

3.环境变量的导入

bash导入变量

set查变量(环境变量和本地变量)

3.1.环境变量。本地变量

将本地变量变为环境变量:export 变量名

比较:

环境变量可以被子进程继承,本地变量不行。-->环境变量具有全局属性,bash后都能看见

三.进程地址空间

问题:父子进程共用一份代码为什么打印全局变量值不同,变量地址打印却一样?

答:此地址是虚拟地址(线性地址)

1.作用:

让每个进程都以为自己独占内存,地址都从0开始,实现进程间数据隔离

2.怎么管理进程地址空间

先描述在组织:内核中创建数据结构对象struct

区域划分:

给程序一个start,end表示某个区域起始地址和结束地址(不是直接是0,让子进程和父进程先都指向同一块空间,如果父子进程都对某区域修改,就修改子进程的区域的实际地址指向),让程序用多个区(代码区,栈,堆),再根据内存情况转为实际地址

页表:进程地址空间管理方案:

每个进程都有一个页表,父进程创建子进程时,只需要将PCB,页表拷贝就行,指向同一份代码,不同时修改了才改页表内物理地址

进程=内核数据结构(PCB+mm_struct/页表)+代码和数据

进程独立再理解:

1.内核数据结构独立,PCB和页表都要拷贝一份

2.代码和数据也独立(代码只读),数据通过页表指向不同物理空间(除非是父子进程同时修改数据)

问题:进程的uid是怎么来的

答:bash给的,bash在家目录读配置文件读来的

补充:

1.查命令行的环境变量名称前加$表示取值:

echo $PATH

2.不想指定路径执行自己的指令方法:

a.可执行文件移动到/usr/bin

b.更改PATH

3.获取环境变量:

1.系统调用:

2.程序获取的env

3.系统内部也维护了一个指针char**environ,指向字符串指针表,直接程序获取(C语言提供的extern char**environ)

相关推荐
专注API从业者5 分钟前
Python/Java 代码示例:手把手教程调用 1688 API 获取商品详情实时数据
java·linux·数据库·python
Ribou37 分钟前
Ubuntu 24.04.2安装k8s 1.33.4 配置cilium
linux·ubuntu·kubernetes
tan180°1 小时前
Boost搜索引擎 网络库与前端(4)
linux·网络·c++·搜索引擎
Mr. Cao code2 小时前
Docker:颠覆传统虚拟化的轻量级革命
linux·运维·ubuntu·docker·容器
抓饼先生2 小时前
Linux control group笔记
linux·笔记·bash
挺6的还3 小时前
25.线程概念和控制(二)
linux
您的通讯录好友3 小时前
conda环境导出
linux·windows·conda
代码AC不AC4 小时前
【Linux】vim工具篇
linux·vim·工具详解
码农hbk4 小时前
Linux signal 图文详解(三)信号处理
linux·信号处理
bug攻城狮5 小时前
Skopeo 工具介绍与 CentOS 7 安装指南
linux·运维·centos