中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

tplink虛擬服務(wù)器做網(wǎng)站百度網(wǎng)盤網(wǎng)頁版登錄首頁

tplink虛擬服務(wù)器做網(wǎng)站,百度網(wǎng)盤網(wǎng)頁版登錄首頁,淘寶聯(lián)盟的網(wǎng)站怎么做的,外貿(mào)手機網(wǎng)站建設(shè)一,前言 創(chuàng)建子進程的目的之一就是為了代勞父進程執(zhí)行父進程的部分代碼,也就是說本質(zhì)上來說父子進程都是執(zhí)行的同一個代碼段的數(shù)據(jù),在子進程修改數(shù)據(jù)的時候進行寫時拷貝修改數(shù)據(jù)段的部分數(shù)據(jù)。 但是還有一個目的——將子進程在運行時指向一個…

一,前言

????????創(chuàng)建子進程的目的之一就是為了代勞父進程執(zhí)行父進程的部分代碼,也就是說本質(zhì)上來說父子進程都是執(zhí)行的同一個代碼段的數(shù)據(jù),在子進程修改數(shù)據(jù)的時候進行寫時拷貝修改數(shù)據(jù)段的部分數(shù)據(jù)。

? ? ? ? 但是還有一個目的——將子進程在運行時指向一個全新的程序代碼,也就是我們的進程程序替換。

????????一般情況下,對應(yīng)的語言寫的程序只能調(diào)用對應(yīng)的語言的接口,而不能調(diào)用其他語言的接口,如C++不能調(diào)用Java或者Python或者Shell等語言的接口,那么如果我們想要調(diào)用別人寫的程序應(yīng)該怎么辦呢?

????????那么進程程序替換就能夠很好地幫助我們解決這個問題,這在很大程度上減少了我們編程的成本,學(xué)會進程程序替換,在很多時候,如果有現(xiàn)成的程序,那么我們不需要自己再去寫一個,是不是方便很多了?

二、什么是進程程序替換?

????????所謂進程程序替換,顧名思義,就是使用一個新的程序替換原有的程序,進程將執(zhí)行新程序的代碼,而不再執(zhí)行原有程序的代碼,前面我們已經(jīng)學(xué)習(xí)了如何創(chuàng)建一個進程,一般情況下,進程程序替換都不會使用父進程直接進行進程程序替換,而是讓父進程調(diào)用fork()函數(shù)創(chuàng)建一個子進程,讓子進程去執(zhí)行一個新的程序即可

????????進程程序替換是指在運行過程中將一個進程的地址空間中的代碼、數(shù)據(jù)和堆棧等內(nèi)容完全替換為另一個程序的代碼、數(shù)據(jù)和堆棧的過程。

三,進程程序替換的原理?

  • ?進程替換前的效果圖

當(dāng)一個進程成功創(chuàng)建一個子進程之后,父子進程的情況如下圖所示:

????????這個時候,我們這里先針對代碼和數(shù)據(jù)進行分析,其他內(nèi)容暫不做考慮,此時父子進程都沒有修改代碼和數(shù)據(jù),因此,父子進程的代碼和數(shù)據(jù)都是指向同一塊內(nèi)容的,也就是代碼和數(shù)據(jù)共享的,如果其中一方對數(shù)據(jù)進行修改,則這一方就會進行寫時拷貝,如果想要執(zhí)行不同的代碼,則此時就要進行進程程序替換

進程程序替換的原理:
????????假如剛開始父子進程都是執(zhí)行程序a.exe,后面,想要讓子進程執(zhí)行b.exe了,那么此時就要進行進程程序替換,替換的過程就是首先將b.exe從磁盤加載進內(nèi)存,然后重新建立子進程的頁表,更新子進程的頁表中的映射關(guān)系(注意,這里修改的是頁表中的物理地址而不是虛擬地址,此時父子進程代碼塊中虛擬地址是一樣的,但是通過頁表映射出來的物理地址是不一樣的),從而實現(xiàn)父子進程的代碼徹底分離,此時父子進程的代碼是互不干擾的,很好地滿足了進程的獨立性

  • ?進程替換之后的效果圖

