OS21.【Linux】環境變量

目錄

1.與環境變量有關的實驗

A.對比命令和自制程序的運行

為什么.像ls、pwd這樣的命令運行是不需要加路徑?

執行自制程序而不加路徑的方法,看看PATH環境變量

方法1:將自制程序移動到系統的搜索路徑下

方法2:臨時修改PATH環境變量

B.查看系統中所有環境變量

解釋幾個常見的環境變量

C.獲取環境變量的函數getenv()

2.環境變量

解釋全局屬性

命令行參數

a.out子進程是如何得到環境變量表的?

證明能被子進程繼承,也就證明的全局屬性

添加環境變量的命令:export

取消環境變量的命令:unset

使用第三方變量environ來訪問環境變量

3.系統變量的分類

環境變量

本地變量

set命令

證明本地變量不可被繼承

4.系統命令的分類

常規命令和內建命令

man和help的區別

5.總結獲取環境變量的幾種方法

6.拓展閱讀:自定義入口函數

7.附: C89標準文檔對main函數的描述


1.與環境變量有關的實驗

從與環境變量有關的實驗來感受環境變量

A.對比命令和自制程序的運行

1.像ls、pwd這樣的命令運行是不需要加路徑的

2.如果不配置環境變量,那么運行開發者自制程序是需要加路徑的

例如:當前目錄下有一個a.out可執行文件,那么運行時需要加路徑:

./a.out #.表示當前目錄

a.out是由以下代碼產生的:?

#include <stdio.h>
int main()
{printf("Hello World!");return 0;
}

為什么.像ls、pwd這樣的命令運行是不需要加路徑?

之前在OS4.【Linux】基本指令入門(3)文章講過:系統的命令存儲在特定的路徑下,那么bash執行指令會到特定的路徑中找

特定的路徑存儲在環境變量PATH中

?使用echo命令打印系統的環境變量:

echo $PATH #注意: $作用:說明PATH是變量名

那么在搜索命令時,會從左向右按順序查找這些路徑下的命令,如果找到了,之后的路徑就不找了?

還可以打印其他環境變量:

echo $HOME #查看當前用戶的家目錄

?

結論:

1.PATH存儲了Linux系統命令的搜索路徑

2.執行非系統命令的程序需要加路徑,因為PATH中沒有;執行系統的命令不需要帶路徑,因為PATH存儲了搜索路徑

執行自制程序而不加路徑的方法,看看PATH環境變量

方法1:將自制程序移動到系統的搜索路徑下

之前OS4.【Linux】基本指令入門(3)在文章做過,這里不再演示

方法2:臨時修改PATH環境變量

*注意:以下兩種方法都只是臨時修改PATH環境變量,重新連接服務器時PATH會恢復默認值,可以得出:?PATH是內存中的環境變量

1.直接覆蓋掉PATH:

 PATH=/home/guest

(按照賦值號=的規則: PATH的新值就是/home/guest)?

會導致有些系統命令是用不了的:

例如ls命令不可用,但pwd是可用的,具體為什么pwd可用本文后面會講

這樣就不用添加路徑了:

2.對PATH添加新的路徑

PATH=$PATH:/home/guest

(要使用冒號分割符,因為冒號分割符的作用就是分開各個路徑)

這樣就不用添加路徑了:

B.查看系統中所有環境變量

使用不帶任何選項的env命令:

其中,=前面的大寫單詞指的是環境變量名,?=后面的是該環境變量的值

環境變量名 = 對應的值

解釋幾個常見的環境變量

USER

指的是當前登錄的用戶(隨su命令切換用戶而變)

LOGNAME

和USER不同的是:在某些情況下,它的值可能會保持不變,即使通過su命令切換到其他用戶

PWD

指當前處于的絕對路徑,其值會在每次執行cd命令后時更新

*注:pwd命令不是使用了PWD環境變量,而是通過getcwd函數實現的

HOME

指當前用戶的家目錄

SHELL

指當前Shell,它的值通常是/bin/bash

C.獲取環境變量的函數getenv()

看看手冊:

