c 禁止程序被結束 多程序任務實現

2021-10-17 08:09:43 字數 3733 閱讀 3742

使用過命令列的同學都知道,我們使用命令列是一般是在shell中執行類似下面這樣的命令

/cmd/path/cmd_bin param1 param2 ... paramn

但是問題來了,任務排程系統又不能和shell互動,要怎樣調起這樣的命令呢?linux為我們提供了一套可行的方式,多程序。至於怎樣實現多程序的方式,我們從簡單到複雜來講吧

system()函式

在c標準庫中有乙個system()函式,在呼叫這個函式時,linux會產生乙個子程序,然後由子程序來呼叫/bin/sh-c string來執行引數string字串所代表的命令。命令執行完後子程序退出,隨即返回原呼叫的程序。這個函式的原型如下

int system(const char * string); 

產生乙個子程序並執行引數中的命令列。引數string即要執行的命令

通過上面的分析可知,system()函式是完成能夠滿足我們的基本需求的,只要我們把要執行的命令拼裝成乙個命令列,然後傳到system()函式即可。像下面例子所示

#include int main ()

但是,由於system()在命令執行完之前是會阻塞主程序的,這對於多個任務同時執行,而且任務都需要執行很長時間,並且我們需要知道每個任務的執行結果的情況下,system()就不能很好地滿足我們的需求了。雖然不能直接使用,但是我們可以參考下system()函式是怎樣實現的。

//c_standard_lib/stdlib/system.c

/* unix system calls */

int _execl(const char *, const char *, ...);

int _fork(void);

int _wait (int *);

int (system)(const char *s)

else /* continue here as parent */

while (_wait(null) != pid)

; /* wait for child */

} return (-1);

}

從上面c標準庫的**中可以看到,在實現system()函式中使用到了3個其他系統函式,分別是fork(),execl()和wait()。既然如此,我們就順勢而為,看看能不能也使用這三個函式來實現乙個滿足我們要求的做法。

自己動手,豐衣足食

上面我們知道了system()函式的用到了哪些系統呼叫,我們接下來就先熟悉下這些系統呼叫好了,原型如下

pid_t fork(void);

fork()系統呼叫會通過複製乙個現有程序來建立乙個全新的程序。返回值:自程序中返回0,父程序返回程序id,出錯返回-1

int execl(const char *pathname, const char *arg, ... /* (char *) null */);

int execlp(const char *file, const char *arg, ... /* (char *) null */);

int execle(const char *pathname, const char *arg, ... /*, (char *) null, char * const envp */);

int execv(const char *pathname, char *const ar**);

int execvp(const char *file, char *const ar**);

int execvpe(const char *file, char *const ar**, char *const envp);

在程序的建立上unix採用了乙個獨特的方法,它將程序建立與載入乙個新程序映象分離。

當我們建立了乙個程序之後,通常將子程序替換成新的程序映象,這可以用exec系列的函式來進行。

當然,exec系列的函式也可以將當前程序替換掉。path引數表示你要啟動程式的名稱包括路徑名

arg引數表示啟動程式所帶的引數,一般第乙個引數為要執行命令名,不是帶路徑且arg必須以null結束

返回值:成功返回0,失敗返回-1

上述exec系列函式底層都是通過execve系統呼叫實現:

int execve(const char *filename, char *const ar**,char *const envp);

pid_t wait(int *wstatus);

pid_t waitpid(pid_t pid, int *wstatus, int options);

系統呼叫exit後,該程序並非馬上消失,而是留下乙個叫殭屍程序的資料結構,殭屍程序是非常特使的一種,它放棄了幾乎所有的記憶體空間,

沒有任何可執行**,也不能別排程,僅僅在程序列表保留位置,而且不占用任何記憶體空間。

wait()函式用於使父程序阻塞,直到乙個子程序結束或者該程序接收到了乙個指定的訊號為止。

如果該父程序沒有子程序或者它的子程序已經結束,則wait()函式就會立即返回。

waitpid()的作用和wait()一樣,但它並不一定要等待第乙個終止的子程序(它可以通過pid指定需要等待終止的子程序),它還有若干options,

當options==wnohang時,相當於提供乙個非阻塞版本的 wait()功能,也能支援作業控制。

實際上,wait()函式只是 waitpid()函式的乙個特例,在linux 內部實現 wait()函式時直接呼叫的就是waitpid()函式

下面是乙個簡單的應用例子,在實際的應用中,除了這3個api的應用之外,還需要做很多其他的事情,如註冊訊號,寫日誌,管道重定向等等,有興趣的同學可以看看apue或者《linux系統程式設計》等等經典著作,這裡就不再囉嗦了。

#include #include #include #include #include #include #include #include #include #include #include #include #include #include int  exec( const std::string& execname, std::vector& params)

ar**[argc] = null;

/*** step 3. fork and exec

*/pid_t pid = fork();

if (pid == 0)

else if (pid > 0)

// get exit value of child process

int exit_value = 0;

if (wifexited(status))

else if (wifsignaled(status))

else

exit_value = 0xf0;

return exit_value;

} return -1;

}

怎樣做到的

本來打算對上述api的實現剖析一番的,但是想到自己已經很就沒有去看這麼底層的東西了,而且linux核心版本更新得很快,所以就放棄了,只能奉上幾個api在核心中的實現**,有興趣的同學自行學習好了

fork()核心實現​elixir.bootlin.com

waitpid核心實現​elixir.bootlin.com

execve核心**​elixir.bootlin.com

PHP多程序處理並行處理任務例項

本文目的 本文通過例子講解linux環境下,使用php進行併發任務處理,以及如何通過pipe用於程序間的資料同步。寫得比較簡單,作為備忘錄。php多程序 通過pcntl 系列函式使用多程序功能。注意 pcntl 只能執行在php cli 命令列 環境下,在web伺服器環境下,會出現無法預期的結果,請...

6 2Process 多程序實現多工

程序實現多工時浪費資源 主程序 占用資源 子程序1 複製主程序 占用資源 子程序2 複製主程序 占用資源 coding utf 8 import threading import time import multiprocessing def test1 子程序1 while true print ...

PHP使用QPM實現多程序並行任務處理程式

考慮用php實現以下場景 有乙個抓站的url列表儲存在佇列裡,後台程式讀取這個佇列,然後轉交給子程序去抓取html存放到檔案裡。為了提高效率,允許多工並行執行,但為了避免機器負載過高,限制了最大的並行任務數 為了測試方便,我們把這個數設為3 當佇列中取到 end標記時,程式結束執行。這個場景用qpm...