?3.1.進程替換注意事項

  • 1.進程替換不會創(chuàng)建新進程,因為進程替換只是將該進程的數(shù)據(jù)替換為指定的可執(zhí)行程序。而進程PCB沒有改變,所以不是新的進程,進程替換后不會發(fā)生進程pid改變
  • 2.進程替換后,如果替換成功后則替換函數(shù)下的代碼不會執(zhí)行,因為進程替換是覆蓋式的替換,替換成功后進程原來的代碼就消失了。同理在進程替換失敗后會執(zhí)行替換函數(shù)后的代碼
  • 3.進程替換函數(shù)在進程替換成功后不返回,函數(shù)的返回值表示替換失敗
  • 4.進程替換成功后,退出碼為替換后的進程的退出碼

四,為什么要進行進程程序替換

????????在學(xué)習(xí)進程程序替換之前,我們知道當(dāng)一個父進程創(chuàng)建一個子進程之后,父子進程的代碼是共享的,子進程只能執(zhí)行父進程的代碼塊

????????但是現(xiàn)在我們的需求增加了,我們不僅要讓子進程能夠執(zhí)行父進程的代碼塊,也要能夠讓子進程能夠做一些父進程不能做的事情,也就是能夠執(zhí)行一個全新的代碼(程序),這樣就能實現(xiàn)父子進程做的事情有所差異,大大提高了辦事效率,同時也使父子進程的代碼徹底分離,維護進程的獨立性

五,怎么實現(xiàn)進程程序替換

????????進程程序替換是指在運行過程中將一個進程的地址空間中的代碼、數(shù)據(jù)和堆棧等內(nèi)容完全替換為另一個程序的代碼、數(shù)據(jù)和堆棧的過程。

這個過程通常是由操作系統(tǒng)提供的 exec 系列函數(shù)來實現(xiàn)的:

  1. 地址空間替換:進程的地址空間是指進程可以訪問的內(nèi)存范圍。通過地址空間替換,進程可以在運行時動態(tài)地加載并執(zhí)行不同的程序,從而實現(xiàn)靈活的程序執(zhí)行和管理。
  2. exec 函數(shù)族:exec 函數(shù)族是一組系統(tǒng)調(diào)用,用于執(zhí)行程序替換操作。這些函數(shù)包括 execl, execv, execle, execve 等,它們允許以不同的方式傳遞參數(shù)給新程序,并執(zhí)行地址空間替換。(我們要改變內(nèi)存,那肯定是要調(diào)用系統(tǒng)調(diào)用接口的,這些函數(shù)會封裝相應(yīng)的接口)
  3. 程序入口點:新程序的入口點是程序中的起始執(zhí)行位置,通常是 main 函數(shù)或其他指定的入口函數(shù)。替換完成后,控制權(quán)將轉(zhuǎn)移到程序入口點,開始執(zhí)行新程序的代碼。

5.1.原理

  • 當(dāng)進程調(diào)用一種exec函數(shù)時,該進程的用戶空間代碼和數(shù)據(jù)完全被新程序替換
  • 替換完成后,控制權(quán)將轉(zhuǎn)移到新程序的入口點,開始執(zhí)行新程序的代碼。

5.2.使用execl()函數(shù)

????????在學(xué)習(xí)使用進程程序替換的相關(guān)接口之前我們首先需要明確一點,這個在使用接口的時候需要做什么事情?

????????很明顯,最基本的我們首先得知道這個程序在哪里,其次,我們還需要知道怎么執(zhí)行這個程序(比如在我們前面學(xué)習(xí)一些指令的時候,有些指令是可以攜帶選項的有些指令可以不用攜帶選項)。

????????總結(jié)起來就是我們需要知道要執(zhí)行的程序的路徑和怎么執(zhí)行新程序

????????execl函數(shù)是Linux系統(tǒng)中用于執(zhí)行新程序的函數(shù)之一,它屬于exec函數(shù)族的一部分。