getenv()的作用:獲取指定的環境變量(environment variable),需要包含<stdlib.h>頭文件

函數的聲明:?char* getenv(const char *name);

注意到有兩個參數:

示例代碼:

#include <stdlib.h>
#include <stdio.h>
int main()
{printf("PATH=%s\n",getenv("PATH"));return 0;
}

運行結果:和不帶任何選項的env命令打印的結果是一樣的

2.環境變量

從上面的三個實驗可以總結出環境變量的定義:

環境變量: 是操作系統中用來指定操作系統運行環境的一些參數,是系統提供的一組 name = value 形式的變量,不同的環境變量有不同的用途,通常具有全局屬性

例如編寫C/C++代碼的時候,在鏈接的時候,有相關環境變量幫助編譯器進行查找所鏈接的動態靜態庫

解釋全局屬性

命令行參數

回顧分析命令行參數的文章:

110.【C語言】編寫命令行程序(1)

113.【C語言】編寫命令行程序(2)

114.【C語言】實戰分析命令行程序:srom轉換工具源碼分析

一般情況下,main函數用的比較多的兩種寫法:

int main()
int main(int argc, char* argv[])

但Linux操作系統為main函數提供了第3個參數:char *envp[]?

(來自GNU Program-Arguments網站)?

注:編譯器會根據情況處理main函數的三種不同寫法

envp的全稱是environment variables?pointer array,是環境變量指針數組,可以打印內容

#include <stdio.h>
int main(int argc,char* argv[],char* envp[])
{for (size_t i=0;envp[i];i++){printf("%s\n",envp[i]);}return 0;
}

提示: argv和env表的結構都一樣

運行結果:

結論:

1.程序運行需要兩張核心向量表:?char* argv[],char* envp[],指針數組的結尾元素的值為空指針 2.main函數之前還有一些函數,這些函數負責向main函數傳遞這兩張表的指針和參數的個數argc

a.out子進程是如何得到環境變量表的?

上方運行了a.out子進程,子進程打印了操作系統的所有環境變量

bash在啟動時,會從操作系統的配置文件中讀取環境變量信息,bash產生的子進程會繼承bash得到的環境變量!

證明能被子進程繼承,也就證明的全局屬性

添加環境變量的命令:export

例如添加臨時環境變量:

export MY_ENV=1

注意: 不能寫成MY_ENV=1,這樣寫是添加本地變量;變成環境變量需要加export前綴

?檢查是否成功添加:

env | grep MY_ENV

再次執行a.out,會發現MY_ENV已經被bash的子進程a.out繼承

取消環境變量的命令:unset

使用第三方變量environ來訪問環境變量

查詢environ的含義:

extern char **environ其實是存一些環境變量字符串指針的數組,?最后一個元素的值為空指針

libc中定義的全局變量environ指向環境變量表,environ沒有包含在任何頭文件中,所以在使用時要用extern聲明

例如以下代碼:

#include <stdio.h>
#include <unistd.h>
int main() 
{extern char** environ;for ( int i = 0; environ[i]; i++) {printf("%d:%s\n", i, environ[i]);}
}

運行結果:

?

3.系統變量的分類

系統變量主要分為本地變量和環境變量

環境變量

見上方內容

本地變量

創建本地變量的命令

本地變量名 = 本地變量值 #前面不要加export

?本地變量和環境變量不同,本地變量主要作用范圍是當前shell進程,不會被子進程繼承,但環境變量可以被子進程繼承

例如添加2個本地變量:

?(\是續行符,可以幫助開發者寫多行命令)

環境變量中是查不到的:

set命令

作用:?查系統中所有的變量(本地變量+環境變量)

例如查之前添加的本地變量:

證明本地變量不可被繼承

證明bash的子進程無法獲取上面提到的VAL1和VAL2的值即可

#include <stdio.h>
#include <stdlib.h>
int main()
{printf("VAL1=%s",getenv("VAL1"));printf("VAL2=%s",getenv("VAL2"));return 0;
}

運行結果:值為空?

將VAL1和VAL2用export導出,再打印:

