九江網(wǎng)站建設(shè)寧波seo教程行業(yè)推廣
目錄
- Linux—進(jìn)程學(xué)習(xí)—3
- 1.進(jìn)程優(yōu)先級(jí)
- 1.1Linux中的進(jìn)程優(yōu)先級(jí)
- 1.2修改進(jìn)程優(yōu)先級(jí)—top
- 2.進(jìn)程的其他概念
- 3.進(jìn)程切換
- 4.環(huán)境變量
- 4.0環(huán)境變量的理解
- 4.1環(huán)境變量的基本概念
- 4.2添加環(huán)境變量—export
- 4.3Linux中環(huán)境變量的由來
- 4.4常見環(huán)境變量
- 4.5和環(huán)境變量相關(guān)的命令
- 4.6通過系統(tǒng)調(diào)用獲得環(huán)境變量
- 4.6.1 getenv
- 4.6.2 putenv
- 4.7本地變量
- 總結(jié):
- 4.8main函數(shù)的參數(shù)
- 4.8.1命令行參數(shù)
- 4.8.1.1命令行參數(shù)的意義
- 4.8.2環(huán)境變量參數(shù)—char* env[]
- 4.8.3總結(jié)
- 4.9環(huán)境變量的組織方式
- 4.10獲取環(huán)境變量的3種方式
Linux—進(jìn)程學(xué)習(xí)—3
1.進(jìn)程優(yōu)先級(jí)
什么是進(jìn)程優(yōu)先級(jí):
-
CPU資源分配的先后順序,就是指進(jìn)程的優(yōu)先權(quán)(priority)。
-
優(yōu)先權(quán)高的進(jìn)程有優(yōu)先執(zhí)行權(quán)利。配置進(jìn)程優(yōu)先權(quán)對(duì)多任務(wù)環(huán)境的Linux很有用,可以改善系統(tǒng)性能。
-
還可以把進(jìn)程運(yùn)行到指定的CPU上,這樣一來,把不重要的進(jìn)程安排到某個(gè)CPU,可以大大改善系統(tǒng)整體性能
要注意權(quán)限和優(yōu)先級(jí)的區(qū)別:
權(quán)限:能還是不能
優(yōu)先級(jí):都能,先做還是后做。
為什么會(huì)有進(jìn)程優(yōu)先級(jí)?
因?yàn)橘Y源太少了,需要資源的進(jìn)程太多了。
就比如大多數(shù)計(jì)算機(jī)的cpu都只有一個(gè),而需要等待cpu的進(jìn)程數(shù)量遠(yuǎn)遠(yuǎn)多于cpu這個(gè)資源的數(shù)量。
1.1Linux中的進(jìn)程優(yōu)先級(jí)
在Linux中,優(yōu)先級(jí)和進(jìn)程狀態(tài)一樣,其實(shí)就是2個(gè)整數(shù)。這個(gè)整數(shù)是放在PCB里面維護(hù)的,屬于是進(jìn)程的一個(gè)屬性
寫一個(gè)小程序來查看進(jìn)程優(yōu)先級(jí):
輸入ps -l
和ps -al
可以查看到一些重要信息【ps -al
可以查看當(dāng)自己運(yùn)行的進(jìn)程信息】
- UID : 代表執(zhí)行者的身份
-
PID : 代表這個(gè)進(jìn)程的代號(hào)
-
PPID :代表這個(gè)進(jìn)程是由哪個(gè)進(jìn)程發(fā)展衍生而來的,亦即父進(jìn)程的代號(hào)
-
PRI :代表這個(gè)進(jìn)程可被執(zhí)行的優(yōu)先級(jí),其值越小越早被執(zhí)行
-
NI :代表這個(gè)進(jìn)程的nice值【默認(rèn)是0】
Linux比較特殊,其最終優(yōu)先級(jí) = PRI(剛被創(chuàng)建出來就被賦予的優(yōu)先級(jí)) + NI
PRI and NI
PRI也還是比較好理解的,即進(jìn)程的優(yōu)先級(jí),或者通俗點(diǎn)說就是程序被CPU執(zhí)行的先后順序,此值越小進(jìn)程的優(yōu)先級(jí)別越高
NI就是我們所要說的nice值了,其表示進(jìn)程可被執(zhí)行的優(yōu)先級(jí)的修正數(shù)值
PRI值越小越快被執(zhí)行,那么加入nice值后,將會(huì)使得PRI變?yōu)?#xff1a;PRI(new)=PRI(old)+nice
這樣,當(dāng)nice值為負(fù)值的時(shí)候,那么該程序?qū)?huì)優(yōu)先級(jí)值將變小,即其優(yōu)先級(jí)會(huì)變高,則其越快被執(zhí)行
調(diào)整進(jìn)程優(yōu)先級(jí),在Linux下,就是調(diào)整進(jìn)程nice值
nice其取值范圍是-20至19,一共40個(gè)級(jí)別
這說明:Linux是支持,進(jìn)程在運(yùn)行中,調(diào)整進(jìn)程優(yōu)先級(jí)的【更改NI實(shí)現(xiàn)】
要注意:
進(jìn)程的nice值不是進(jìn)程的優(yōu)先級(jí),他們不是一個(gè)概念,但是進(jìn)程nice值會(huì)影響到進(jìn)程的優(yōu)先級(jí)變化
1.2修改進(jìn)程優(yōu)先級(jí)—top
修改進(jìn)程優(yōu)先級(jí)其實(shí)沒有什么必要,因?yàn)闀?huì)不會(huì)修改另說,很多時(shí)候修改完的效果并不會(huì)說有想象的那么好。除非是追求極致效率,不然沒有必要去修改進(jìn)程優(yōu)先級(jí)。
這里演示一個(gè)修改進(jìn)程優(yōu)先級(jí)的方法——使用top修改進(jìn)程優(yōu)先級(jí)
top修改優(yōu)先級(jí)的方法:
- 進(jìn)入top后按“r”–>輸入進(jìn)程PID–>輸入nice值
驗(yàn)證一下:
進(jìn)場優(yōu)先級(jí)的修改可能會(huì)需要root權(quán)限,因此調(diào)用top的時(shí)候,可以使用sudo top
正常輸入r彈出來的進(jìn)程是一個(gè)默認(rèn)進(jìn)程,如上圖所示,默認(rèn)進(jìn)程的ipd是9152、
這里的小程序仍然是上面那個(gè)。
輸入要修改優(yōu)先級(jí)的進(jìn)程的pid,然后就會(huì)對(duì)我們輸入的pid的進(jìn)程進(jìn)行修改,如下圖所示
然后輸入在對(duì)25849的進(jìn)程優(yōu)先級(jí)輸入一個(gè)-100
退出top工具,出來查看進(jìn)程優(yōu)先級(jí)發(fā)現(xiàn)NI和PRI都發(fā)生了變化【PRI最終是60,變小了,因此該進(jìn)程的優(yōu)先級(jí)變高了】
但是該進(jìn)程退出后,在重新運(yùn)行的話,優(yōu)先級(jí)還是默認(rèn)的
這里需要注意——Linux是不會(huì)讓用戶過度的修改NI值的。
這是因?yàn)?#xff0c;如果用戶將自己的進(jìn)程的優(yōu)先級(jí)調(diào)的非常高,那么就會(huì)導(dǎo)致這個(gè)進(jìn)程經(jīng)常需要占用CPU,這樣就會(huì)導(dǎo)致操作系統(tǒng)的調(diào)度失衡,其他進(jìn)程很可能沒辦法占用到cpu資源了。因此Linux不會(huì)讓用戶過分的去調(diào)低NI值,來讓進(jìn)程的優(yōu)先級(jí)過高
NI的值前面也說了,范圍就是-20至19,一共40個(gè)級(jí)別。
因此Linux中,用戶能夠修改的最終的優(yōu)先級(jí)范圍就是[80 - 20, 80 + 19]。
2.進(jìn)程的其他概念
-
**競爭性:**系統(tǒng)進(jìn)程數(shù)目眾多,而CPU資源只有少量,甚至1個(gè),所以進(jìn)程之間是具有競爭屬性的。為了高效完成任務(wù),更合理競爭相關(guān)資源,便具有了優(yōu)先級(jí)
-
**獨(dú)立性:**多進(jìn)程運(yùn)行,需要獨(dú)享各種資源,多進(jìn)程運(yùn)行期間互不干擾。哪怕其中一個(gè)進(jìn)程掛了,但是不會(huì)影響另外一個(gè)進(jìn)程運(yùn)行。
為了維持這個(gè)獨(dú)立性,需要耗費(fèi)更多的資源來維護(hù)【學(xué)習(xí)進(jìn)程地址空間之后,才能理解】
-
**并行:**多個(gè)進(jìn)程在多個(gè)CPU下分別,同時(shí)進(jìn)行運(yùn)行,這稱之為并行
-
并發(fā): 多個(gè)進(jìn)程在一個(gè)CPU下采用進(jìn)程切換的方式,在一段時(shí)間之內(nèi),讓多個(gè)進(jìn)程都得以推進(jìn),稱之為并發(fā)
對(duì)并發(fā)需要知道的:
一個(gè)cpu,在任意一個(gè)時(shí)刻下,只能夠運(yùn)行一個(gè)進(jìn)程,也就是只能被一個(gè)進(jìn)程占用。
在cpu資源只有一個(gè)或2個(gè)的情況下,為了能夠在一段時(shí)間內(nèi),推進(jìn)多個(gè)進(jìn)程運(yùn)行的現(xiàn)象叫做并發(fā)。
這是如何做到的呢,其實(shí)主要靠的是一個(gè)策略——時(shí)間片
其實(shí)就是一個(gè)進(jìn)程,操作系統(tǒng)規(guī)定你只能占用cpu資源多少時(shí)間。時(shí)間到了,就必須將cpu資源讓出來,讓其他進(jìn)程占用cpu。這里有個(gè)現(xiàn)象是進(jìn)程切換。
3.進(jìn)程切換
前面也說了,CPU比較蠢,需要分析并接受外部的指令和數(shù)據(jù),才能夠進(jìn)行運(yùn)算。
因此CPU只干三件事情,【1.取指令、2.分析指令、3.執(zhí)行指令】
在這個(gè)前提下,進(jìn)程再被CPU執(zhí)行的時(shí)候,其實(shí)CPU就是不斷的在重復(fù)這三步,這個(gè)過程用到了很多的寄存器,一個(gè)CPU內(nèi)部會(huì)有一套寄存器。
對(duì)于進(jìn)程切換的一些知識(shí)和理解,先看下面這個(gè)圖:
對(duì)進(jìn)程切換的分析:
進(jìn)程再被執(zhí)行的時(shí)候,肯定會(huì)產(chǎn)生非常多的臨時(shí)數(shù)據(jù),這些臨時(shí)數(shù)據(jù)在執(zhí)行的時(shí)候都在寄存器當(dāng)中運(yùn)算。這些數(shù)據(jù)都是屬于當(dāng)前進(jìn)程的,也就是說,當(dāng)該進(jìn)程的時(shí)間片到了之后,其他進(jìn)程占用CPU之后,這些臨時(shí)數(shù)據(jù)就會(huì)被清空。
但是會(huì)有一個(gè)情況,當(dāng)進(jìn)程的時(shí)間片到了之后,如果進(jìn)程還沒有執(zhí)行完,那么就要考慮該進(jìn)程回到CPU的情況。
因此,操作系統(tǒng)會(huì)將該進(jìn)程退出時(shí),寄存器內(nèi)的臨時(shí)數(shù)據(jù),在另外一個(gè)地方備份起來【上下文保護(hù)】,并記住這個(gè)進(jìn)程,然后清空寄存器內(nèi)的臨時(shí)數(shù)據(jù),來給下一個(gè)切換進(jìn)來的進(jìn)程使用。然后每次進(jìn)程切換的時(shí)候,都要判斷新進(jìn)來的進(jìn)程是不是之前有記錄的未執(zhí)行完的進(jìn)程,如果有記錄的話,就將之前備份的臨時(shí)數(shù)據(jù)拿出來,繼續(xù)執(zhí)行該進(jìn)程【上下文恢復(fù)】。從而實(shí)現(xiàn)上下文數(shù)據(jù)的恢復(fù)。
總結(jié):
-
進(jìn)程在切換的時(shí)候,要進(jìn)行進(jìn)程的上下文保護(hù)
-
進(jìn)程恢復(fù)運(yùn)行的時(shí)候,要進(jìn)行進(jìn)程的上下文恢復(fù)
4.環(huán)境變量
4.0環(huán)境變量的理解
為了更好的理解環(huán)境變量這個(gè)概念,下面先講個(gè)幫助理解的例子:
在Linux中,我們輸入系統(tǒng)的指令,是直接輸入的【比如ls man who等指令】、而我們自己寫的可執(zhí)行程序,也可以理解成指令。
但是我們自己寫的可執(zhí)行程序,卻要加一個(gè)./
我們查看文件類型會(huì)發(fā)現(xiàn),s和自己寫的process都是可執(zhí)行程序
那是為什么呢?這是因?yàn)橄到y(tǒng)找得到系統(tǒng)指令池的指令,找不到我們自己寫的指令。
這也就是為什么我們要執(zhí)行自己的指令,需要加上./
的原因,這里的./
是當(dāng)前路徑的意思,告訴系統(tǒng)在當(dāng)前路徑找到process這個(gè)指令去執(zhí)行。而系統(tǒng)的指令都放在了usr/bin下
如果我們想要自己的指令也可以像系統(tǒng)指令那樣執(zhí)行,通過root權(quán)限將自己的指令移動(dòng)到usr/bin這個(gè)目錄下即可?!镜俏覀儾煌扑]這樣做,因?yàn)樽约簩懙某绦蚴菦]有測試的,不穩(wěn)定也不安全,會(huì)污染系統(tǒng)指令池】
但是為什么在usr/bin這個(gè)路徑下,系統(tǒng)就找得到,而在自己這個(gè)路徑下系統(tǒng)就找不到呢?
這就跟要談的環(huán)境變量有關(guān)系了,系統(tǒng)中有一個(gè)環(huán)境變量叫做PATH
,這個(gè)環(huán)境變量是系統(tǒng)啟動(dòng)的時(shí)候定義的一個(gè)全局有效的環(huán)境變量
可以看到,每個(gè)冒號(hào)中間間隔的都是一個(gè)路徑,那么在執(zhí)行一個(gè)指令的時(shí)候,操作系統(tǒng)就會(huì)在環(huán)境變量PATH
提供的這些路徑當(dāng)中去找、找到了就執(zhí)行
如果這些路徑下都沒找到該指令的時(shí)候,就會(huì)報(bào)錯(cuò)—找不到該指令
要注意:環(huán)境變量不是只有PATH,環(huán)境變量是有很多的
4.1環(huán)境變量的基本概念
-
環(huán)境變量(environment variables)一般是指在操作系統(tǒng)中用來指定操作系統(tǒng)運(yùn)行環(huán)境的一些參數(shù)
-
如:我們?cè)诰帉慍/C++代碼的時(shí)候,在鏈接的時(shí)候,從來不知道我們的所鏈接的動(dòng)態(tài)靜態(tài)庫在哪里,但是照樣可以鏈接成功,生成可執(zhí)行程序,原因就是有相關(guān)環(huán)境變量幫助編譯器進(jìn)行查找。
-
環(huán)境變量通常具有某些特殊用途,還有在系統(tǒng)當(dāng)中通常具有全局特性
環(huán)境變量其實(shí)就是操作系統(tǒng)為了滿足不同的應(yīng)用場景而預(yù)先在系統(tǒng)內(nèi)設(shè)置很多的全局變量。
而這些變量一直都會(huì)被其他進(jìn)程所訪問到。
4.2添加環(huán)境變量—export
添加環(huán)境變量有個(gè)需要注意的問題,下面做個(gè)案例:
可不敢想下圖一樣直接將要添加的路徑直接添加到環(huán)境變量中
這樣會(huì)導(dǎo)致環(huán)境變量只剩下你所添加的這個(gè)路徑,之前的路徑都會(huì)被覆蓋的。
但是如果真的覆蓋了,其實(shí)問題也不大,因?yàn)榄h(huán)境變量這個(gè)東西,只要關(guān)掉這個(gè)命令行客戶端,然后重新打開,環(huán)境變量就會(huì)重置了。原因是啥后面才學(xué)。這里只需要知道即可
由于之前的環(huán)境變量被覆蓋,會(huì)導(dǎo)致原來系統(tǒng)的指令也用不了的。
正確的添加環(huán)境變量的方法:
輸入
export PATH=%PATH:要添加的路徑
這樣就可以在原來的環(huán)境變量上,添加一個(gè)新的路徑
這樣就可以直接像執(zhí)行系統(tǒng)指令一樣,直接執(zhí)行自己的程序,并且 which自己的指令,也會(huì)直接出現(xiàn)指令所在的路徑,因?yàn)閣hich能夠在環(huán)境變量中找到,
4.3Linux中環(huán)境變量的由來
在Linux中,用戶的根目錄下存在兩個(gè)隱藏文件,如下圖所示:
這兩個(gè)文件的內(nèi)容如下圖所示:
每次用戶登錄的時(shí)候,系統(tǒng)都會(huì)執(zhí)行一次這兩個(gè)文件,通過這兩個(gè)文件來構(gòu)建當(dāng)前用戶的shell環(huán)境變量?!具@兩個(gè)文件的內(nèi)容看不懂很正?!?/p>
為什么用戶修改環(huán)境變量每次登錄的時(shí)候,環(huán)境變量都會(huì)被重置的原因就在這這里。
用戶每次登錄,系統(tǒng)都會(huì)登錄上面所說的兩個(gè)文件來加載環(huán)境變量。
4.4常見環(huán)境變量
-
PATH : 指定命令的搜索路徑
-
HOME : 指定用戶的主工作目錄(即用戶登陸到Linux系統(tǒng)中時(shí),默認(rèn)的目錄)
-
SHELL : 當(dāng)前Shell,它的值通常是/bin/bash。
除了這些環(huán)境變量,還有很多環(huán)境變量,比如為什么我們能找到之前所輸入的指令,就是因?yàn)長inux當(dāng)中幫我們記住了我們所輸入的一些指令記錄。比如Linux內(nèi)核怎么知道我們用的是那個(gè)類型的shell呢?也是通過環(huán)境變量解決的。
環(huán)境變量其實(shí)就是操作系統(tǒng)為了滿足不同的應(yīng)用場景而預(yù)先在系統(tǒng)內(nèi)設(shè)置很多的全局變量。
輸入env指令,可以查看系統(tǒng)所有的環(huán)境變量。
比如里面有一個(gè)環(huán)境變量叫做HISTSIZE,這個(gè)環(huán)境變量的3000就是Linux系統(tǒng)能幫我們記住3000條歷史指令記錄
4.5和環(huán)境變量相關(guān)的命令
-
echo: 顯示某個(gè)環(huán)境變量值
-
export: 設(shè)置一個(gè)新的環(huán)境變量
-
env: 顯示所有環(huán)境變量
-
unset: 清除環(huán)境變量
-
set: 顯示本地定義的shell變量和環(huán)境變量
4.6通過系統(tǒng)調(diào)用獲得環(huán)境變量
下面將通過系統(tǒng)調(diào)用獲得環(huán)境變量的實(shí)驗(yàn)來加深對(duì)環(huán)境變量的理解
4.6.1 getenv
除了通過env來顯示環(huán)境變量,我們也可以通過系統(tǒng)調(diào)用來獲得環(huán)境變量。
下面做個(gè)小實(shí)驗(yàn):
我們通過getenv()
這個(gè)接口,來獲得環(huán)境變量
getenv的官方介紹:
因此我們來做個(gè)實(shí)驗(yàn):通過系統(tǒng)調(diào)用來拿到USER這個(gè)環(huán)境變量的值
實(shí)驗(yàn)的代碼如下:
Makefile文件的內(nèi)容如下:
執(zhí)行程序的結(jié)果如下:
可以看到,getenv拿到了USER這個(gè)環(huán)境變量的值
因此,如果USER環(huán)境變量改變了,這里執(zhí)行的結(jié)果也會(huì)進(jìn)行改變
實(shí)驗(yàn)如下:登錄root用戶,然后再執(zhí)行此文件
輸入su -
登錄root用戶,此時(shí)發(fā)現(xiàn)USER環(huán)境變量已經(jīng)加載成root了。
那此時(shí)在執(zhí)行我們能寫的程序,結(jié)果會(huì)跟著改變嗎?
如下圖所示
結(jié)果與預(yù)期相符。通過系統(tǒng)調(diào)用能夠獲得環(huán)境變量
既然系統(tǒng)調(diào)用能夠獲得環(huán)境變量,這樣就能夠判斷當(dāng)前用戶的身份了,從而就可以判斷當(dāng)前用戶是否有權(quán)限去訪問某個(gè)文件了。
【這也就是為什么用普通用戶身份無法訪問一些文件,因?yàn)橄到y(tǒng)通過拿到用戶的USER環(huán)境變量,來判斷當(dāng)前用戶這個(gè)身份有沒有權(quán)限訪問該文件**(if語句判斷),在拿到當(dāng)前文件的屬性是能夠被誰訪問的(stat拿到文件屬性),從而判斷當(dāng)前用戶沒有權(quán)限訪問該文件,從而輸出Permission denied**】
下面手動(dòng)實(shí)現(xiàn)一下權(quán)限是否足夠的判斷:
實(shí)驗(yàn)結(jié)果:
還可以再講一個(gè)加深理解環(huán)境變量的例子:
ls指令不論什么時(shí)候都可以知道用戶當(dāng)前所處的目錄,憑什么?為什么執(zhí)行自己寫的程序的時(shí)候,需要
./mycode
,而ls mycode
,不需要ls ./mycode
?這是因?yàn)閘s每次都知道當(dāng)前的路徑,自然也不需要用戶手動(dòng)添加相對(duì)路徑給shell了。那ls憑什么知道用戶所處的路徑呢?——憑環(huán)境變量PWD
ls也是一個(gè)可執(zhí)行程序,是一個(gè)指令,因此每次它執(zhí)行都相當(dāng)于bash的子進(jìn)程,都可以繼承到全局屬性的環(huán)境變量,因此每次執(zhí)行l(wèi)s,ls都可以通過環(huán)境變量PWD來知道當(dāng)前路徑,自然就不需要用戶手動(dòng)告訴shell相對(duì)路徑了
而每次變更路徑的時(shí)候,bash都會(huì)及時(shí)的更新環(huán)境變量PWD,而ls每次執(zhí)行又可以繼承到全局屬性的環(huán)境變量,因此不管用戶在哪里ls,都可以通過環(huán)境變量PWD來獲取當(dāng)前路徑。
4.6.2 putenv
這個(gè)系統(tǒng)調(diào)用,目前來說用不到。**功能就是添加或者修改一個(gè)環(huán)境變量。**后面學(xué)習(xí)完進(jìn)程控制,自己寫一個(gè)簡單的命令行解釋器的時(shí)候會(huì)使用它
4.7本地變量
系統(tǒng)的環(huán)境變量可以說是一個(gè)全局有效的變量,在Linux中除了這種全局變量,還可以定義局部變量
可以看到通過echo是可以獲得到該環(huán)境變量的,但是這個(gè)并不是添加了一個(gè)系統(tǒng)的環(huán)境變量
如上圖所示,env展示的系統(tǒng)環(huán)境變量中并沒有myval的存在
說明這個(gè)myval是一個(gè)shell創(chuàng)建的一個(gè)局部變量,只在shell有效
但是如果非要查看到myval的存在,可以用set,set展示的變量巨多,包括了環(huán)境變量和本地變量
下面做一個(gè)實(shí)驗(yàn):通過getenv來看看是否能夠獲取到變量myval
代碼如下:
執(zhí)行程序的結(jié)果如下:
想要myval變成系統(tǒng)的環(huán)境變量可以使用export來導(dǎo)入
但是這個(gè)導(dǎo)入的環(huán)境變量也只是臨時(shí)的,只需要重啟shell就會(huì)消失。因?yàn)橹貑hell會(huì)重新根據(jù)環(huán)境變量的配置文件來導(dǎo)入環(huán)境變量
總結(jié):
- 環(huán)境變量是全局的,代表它是可以被子進(jìn)程繼承的。因?yàn)閙ycode程序運(yùn)行時(shí),對(duì)于bash來說,就是一個(gè)子進(jìn)程,但是它仍然可以獲取環(huán)境變量。
為什么子進(jìn)程需要繼承環(huán)境變量呢?——因?yàn)榭梢詽M足不同的應(yīng)用場景,比如執(zhí)行命令時(shí)候的身份認(rèn)證,PATH的指令路徑
- 本地變量就無法被繼承。它只對(duì)當(dāng)前進(jìn)程(bash)有效
4.8main函數(shù)的參數(shù)
4.8.1命令行參數(shù)
之前的學(xué)習(xí)中,又見到過main函數(shù)是有3個(gè)形參的。這個(gè)參數(shù)叫做命令行參數(shù)
int main(int argc, char *argv[], char *envp[]);
這里的這個(gè)argc是決定 argv這個(gè)指針數(shù)組有多少個(gè)元素的。而argv這個(gè)指針數(shù)組裝的都是char*指針,一般來說都是字符串
這里做個(gè)實(shí)驗(yàn)來看看argv這個(gè)指針數(shù)組內(nèi)裝的字符串都是什么
自動(dòng)化構(gòu)建工具M(jìn)akefile文件的內(nèi)容:
用c99是因?yàn)榇a中出現(xiàn)了for(int i = 0)這個(gè)代碼
代碼如下:
執(zhí)行結(jié)果如下:
可以看到只有1個(gè)元素,下標(biāo)為0的第一個(gè)元素是這個(gè)可執(zhí)行文件的名字
如果將在執(zhí)行的時(shí)候加n個(gè)選項(xiàng),那么argc就會(huì)是n+1,argv數(shù)組就會(huì)有n+1個(gè)元素,如下圖所示:
那這個(gè)是怎么實(shí)現(xiàn)的呢?
其實(shí)就是我們輸?shù)闹噶钇鋵?shí)是一個(gè)長字符串,然后shell會(huì)將我們的指令以空格為分隔符,將這個(gè)長字符串切割成一個(gè)個(gè)小字符串,也就是一個(gè)個(gè)指令,然后每個(gè)指令都是一個(gè)字符串類型,然后讓根據(jù)argc來開辟argv的空間,然后讓argv存儲(chǔ)著一個(gè)個(gè)指令。
看下圖可以更好的理解:
4.8.1.1命令行參數(shù)的意義
可以通過輸入分割出來的小字符串來實(shí)現(xiàn)不同功能的實(shí)現(xiàn)——即argc和argv的應(yīng)用
下面是便于理解的例子:
下面是實(shí)驗(yàn)結(jié)果:
經(jīng)過這個(gè)實(shí)驗(yàn)結(jié)果,可以看到命令行參數(shù)存在的意義:利用argc和argv兩個(gè)命令行參數(shù),執(zhí)行同一個(gè)程序,但是可以通過不同的選項(xiàng)來實(shí)現(xiàn)不同的功能
這個(gè)非常常見!ls指令就是如此!
在window中也有一個(gè)程序可以通過不同選項(xiàng)二實(shí)現(xiàn)不同功能的場景,如下圖所示:
4.8.2環(huán)境變量參數(shù)—char* env[]
env這個(gè)環(huán)境變量參數(shù),也是指針數(shù)組類型,裝著的就是系統(tǒng)中env所展示的環(huán)境變量
他的結(jié)構(gòu)和argv是一樣的,只是每個(gè)指針變量都指向一個(gè)環(huán)境變量 。因此可以看出,環(huán)境變量其實(shí)是被系統(tǒng)當(dāng)做一行字符串的。
下面做個(gè)實(shí)驗(yàn)——通過環(huán)境變量參數(shù)來獲取環(huán)境變量
代碼如下:
for循環(huán)這樣寫是因?yàn)?#xff0c;env[i]的最后一個(gè)元素是NULL,因此肯定會(huì)停止循環(huán)
實(shí)驗(yàn)結(jié)果:
4.8.3總結(jié)
那學(xué)習(xí)了命令行參數(shù)和環(huán)境變量參數(shù)之后,就知道,實(shí)際上在main函數(shù)運(yùn)行的時(shí)候,系統(tǒng)是會(huì)向main函數(shù)這個(gè)子進(jìn)程傳兩個(gè)表的,一個(gè)表是命令行參數(shù)表,一個(gè)表是環(huán)境變量表。
這也就是為什么之前說,環(huán)境變量是能夠繼承給子進(jìn)程的
因此實(shí)際上自己的程序在執(zhí)行之前,系統(tǒng)是會(huì)幫我們做非常多事情的。
4.9環(huán)境變量的組織方式
前面說了,main函數(shù)運(yùn)行的時(shí)候,系統(tǒng)會(huì)向其傳兩個(gè)表,而環(huán)境變量就是通過傳環(huán)境變量表傳給main函數(shù)的。但其實(shí)c語言還提供了一個(gè)變量來獲得環(huán)境變量——environ
這個(gè)environ是一個(gè)二級(jí)指針,指向的就是環(huán)境變量的表的開頭
每個(gè)程序都會(huì)收到一張環(huán)境表,環(huán)境表是一個(gè)字符指針數(shù)組,每個(gè)指針指向一個(gè)以’\0’結(jié)尾的環(huán)境字符串
因此,可以不通過環(huán)境變量參數(shù)env來獲取環(huán)境變量,也可以通過environ變量來獲取環(huán)境變量。
代碼如下:
libc中定義的全局變量environ指向環(huán)境變量表,environ沒有包含在任何頭文件中,所以在使用時(shí) 要用extern聲明。
執(zhí)行結(jié)果如下:
4.10獲取環(huán)境變量的3種方式
- 通過c語言提供的接口——系統(tǒng)調(diào)用來獲取環(huán)境變量【
getenv
】 - 通過命令行參數(shù)中的環(huán)境變量參數(shù)——
char *env[]
- 通過c語言提供的一個(gè)全局變量——
char **environ
這三個(gè)獲取方式更推薦
getenv
,因?yàn)楹芏鄨鼍岸疾皇且@取全部的環(huán)境變量,而是按照需要的環(huán)境變量去獲取。而getenv
可以直接通過環(huán)境變量的名字來獲取到想要的環(huán)境變量