????????這個函數(shù)的作用是在當(dāng)前進程的上下文中啟動一個新的程序,并替換當(dāng)前進程的映像為新的程序映像。調(diào)用execl函數(shù)后,當(dāng)前進程將停止執(zhí)行,并由新的程序開始執(zhí)行.

函數(shù)原型如下

參數(shù)說明:

  • path:要執(zhí)行的程序的路徑。
  • arg0:新程序的參數(shù)列表的開始,通常這會是新程序的名稱(盡管這不是強制的,但它通常用于錯誤消息和程序內(nèi)部)。
  • ...:一個可變參數(shù)列表(參數(shù)的數(shù)量不固定),新程序的參數(shù)列表,必須以NULL結(jié)尾。

????????execl函數(shù)會根據(jù)提供的路徑path找到并執(zhí)行相應(yīng)的程序,同時將arg0及其后面的參數(shù)作為新程序的命令行參數(shù)傳遞。注意,參數(shù)列表必須以NULL結(jié)尾,這是告訴execl參數(shù)列表結(jié)束的標(biāo)志。?

??只看上面的解釋,我相信小伙伴們對于這一塊還是不太理解,那么上代碼:

?我們來看個例子

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{printf("I'm a process, pid: %d\n", getpid());printf("execl begin...\n");int a=execl("/usr/bin/ls", "ls", "-a", "-l", NULL);printf("execl end...\n");return 0;
}

????????如果execl函數(shù)調(diào)用成功,那么它實際上不會返回,因為當(dāng)前進程的映像已經(jīng)被新程序替換。如果調(diào)用失敗,它會返回-1,并設(shè)置全局變量errno以指示錯誤原因。常見的錯誤原因可能包括文件未找到、權(quán)限不足等。

????????execl函數(shù)和其他exec函數(shù)一樣,不會創(chuàng)建新的進程。它們只是在當(dāng)前進程的上下文中啟動另一個程序。因此,調(diào)用execl前后,進程的ID(PID)不會改變。

????????同時,由于execl會替換整個進程映像,所以在調(diào)用execl之前,通常需要確保當(dāng)前進程的所有打開的文件描述符、內(nèi)存分配等都被適當(dāng)?shù)靥幚砘蜥尫?#xff0c;因為這些資源不會被新程序繼承。

5.2.1.結(jié)論與細節(jié)

1,程序替換一旦成功,exec后面的代碼不在執(zhí)行。因為被替換掉了,這也是什么代碼沒有輸出execl end的原因了

2,exec函數(shù)調(diào)用成功,那么它實際上不會有返回值;調(diào)用失敗,它會返回-1

3,exec函數(shù)不會創(chuàng)建新的進程。它們只是在當(dāng)前進程的上下文中啟動另一個程序

4,創(chuàng)建一個進程。我們是先創(chuàng)建PCB、地址空間、頁表等再先把程序加載到內(nèi)存

????????????????????????????????如果先加載的話,頁表都沒辦法映射的

5,程序替換的本質(zhì)就是加載 (可以看成一個加載器),有替換就是替換,沒有就是程序加載

????????程序替換的本質(zhì)是程序加載,因為在執(zhí)行 exec 函數(shù)時,操作系統(tǒng)會加載新程序的可執(zhí)行文件,并將其代碼、數(shù)據(jù)和堆棧等部分加載到進程的地址空間中。這個過程涉及將新程序的內(nèi)容從磁盤加載到內(nèi)存中,為進程提供執(zhí)行所需的資源。

????????因此,雖然我們常說是“程序替換”,但實際上更準(zhǔn)確地說是將新程序加載到內(nèi)存中,替換掉原有的程序,以實現(xiàn)進程的功能切換和更新。

6,程序運行要加載到內(nèi)存;為什么?

????????馮諾依曼體系規(guī)定;

如何加載的呢?

????????就是程序替換:程序替換是操作系統(tǒng)的接口,所謂的把磁盤里的數(shù)據(jù)加載到內(nèi)存就是把磁盤設(shè)備的數(shù)據(jù)拷貝到內(nèi)存里。把數(shù)據(jù)從一個硬件搬到另一個硬件,只有操作系統(tǒng)能做