4.系統命令的分類

常規命令和內建命令

問題:執行echo命令讓bash產生了子進程,那為什么能獲取本地變量?

顯然echo不是常規命令

Linux下有兩種命令:

1.常規命令: 通過創建子進程;來執行常規命令
2.內建命令(也稱內置命令,英文名為builtin): bash 不創建子進程,而是由自己親自執行,類似于 bash 調用了自己寫的或者系統提供的函數

例如cd命令調用了chdir()系統調用接口,是由bash自己執行的函數,cd命令的作用是讓進程改變自己的路徑

成功切換返回0,否則返回-1?

可以寫一個簡單的切換路徑的程序:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{if (argc == 1){printf("Usage:cd path");return -1;}if (chdir(argv[1]))printf("%s: No such directory\n", argv[1]);elseprintf("Change path successfully\n");while (1){scanf("%s", argv[1]);if (chdir(argv[1]))printf("%s: No such directory\n", argv[1]);elseprintf("Change path successfully\n");}return 0;
}

注意:這個程序和cd命令還不太一樣,?是讓進程改變自己的路徑,不是更改bash的路徑,因此使用上方代碼切換路徑后,pwd命令打印的值是不變的

可以在cwd文件中看到:?

當然可以繼續切換看看cwd的值的變化

man和help的區別

man主要查看的是外部命令和一些系統調用和函數,例如ls、printf……
help主要查看的就是內置命令了。

提示:使用type命令可以查看命令的類型,例如

5.總結獲取環境變量的幾種方法

1.使用命令env

2.使用getenv()函數

3.直接打印char* envp[]

4.第三方變量environ獲取

6.拓展閱讀:自定義入口函數

Linux下可以通過自定義入口函數的方法來達到不從main函數(cppreference main_function)開始執行的目的

在https://www.geeksforgeeks.org/c/write-running-c-code-without-main/提到一種方法;

#include<stdio.h> 
#include<stdlib.h> // entry point function 
int nomain(); void _start(){ // calling entry point nomain(); exit(0); 
} int nomain() 
{ puts("Geeksforgeeks"); return 0; 
}

編譯命令:

gcc -o nomain.out nomain.c -nostartfiles

?運行結果:

摘自stackoverflow what-is-the-use-of-start-in-c的回答:

The symbol?_start?is the?entry point?of your program. That is, the address of that symbol is the address jumped to on program start. Normally, the function with the name?_start?is supplied by a file called?crt0.o?which contains the startup code for the C runtime environment. It sets up some stuff, populates the argument array?argv, counts how many arguments are there, and then calls?main. After?main?returns,?exit?is called.

If a program does not want to use the C runtime environment, it needs to supply its own code for?_start. For instance, the reference implementation of the Go programming language does so because they need a non-standard threading model which requires some magic with the stack. It's also useful to supply your own?_start?when you want to write really tiny programs or programs that do unconventional things.

翻譯: _start符號是Linux下規定的函數的入口點,程序啟動時會跳轉到該符號所表示的地址

正常情況下, 由_start標識的的函數由crt0.o文件提供,它包含了 C 運行時環境的啟動代碼. 該代碼會完成一些初始化工作: 填充參數數組 argv ,統計參數個數argc,然后調用main函數. main 返回后,再調用exit函數

如果某個程序不想使用C運行時環境,就必須自行提供 _start 的實現
當你想編寫體積極小的程序,或者做一些非常規操作時,自己寫 _start 也很有用

7.附: C89標準文檔對main函數的描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91893.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91893.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91893.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

加密流量論文復現:《Detecting DNS over HTTPS based data exfiltration》(上)

本文將以我個人的理解去閱讀該篇流量加密論文&#xff0c;并在下一篇盡力對其中的實驗部分進行復現。話不多說&#xff0c;先從論文開始著手。 內容介紹 傳統的DNS(Domain Name System)協議是以明文傳輸的。DNS作為互聯網的基礎設施&#xff0c;最初設計時主要考慮的是功能和效…

Apache RocketMQ 中Message (消息)的核心概念

