當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > TN0015_fork函數(shù)替換為SylixOS進(jìn)程
修訂歷史
版本 日期 原因
V1.00 2016/12/04 創(chuàng)建文檔
V1.10 2017/02/05 修改文檔
目錄
1. 適用范圍 1
2. 原理介紹 1
2.1 Linux下fork函數(shù)功能淺析 1
2.2 posix_spawn原型介紹 1
3. 技術(shù)實(shí)現(xiàn) 2
3.1 文件描述符 2
3.2 全局變量 3
3.3 守護(hù)進(jìn)程 4
4. posix_spawn源碼實(shí)現(xiàn)框圖 4
5. 參考資料 6
附錄一:設(shè)置文件描述符不可復(fù)制 6
1. 適用范圍
SylixOS是一款為嵌入式系統(tǒng)設(shè)計(jì)的硬實(shí)時(shí)系統(tǒng)。為了保證系統(tǒng)的實(shí)時(shí)性,系統(tǒng)創(chuàng)建子進(jìn)程時(shí)不做頁(yè)表切換(頁(yè)表切換很耗時(shí)間,不利于實(shí)時(shí)性的體現(xiàn)),即父子進(jìn)程共享同一個(gè)頁(yè)表,而對(duì)于Linux下fork函數(shù)創(chuàng)建的父子進(jìn)程是需要進(jìn)行頁(yè)表復(fù)制和切換的。為了在SylixOS下實(shí)現(xiàn)Linux的fork函數(shù)功能,本文總結(jié)了如何使用posix標(biāo)準(zhǔn)的posix_spawn函數(shù)替換fork函數(shù)。
2. 原理介紹
SylixOS的posix_spawn函數(shù)是基于posix標(biāo)準(zhǔn)的,是fork函數(shù)和exec函數(shù)的功能合二為一,它只是創(chuàng)建一個(gè)新進(jìn)程并執(zhí)行指定程序。
2.1 Linux下fork函數(shù)功能淺析
由fork函數(shù)創(chuàng)建的子進(jìn)程獲得父進(jìn)程的堆棧、數(shù)據(jù)段和執(zhí)行文本段的拷貝,實(shí)質(zhì)上我們可以這樣理解:即子進(jìn)程完全復(fù)制父進(jìn)程的頁(yè)表(對(duì)于有寫時(shí)拷貝機(jī)制的fork函數(shù)我們也可以這么理解)。
父子進(jìn)程均可修改各自的棧數(shù)據(jù)、以及堆段中的變量,而不影響另一進(jìn)程。程序可以通過(guò)fork函數(shù)的返回值來(lái)區(qū)別父子進(jìn)程,在父進(jìn)程中fork函數(shù)將返回子進(jìn)程的進(jìn)程ID。鑒于父進(jìn)程可能需要?jiǎng)?chuàng)建,進(jìn)而追蹤多個(gè)子進(jìn)程(通過(guò)wait函數(shù)或類似的方法)。fork函數(shù)在子進(jìn)程中返回0,子進(jìn)程可以通過(guò)getpid函數(shù)以獲得自身ID,可以使用getppid函數(shù)獲得父進(jìn)程的ID。
父子進(jìn)程之間文件共享,子進(jìn)程獲得父進(jìn)程所有文件描述符號(hào)的副本(副本的創(chuàng)建類似于dup函數(shù)的功能),且父子進(jìn)程中對(duì)應(yīng)的描述符均指向相同的文件句柄(即公用一個(gè)文件結(jié)構(gòu)和文件節(jié)點(diǎn)),共享同一個(gè)文件句柄,這樣公用的文件偏移量保證了父子進(jìn)程寫同一個(gè)文件時(shí)不會(huì)覆蓋彼此寫入的內(nèi)容(但是父子進(jìn)程的輸出會(huì)隨意混雜在一起,可用進(jìn)程間同步來(lái)規(guī)避)。
總的來(lái)說(shuō)fork函數(shù)創(chuàng)建子進(jìn)程,復(fù)制父進(jìn)程的信息可分為主要三個(gè)方面:
1、復(fù)制父進(jìn)程的文件描述符表;
2、復(fù)制父進(jìn)程數(shù)據(jù)段;
3、復(fù)制父進(jìn)程的環(huán)境變量。
對(duì)于SylixOS系統(tǒng)來(lái)說(shuō)不提供fork函數(shù),也沒(méi)有提供與fork函數(shù)相同功能的函數(shù)。而SylixOS提供一個(gè)posix標(biāo)準(zhǔn)的posix_spawn函數(shù),我們可以根據(jù)fork函數(shù)功能進(jìn)行使用posix_spawn函數(shù)替換fork函數(shù)。
2.2 SylixOS的posix_spawn函數(shù)原型介紹
#include <spawn.h>
int posix_spawn(pid_t *pid,
const char *path,
constposix_spawn_file_actions_t *file_actions,
constposix_spawnattr_t *attrp,
char *const argv[],
char *const envp[]);
函數(shù)成功返回 0,失敗返回-1 并設(shè)置錯(cuò)誤碼。函數(shù)參數(shù)如表2 1函數(shù)參數(shù)對(duì)比:
表2 1函數(shù)參數(shù)
項(xiàng)目 posix_spawn
進(jìn)程號(hào)pid 新的進(jìn)程號(hào)
文件操作集file_actions 新進(jìn)程啟動(dòng)時(shí)需要處理的文件操作集, 為 0 表示不進(jìn)行任何文件操作
新進(jìn)程初始化屬性attrp 新進(jìn)程初始化屬性,為 NULL 表示不設(shè)置
命令行參數(shù)字符串?dāng)?shù)組argv 命令行參數(shù)組成的字符串?dāng)?shù)組,數(shù)組以可執(zhí)行文件名開(kāi)始以 NULL結(jié)束,為 NULL 表示不使用命令行參數(shù)多64個(gè)
進(jìn)程環(huán)境變量字符串?dāng)?shù)組envp 需要預(yù)先設(shè)置的進(jìn)程環(huán)境變量字符串?dāng)?shù)組,數(shù)組以 NULL 結(jié)束,為NULL 表示不需要設(shè)置環(huán)境變量不超過(guò)64個(gè)
可執(zhí)行文件路徑path path 是可執(zhí)行文件路徑
根據(jù)posix_spawn函數(shù)原型和功能可知,針對(duì)fork函數(shù)創(chuàng)建子進(jìn)程時(shí)復(fù)制的主要三個(gè)方面有如下的方法替代:
1. 復(fù)制文件描述符表:posix_spawn函數(shù)自身在創(chuàng)建子進(jìn)程時(shí)也復(fù)制父進(jìn)程所有的文件描述符,父子進(jìn)程的文件描述符表指向同一個(gè)文件結(jié)構(gòu),這個(gè)和fork函數(shù)一樣;
2. 復(fù)制數(shù)據(jù)段:posix_spawn函數(shù)可以通過(guò)第五個(gè)參數(shù)指針數(shù)組argv[ ]進(jìn)行數(shù)據(jù)傳遞,對(duì)于對(duì)父進(jìn)程的代碼段的復(fù)制只能通過(guò)再次編寫來(lái)解決;
3. 復(fù)制壞境變量:posix_spawn函數(shù)可以使用第六個(gè)參數(shù)數(shù)指針數(shù)組envp[ ]來(lái)傳遞父進(jìn)程的環(huán)境參數(shù),并且可以認(rèn)為設(shè)置envp[ ]參數(shù)來(lái)設(shè)置子進(jìn)程的環(huán)境參數(shù)。
注:因?yàn)樵赟ylixOS父子進(jìn)程因?yàn)槭枪蚕硗粡堩?yè)表的,所以對(duì)于SylixOS操作系統(tǒng)的父子進(jìn)程天生就有共享內(nèi)存(即共享同一張頁(yè)表地址),不過(guò)需要注意如果父子進(jìn)程通過(guò)使用同一張頁(yè)表同一個(gè)地址來(lái)傳遞數(shù)據(jù)很危險(xiǎn),需謹(jǐn)慎使用(比如子進(jìn)程到共享頁(yè)表地址進(jìn)行讀寫操作,不小心踩到父進(jìn)程的堆�?臻g會(huì)造成不可估量的危險(xiǎn))。
3. 技術(shù)實(shí)現(xiàn)
3.1 文件描述符
例程描述:
父進(jìn)程創(chuàng)建子進(jìn)程前已經(jīng)打開(kāi)一個(gè)文件,父進(jìn)程將文件描述符值傳遞給子進(jìn)程,父、子進(jìn)程共同對(duì)同一文件進(jìn)行寫操作。
例程總結(jié):
父進(jìn)程在創(chuàng)建子進(jìn)程時(shí),子進(jìn)程復(fù)制父進(jìn)程的文件描述符表,所以只需要通過(guò)傳參的方式把文件描述符告知給子進(jìn)程,子進(jìn)程就能夠使用這個(gè)文件描述符,深入了解后發(fā)現(xiàn)使用posix_spawn函數(shù)創(chuàng)建子進(jìn)程,父子進(jìn)程也是公用一個(gè)文件結(jié)構(gòu)和文件節(jié)點(diǎn)。posix_spawn函數(shù)也支持執(zhí)行時(shí)關(guān)閉(close-on-exec) 標(biāo)志,即文件描述符設(shè)置FD_CLOEXEC標(biāo)志,在創(chuàng)建子進(jìn)程時(shí)子進(jìn)程不能復(fù)制該文件描述符 。
注:close-on-exec標(biāo)志可通過(guò)fnctl函數(shù)對(duì)文件描述符設(shè)置,具體實(shí)現(xiàn)可參考附錄一。
3.2 全局變量
例程描述:
父進(jìn)程創(chuàng)建子進(jìn)程時(shí)將全局變量值傳遞給子進(jìn)程,隨后父進(jìn)程對(duì)全局變量進(jìn)行加1操作,子進(jìn)程對(duì)接收到的全局變量值也進(jìn)行加1操作。
例程總結(jié):
父進(jìn)程可通過(guò)傳遞參數(shù)的方式將子進(jìn)程需要的數(shù)據(jù)傳遞給子進(jìn)程,這樣父子進(jìn)程都有自己的數(shù)據(jù),且互不干擾。
3.3 守護(hù)進(jìn)程
例程描述:
父進(jìn)程創(chuàng)建子進(jìn)程,子進(jìn)程執(zhí)行daemon函數(shù)將自己設(shè)為守護(hù)進(jìn)程,父進(jìn)程手動(dòng)退出。
例程總結(jié):
SylixOS提供了設(shè)置守護(hù)進(jìn)程daemon函數(shù),該函數(shù)內(nèi)部包含了部分fork函數(shù)創(chuàng)建守護(hù)進(jìn)程的相關(guān)操作。
daemon原型介紹
SylixOS提供API接口daemon函數(shù),可以設(shè)置當(dāng)前進(jìn)程為守護(hù)進(jìn)程。
#include <unistd.h>
int daemon(int nochdir, int noclose);
函數(shù) daemon 原型分析:
此函數(shù)成功返回 0,失敗返回-1 并設(shè)置錯(cuò)誤碼;
參數(shù) nochdir 表示是否切換進(jìn)程當(dāng)前工作目錄到根目錄“ /”。 0 表示切換, 其他表
示不切換;
參數(shù) noclose 表示是否重定向標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出到“ /dev/null”
文件。 0 表示重定向, 其他表示不重定向
4. posix_spawn函數(shù)源碼實(shí)現(xiàn)
posix_spawn函數(shù)中的流程實(shí)現(xiàn)
對(duì)于posix_spawn函數(shù)實(shí)現(xiàn)的核心步驟__processStart的實(shí)現(xiàn)流程:
__processStart函數(shù)的實(shí)現(xiàn)流程
5. 參考資料
《 SylixOS 應(yīng)用開(kāi)發(fā)手冊(cè)》
附錄一置文件描述符不可復(fù)制
1.在open函數(shù)打開(kāi)時(shí)設(shè)置標(biāo)志位:
iFd = open("./filetest", O_RDWR | O_CREAT | O_CLOEXEC , FILE_MODE);
加上這個(gè)標(biāo)志:O_CLOEXEC
2.使用fcntl函數(shù)設(shè)置文件描述符不可復(fù)制:
fcntl(iFd, F_SETFD, 0);
注:0表示不設(shè)置標(biāo)志位,1表示設(shè)置標(biāo)志位
华清图书馆
0元电子书,限时免费申领10本华清图书PDF版
扫码关注华清远见公众号