5.3.多進程實現(xiàn)使用ls?

1,我們可以創(chuàng)建一個子進程,由子進程來進行程序替換,父進程來等待結(jié)果就可以。為什么? 父進程能得到子進程的執(zhí)行結(jié)果

2,我們知道父進程與子進程映射到同一塊代碼,那么子進程進行程序替換后,不是會覆蓋嗎,替換為什么不影響父進程?

????????進程具有獨立性,在進行程序替換時要進行寫時拷貝,寫時拷貝的本質(zhì)就是開辟新的空間

3,shell是如何運行起來一個指令的?

????????首先創(chuàng)建子進程,shell會waitpid()等待進程結(jié)果,子進程會繼承shell的代碼,但是不影響。子進程進行程序替換,替換為我們輸入的指令

?上面的實驗是沒有子進程的,是一個純單進程的實驗,下面將演示一個多進程的例子執(zhí)行l(wèi)s指令

上面的實驗思路就是父進程創(chuàng)建一個子進程,然后本來子進程是要執(zhí)行父進程的代碼塊和父進程進行代碼共享的,但是我們在子進程中調(diào)用execl函數(shù)接口,因此,在子進程中會進行程序替換

6.exec系列函數(shù)

????????由我們庫封裝的exec函數(shù)常用的有上面的幾種,這些函數(shù)都有下面的特性,當(dāng)該函數(shù)成功執(zhí)行,那么進程替換成功,代碼不再返回,如果函數(shù)調(diào)用失敗,例如不正確的地址,不正確的文件等等,函數(shù)會返回一個-1,并且exec函數(shù)之后在函數(shù)調(diào)用失敗時才有返回值,成功沒有返回值。

? ? ? ? 只有失敗時有返回值其實很好理解,因為函數(shù)調(diào)用成功那就表示程序替換成功,原來的代碼都被替換了,我返回之后給誰?沒了,之后的代碼就是新代碼了

1.execl:

該函數(shù)允許通過提供可變數(shù)量的參數(shù)來執(zhí)行指定的可執(zhí)行文件。它的原型如下:

int execl(const char *path, const char *arg0, ... /*, (char *)0 */);

path 是要執(zhí)行的可執(zhí)行文件的路徑,arg0 是第一個參數(shù),后續(xù)參數(shù)都是傳遞給可執(zhí)行文件的命令行參數(shù),以 NULL 結(jié)尾。

觀察上圖發(fā)現(xiàn)進程替換成功后,替換函數(shù)下的打印沒有執(zhí)行,原因與注意事項的第二條相同

如果替換失敗:

2.execlp:

該函數(shù)與 execl 類似,但是它會在系統(tǒng)的環(huán)境變量 PATH 指定的目錄中查找可執(zhí)行文件。它的原型如下:

int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);

file 是要執(zhí)行的可執(zhí)行文件的文件名,arg0 是第一個參數(shù),后續(xù)參數(shù)都是傳遞給可執(zhí)行文件的命令行參數(shù),以 NULL 結(jié)尾。

相比于execl函數(shù),execlp函數(shù)的第一個參數(shù)能直接寫文件名,系統(tǒng)會PATH環(huán)境變量里去查找

多的字母p的意思:PATH環(huán)境變量

int main()
{pid_t id = fork();if (id == 0){printf("I'm a process, pid: %d\n", getpid());printf("execl begin...\n");execl("ls", "ls", "-a", "-l", NULL);printf("execl end...\n");exit(1);}pid_t rid = waitpid(id, NULL, 0);if (rid > 0){printf("wait successfully\n");}return 0;
}

3.execv:

類似于 execl,但是允許傳遞一個參數(shù)數(shù)組給被執(zhí)行的程序。它的原型如下:

int execv(const char *path, char *const argv[]);