好的&#xff0c;我們來深入理解一下 Apache RocketMQ 中 Message (消息) 這個核心概念。這份文檔詳細闡述了消息的定義、在模型中的位置、內部屬性、約束和使用建議。 你可以將 Message 看作是 RocketMQ 系統中數據傳輸和處理的最小原子單位。它承載了業務數據&#xff0c;并附…

C 語言問題

1. C語言中 union 與 struct 的區別類型structunion內存分配機制編譯器為每個成員?獨立分配內存空間&#xff0c;總內存大小 所有成員大小之和&#xff08;考慮內存對齊&#xff09;所有成員?共享同一段內存空間&#xff0c;總內存大小 ?最大成員的大小?數據存儲特性1. 所…

[ LeetCode優選算法專題一雙指針-----盛最多的水]

1.題目鏈接 LeetCode盛最多的水 2.題目描述 3.題目解析 問題本質分析 "盛最多水的容器" 問題可以抽象為&#xff1a;在坐標軸上有 n 條垂直線段&#xff0c;第 i 條線段的兩個端點分別是 (i, 0) 和 (i, height [i])。找到兩條線段&#xff0c;使得它們與 x 軸共同…

舊筆記本電腦如何安裝飛牛OS

01引言隨著電子產品的更新換代&#xff0c;我們有很多的電子產品已經滿足不了現在的工作需求和日常娛樂了&#xff0c;比如&#xff1a;用了很久厚重筆記本電腦放在現在辦公也是有點吃力了&#xff0c;我們現在換新了舊的還不想放在那里吃灰&#xff0c;怎么辦呢&#xff1f;我…

某金服Java面試終極指南:25題完整解析與場景化方案

涵蓋分布式鎖、緩存、事務、高并發等金融系統核心考點&#xff0c;附解決方案與抗風險設計一、分布式鎖深度解決方案 1. Redis分布式鎖完整實現 // 原子加鎖 防死鎖 String uuid UUID.randomUUID().toString(); Boolean locked redisTemplate.opsForValue().setIfAbsent(&qu…

MATLAB 2025a的下載以及安裝,安裝X310的測試附加功能(附加安裝包)

首先將安裝包下載到本地中之后解壓該文件夾&#xff0c;打開文件發現有兩個文件&#xff0c;其中crach文件夾中是破解matlab所用到的文件。而另一個壓縮包就是需要安裝的文件&#xff0c;要先解壓在安裝。在安裝之前將網絡斷開&#xff0c;不然可能破解不成功&#xff0c;先進入…

Scala實用編程(附電子書資料)

概述 Scala 是一種多范式編程語言&#xff0c;結合了面向對象編程&#xff08;OOP&#xff09;和函數式編程&#xff08;FP&#xff09;的特性電子書資料&#xff1a;https://pan.quark.cn/s/88737d4a680d Scala 的核心特點多范式融合 既支持面向對象編程&#xff08;類、繼承、…

數據結構(8)雙向鏈表

目錄 一、概念與結構 二、雙向鏈表的實現 1、初始化 2、尾插 3、頭插 4、尾刪 5、頭刪 6、在指定位置之后插入結點 7、刪除指定位置的結點 三、完整參考代碼 一、概念與結構 這里的雙向鏈表是指帶頭的的雙向循環鏈表&#xff0c;這里的“帶頭”和之前所說的“頭結…

【DeepSeek-R1 】分詞系統架構解析

文章目錄 ??前言 ?? 1. SentencePiece Unigram 的核心原理 1.1 算法基礎框架 1.2 核心數學原理 1.3 與BPE/WordPiece的對比 ?? 2. DeepSeek-R1 分詞器實現細節 2.1 詞表結構設計 2.2 關鍵特性實現 ?? 3. 性能優化關鍵技術 3.1 加速策略對比 3.2 編碼過程偽代碼 ?? 4.…

Linux自主實現shell

以下是在Linux操作系統 centos7版本下實現的shell &#xff0c;該shell具備bash的基礎功能&#xff0c;無上下鍵輸入歷史命令功能&#xff0c;刪除字符或命令時按住Ctrl Back #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.…

