2021-05-12 14:32:11
SylixOS 的system使用
1. 適用範圍
SylixOS是一款為大型嵌入式系統設計的硬實時系統,支援使用system呼叫執行命令。SylixOS為了保證實時性在system的實現上和Linux有所差別,本文著重介紹SylixOS如何實現system和在使用system時需要注意的事項。
2. 原理介紹
SylixOS為保證系統的實時性所以沒有實現fork功能,Linux下system是使用fork實現的。而SylixOS則通過使用核心的shell執行緒實現system功能。
2.1 Linux的system功能淺析
Linux下system會呼叫fork產生子進程,由子進程execve呼叫/bin/sh-c string來執行引數string字串所代表的命令,此命令執行完後隨即返回原呼叫的進程。
因為Linux下是通過fork實現system,所以被執行的命令繼承父系的一些資源(比如檔案描述符,父系的工作路徑等)。同時能夠實現非同步執行和同步執行,同步執行即父系等待system呼叫執行結束(包括system呼叫的命令執行結束);非同步即不等待,父系繼續執行。
2.2
SylixOS的system原理介紹
#include<stdlib.h> intsystem(constchar *command); |
函數成功返回 0,失敗返回-1,並設定錯誤碼。
SylixOS的system是先建立一個核心的shell執行緒,然後通過核心的shell執行緒執行system需要執行的命令。
如果使用system呼叫執行一個進程,則同時啟動一個核心執行緒來join等待清除該進程。如果使用system呼叫執行一個shell命令,則直接由核心執行緒t_tshell負責清除。如圖 21所示,由open(pid=5)呼叫system執行hellow(pid=6),而核心建立一個hellow(pid=0)的核心執行緒join等待。
圖 21 system呼叫現象
2.3 SylixOS的system功能
SylixOS 的system實現原理和Linux不同,功能上和Linux的基本相同。
1. SylixOS實現system基礎功能,呼叫執行命令;
2. SylixOS 的system執行命令可設定為同步執行和非同步執行。
3. SylixOS的system繼承父係進程的工作空間;
4. SylixOS中由system啟動的進程繼承核心執行緒的棧空間大小;
5.Linux的system呼叫的三者有血緣關係,所以被system呼叫的進程繼承父系的資源(包括檔案描述符),而SylixOS的system呼叫的三者之間沒有血緣關係,所以不能夠繼承父系的資源。所以SylixOS在使用system時需要注意,在技術實現章節會介紹如何實現system的這個功能。
3. 技術實現
在移植Linux應用程式時,在某些特定的場景上Linux使用者會在A進程通過system呼叫B進程,同時通過傳參把一些檔案描述符傳遞到B進程。因為Linux下B進程繼承A進程的檔案描述符,所以B進程便能使用A進程的檔案描述符進行操作。
使用場景如程式清單 31和程式清單 32所示。
程式清單 31 A進程程式碼
#include<stdio.h> #include<stdlib.h>
#define PATH_LEN 20 /* 路徑長度 */ #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) /* 建立檔案的許可權 */
intmain(intargc, char **argv) { int iFd1; int iFd2; char cBuf[PATH_LEN] = {0};
iFd1 = open("test1", O_CREAT | O_WRONLY, FILE_MODE); /* 開啟檔案 */ iFd2 = open("test2", O_CREAT | O_WRONLY, FILE_MODE);
printf("open readfd %d writefd %dn", iFd1, iFd2); /* * 構建system命令字串 */ sprintf(cBuf, "%s %d:%d", "/apps/hellow/hellow", iFd1, iFd2);
system(cBuf); /* 呼叫system執行 */
close(iFd1); close(iFd2); printf("after system!n"); return 0; } |
程式清單 32 B進程程式碼
#include<stdio.h> intmain (intargc, char **argv) { intreadfd; intwritefd;
sscanf (argv[1], "%d:%d", &readfd, &writefd); /* 解析引數,獲得檔案描述符 */ printf("hellow readfd %d writefd %dn", readfd, writefd);
if (!write(writefd, "SylixOS", sizeof("SylixOS"))) { perror("write"); return -1; } return (0); } |
在SylixOS執行結果如所示,B進程沒有繼承A進程的檔案描述符導致報錯。
圖 31 SylixOS執行結果
遇到這種情況,可以通過使用posix_spawn來替換system。posix_spawn函數建立子進程並繼承父系的檔案描述符,所以可以通過posix_spawn替換system實現。如程式清單 33所示,只需修改A進程,B進程不用修改。
程式清單 33 A進程修改後原始碼
#include<stdio.h> #include<stdlib.h> #include<spawn.h>
#define PATH_LEN 20 /* 路徑長度 */ #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) /* 建立檔案的許可權 */
intmain(intargc, char **argv) { int iFd1; int iFd2; char cBuf[PATH_LEN] = {0};
iFd1 = open("test1", O_CREAT | O_WRONLY, FILE_MODE); /* 開啟檔案 */ iFd2 = open("test2", O_CREAT | O_WRONLY, FILE_MODE);
printf("open readfd %d writefd %dn", iFd1, iFd2); #ifndef SYLIXOS /* * 構建system命令字串 */ sprintf(cBuf, "%s %d:%d", "/apps/hellow/hellow", iFd1, iFd2); system(cBuf); /* 呼叫system執行 */ #else char *pcArgv[5] = { "/apps/hellow/hellow", "SylixOS", (char *)0 }; int iRet; pid_tiPid;
sprintf(pcArgv[1], "%d:%d", iFd1, iFd2); /* 構建system命令字串 */ iRet = posix_spawn(&iPid, /* 啟動進程 */ "/apps/hellow/hellow", NULL, NULL, pcArgv, NULL); if (iRet != 0) { close(iFd1); close(iFd2); return (-3); } #endif waitpid(iPid, NULL, 0); close(iFd1); close(iFd2); printf("after system!n"); return 0; } |
執行結果如圖 32所示,執行正確。
圖 32 修改後執行結果
本文永久更新連結地址:http://www.linuxidc.com/Linux/2017-06/144762.htm
相關文章