path 是要執(zhí)行的可執(zhí)行文件的路徑,argv 是一個以 NULL 結(jié)尾的參數(shù)數(shù)組,其中每個元素都是一個字符串,表示命令行參數(shù)。

相比于exec多個字母v:代表vector

int main()
{pid_t id = fork();if (id == 0){printf("I'm a process, pid: %d\n", getpid());printf("execl begin...\n");char* argv[] = { "ls","-a","-l",NULL};execv("/usr/bin/ls",argv);printf("execl end...\n");exit(1);}pid_t rid = waitpid(id, NULL, 0);if (rid > 0){printf("wait successfully\n");}return 0;
}

4.execvp:

類似于 execv,但是它會在系統(tǒng)的環(huán)境變量 PATH 指定的目錄中查找可執(zhí)行文件。它的原型如下:

int execvp(const char *file, char *const argv[]);

file 是要執(zhí)行的可執(zhí)行文件的文件名,argv 是一個以 NULL 結(jié)尾的參數(shù)數(shù)組,其中每個元素都是一個字符串,表示命令行參數(shù)。

既有字母p 又有v,結(jié)合上面那兩種就行

5.execle:

函數(shù)與 execl 函數(shù)類似,但允許在啟動新程序時傳遞額外的環(huán)境變量。它的原型如下:

int execle(const char *path, const char *arg, ..., char *const envp[]);

path 是要執(zhí)行的可執(zhí)行文件的路徑,arg 是要傳遞給新程序的命令行參數(shù),后面的參數(shù)是額外的環(huán)境變量,以 NULL 結(jié)尾。

進程程序替換不會替換環(huán)境變量的

想要子進程繼承全部的環(huán)境變量,不用管,直接就能拿到

單純新增環(huán)境變量,在父進程里使用putenv()函數(shù),會影響子進程

putenv 是 C 語言中的一個庫函數(shù),它定義在 <stdlib.h> 頭文件中。這個函數(shù)用于將字符串添加到環(huán)境變量中,或者修改已經(jīng)存在的環(huán)境變量的值。

int putenv(const char *string);

使用全新的環(huán)境變量,就使用execle()函數(shù),那么替換后的代碼切換后的環(huán)境變量就只是我們傳入的表里的內(nèi)容

?因為此時我們沒有環(huán)境變量MYSTR所以第一行打印為空

這里在myProc子進程中用execle函數(shù)來導(dǎo)入環(huán)境變量MYSTR

注意:

  • 1.導(dǎo)環(huán)境變量的數(shù)組最后以NULL結(jié)尾
  • 2.導(dǎo)入環(huán)境變量后原系統(tǒng)環(huán)境變量的值被清空,這種導(dǎo)入環(huán)境變量的方式為覆蓋式導(dǎo)入?

?6.使用方法總結(jié)

有人就說了上面那些函數(shù),我怎么記得住他們的用法啊?

?使用這些函數(shù)其實簡單,先將函數(shù)名的exec提取出來看后面的幾個字母。

l:表示用列表方式傳遞。

?? ?其中/bin/ls表示需要執(zhí)行的文件是誰,ls表示執(zhí)行方式,而-a和-l表示這個執(zhí)行的參數(shù)列表。

v:表示使用數(shù)組的方式傳遞。?

?可以看到我們用過指針數(shù)組的方式將我們的執(zhí)行和參數(shù)列表存到了一起,然后將這個指針數(shù)組作為參數(shù)傳遞給我們的execv函數(shù)就行。

p:表示自己只需要傳遞需要執(zhí)行的文件是誰,操作系統(tǒng)會從默認環(huán)境變量當(dāng)中去查找。

?e:表示可以傳遞自己的環(huán)境變量。?

?注意:當(dāng)我們傳遞自己的環(huán)境變量時會替換默認環(huán)境變量,所以如果想要添加一個環(huán)境變量,而不是替換那就需要下方的操作。

通過系統(tǒng)提供的存環(huán)境變量的environ變量,在用putenv函數(shù)添加自己的環(huán)境變量,以達到添加環(huán)境變量的操作。