vue+elementUI上傳圖片至七牛云組件封裝及循環使用

1.效果&#xff08;解決循環組件賦值問題&#xff09; 廢話不多說直接上代碼 2.下載七牛云依賴 npm install qiniu-js # 或者使用 yarn yarn add qiniu-js3.在vue組件中引入 import * as qiniu from qiniu-js4.在components文件夾下創建UploadImg1/uploadImg.vue組件 <templ…

2025年6月電子學會青少年軟件編程(C語言)等級考試試卷(一級)

答案和更多內容請查看網站&#xff1a;【試卷中心 -----> 電子學會 ----> C/C ----> 一級】 網站鏈接 青少年軟件編程歷年真題模擬題實時更新 一、編程題 第 1 題 希望如光 題目描述 在充滿挑戰的生活中&#xff0c;希望往往是支撐人們穿越黑暗的核心力量。這…

拒絕復雜,AI圖表制作簡單化

在信息爆炸的時代&#xff0c;數據可視化已成為傳遞信息的核心手段。無論是職場匯報中的業績分析&#xff0c;還是學術研究里的實驗數據呈現&#xff0c;一張清晰直觀的圖表往往能勝過千言萬語。而 AI 技術的介入&#xff0c;徹底改變了圖表制作的傳統模式 —— 它不僅讓零基礎…

easypoi生成多個sheet的動態表頭的實現

在使用 EasyPOI 導出 Excel 時&#xff0c;生成多個 Sheet 且每個 Sheet 的表頭是動態的&#xff08;即每個 Sheet 的列數和列名可能不同&#xff09;&#xff0c;可以通過如下方式實現&#xff1a;? 實現原理簡述 使用 Workbook workbook ExcelExportUtil.exportExcel(expor…

移除鏈表元素+反轉鏈表+鏈表的中間節點+合并兩個有序鏈表+環形鏈表約瑟夫問題+分割鏈表

一、移除鏈表元素 給你一個鏈表的頭節點 phead 和一個整數 val &#xff0c;請你刪除鏈表中所有滿足 Node.val val 的節點&#xff0c;并返回 新的頭節點 (列表中的節點數目在范圍 [0, 104] 內) 示例&#xff1a;輸入&#xff1a;head [1,2,6,3,4,5,6], val 6 …

vue3+arcgisAPI4示例:軌跡點模擬移動(附源碼下載)

demo源碼運行環境以及配置運行環境&#xff1a;依賴Node安裝環境&#xff0c;需要安裝Node。 運行工具&#xff1a;vscode或者其他工具。 配置方式&#xff1a;下載demo源碼&#xff0c;vscode打開&#xff0c;然后順序執行以下命令&#xff1a; &#xff08;1&#xff09;下載…

Design Compiler:Milkyway庫的創建與使用

相關閱讀 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 DC Ultra推出了拓撲模式&#xff0c;在綜合時會對標準單元進行粗布局(Coarse Placement)并使用虛擬布線(Virtual Routing)技術計算互聯延遲&#xff0c;關于拓…

嵌入式教學的云端革命:高精度仿真如何重塑倒車雷達實驗與工程教育——深圳航天科技創新研究院賦能新一代虛實融合實訓平臺

一、嵌入式教學的困境與破局之道 在傳統嵌入式系統教學中&#xff0c;硬件依賴始終是核心痛點。以“倒車雷達實驗”為例&#xff0c;學生需操作STM32開發板、超聲波傳感器、蜂鳴器等硬件&#xff0c;面臨設備損耗、接線錯誤、調試效率低等問題。更關鍵的是&#xff0c;物理硬件…

flutter-boilerplate-project 學習筆記

項目地址&#xff1a; https://github.com/zubairehman/flutter_boilerplate_project/tree/master 樣板包含創建新庫或項目所需的最小實現。存儲庫代碼預加載了一些基本組件&#xff0c;例如基本應用程序架構、應用程序主題、常量和創建新項目所需的依賴項。通過使用樣板代碼…