? ? ? ? 上面的幾個字母通過不同的組合可以達到不同的操作方式。

7.也可以調(diào)用其他語言的程序

code.c里:

int main()
{char* const env[] = {(char*)"first",(char*)"second",NULL };pid_t id = fork();if (id == 0){printf("I'm a process, pid: %d\n", getpid());printf("execl begin...\n");execle("./mytest", "mytest", NULL, env)printf("execl end...\n");exit(1);}pid_t rid = waitpid(id, NULL, 0);if (rid > 0){printf("wait successfully\n");}return 0;
}

?test.cpp里:

#include <iostream>
#include <unistd.h>using namespace std;int main()
{for (int i = 0; environ[i]; i++){printf("env[%d]: %s\n", i, environ[i]);}cout << "This is C++" << endl;return 0;
}

當(dāng)然我們也能傳系統(tǒng)環(huán)境變量,但是沒必要,這樣的話直接默認就行

execle("./mytest", "mytest", NULL, environ)//傳入這個全局變量

http://m.risenshineclean.com/news/63966.html

相關(guān)文章:

  • 59網(wǎng)站一起做網(wǎng)店網(wǎng)絡(luò)營銷模式
  • 免費網(wǎng)絡(luò)推廣培訓(xùn)課程seo網(wǎng)站優(yōu)化外包
  • 中文游戲制作軟件常州百度關(guān)鍵詞優(yōu)化
  • 做網(wǎng)站設(shè)像素國內(nèi)廣告投放平臺
  • 網(wǎng)站域名登陸長沙seo優(yōu)化價格
  • 蘇州網(wǎng)站建設(shè)推廣服務(wù)百度電話怎么轉(zhuǎn)人工客服
  • 怎么做網(wǎng)站免費的刷贊百度seo正規(guī)優(yōu)化
  • 廣州網(wǎng)站外貿(mào)推廣seo有哪些網(wǎng)站
  • 哪家手表網(wǎng)站鞏義網(wǎng)絡(luò)推廣
  • 大型網(wǎng)站開發(fā) 框架網(wǎng)絡(luò)搜索關(guān)鍵詞排名
  • 凡科做的網(wǎng)站為什么打不開十大跨界營銷案例
  • 做網(wǎng)站需要哪些素材網(wǎng)站優(yōu)化排名軟件
  • wordpress javascript廣告插件seo排名推廣
  • 網(wǎng)站做優(yōu)化多少錢牛推網(wǎng)
  • 汶上云速網(wǎng)站建設(shè)如何找做網(wǎng)站的公司
  • 北京微信網(wǎng)站建設(shè)費用北京seo優(yōu)化公司
  • 網(wǎng)站建設(shè)有什么方法連接數(shù)據(jù)庫網(wǎng)絡(luò)營銷師證
  • 政府網(wǎng)站建設(shè)新模式網(wǎng)站排名優(yōu)化軟件聯(lián)系方式
  • 開鎖都在什么網(wǎng)站做最有效的推廣學(xué)校的方式
  • 諸城做網(wǎng)站找個人種子搜索神器 bt 下載
  • 網(wǎng)站建設(shè) 價格新聞軟文自助發(fā)布平臺
  • 大連app制作seo外包優(yōu)化網(wǎng)站
  • jsp做網(wǎng)站能實現(xiàn)什么功能百度網(wǎng)盤搜索引擎
  • .網(wǎng)站開發(fā)工具dw搜索引擎付費推廣
  • .net 創(chuàng)建網(wǎng)站項目網(wǎng)絡(luò)營銷的主要特點有哪些
  • 關(guān)于網(wǎng)站建設(shè)相關(guān)文章武漢 網(wǎng)絡(luò) 推廣
  • 南京網(wǎng)站流量優(yōu)化輕松seo優(yōu)化排名 快排
  • 建設(shè)公司網(wǎng)站要注意哪些杭州網(wǎng)站排名提升
  • 化妝品網(wǎng)站建設(shè)項目計劃書今日新聞頭條
  • wordpress建站速度提升免費推廣途徑與原因