国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 操作系統 > 正文

進程控制之exec函數

2024-06-28 13:28:35
字體:
來源:轉載
供稿:網友
進程控制之exec函數

用fork函數創建子進程后,子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時,該進程執行的程序完全替換為新程序,而新程序則從其main函數開始執行。因為調用exec并不創建新進程,所以前后的進程ID并未改變。exec只是用一個全新的程序替換了當前進程的正文、數據、堆和棧段。

有6種不同的exec函數可供使用,它們常常被統稱為exec函數。這些exec函數使得UNIX進程控制原語更加完善。用fork可以創建新進程,用exec可以執行新程序。exit函數和兩個wait函數處理終止和等待終止。這些是我們需要的基本的進程控制原語。

#include <unistd.h>int execl( const char *pathname, const char *arg0, ... /* (char *)0 */ );int execv( const char *pathname, char *const argv[] );int execle( const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );int execve( const char *pathname, char *const argv[], char *const envp[] );int execlp( const char *filename, const char *arg0, ... /* (char *)0 */ );int execvp( const char *filename, char *const argv[] );6個函數返回值:若出錯則返回-1,若成功則不返回值

這些函數之間的第一個區別是前4個取路徑名作為參數,后兩個(execlp和execvp,p表示PATH,個人理解)則取文件名作為參數當指定filename作為參數時

  • 如果filename中包含了/,則將其視為路徑名。
  • 否則就按PATH環境變量,在它所指定的各目錄中搜尋可執行文件。

PATH變量包含了一張目錄表(稱為路徑前綴),目錄之間用冒號(:)分隔。例如name = value環境字符串:

PATH=/bin:/usr/bin:/usr/local/bin/:.

指定在4個目錄中進行搜索。最后的路徑前綴(.)表示當前目錄。(零長前綴也表示當前目錄。在value的開始處可用:表示,在行中間則要用::表示,在行尾則以:表示。)

如果execlp或execvp使用路徑名前綴中的一個找到了一個可執行文件,但是該文件不是由連接編輯器產生的機器可執行文件,則認為該文件是一個shell腳本,于是試著調用/bin/sh,并以該filename作為shell的輸入。

第二個區別與參數表的傳遞有關(l表示list,v表示矢量vector)。函數execl、execlp和execle要求將新程序的每個命令行參數都說明為一個單獨的參數。這種參數表以空指針結尾。對于另外三個函數(execv、execvp和execve),則應先構造一個指向各參數的指針數組,然后將該數組地址作為這三個函數的參數。

在ISO C原型之前,對execl、execle和execlp這三個函數表示命令行參數的一般方法是:

char *arg0, char *arg1, …, char *argn, (char *)0

應當特別指出的是:在最后一個命令行參數之后跟了一個空指針。如果用常數0來表示一個空指針,則必須將它強制轉換為一個字符指針,否則將它解釋為整型參數。如果一個整型數的長度與char *的長度不同,那么exec函數的實際參數就將出錯。

最后一個區別與向新程序傳遞環境表相關。以e結尾的兩個函數(execle和execve)可以傳遞一個指向環境字符串指針數組的指針。其他四個函數則使用調用進程中的environ變量為新程序復制現有的環境。通常,一個進程允許將其環境傳播給其子進程,但有時也有這種情況,即進程想要為子進程指定某一個確定的環境。

在使用ISO C原型之前,execle的參數是:

char *pathname, char *arg0, …, char *argn, (char *)0, char *envp[]

從中可見,最后一個參數是指向環境字符串的各字符指針構成的數組的地址。而ISO C原型中,所有命令行參數、空指針和envp指針都用省略號(...)表示。

這6個exec函數名中的字符說明:字母p表示該函數取filename作為參數,并且用PATH環境變量尋找可執行文件。字母l表示該函數取一個參數表,它與字母v互斥。字母v表示該函數取一個argv[]矢量。字母e表示該函數取envp[]數組,而不使用當前環境。

                                          表8-6 6個exec函數之間的區別

090401204936

在執行exec后,進程ID沒有改變。除此之外,執行新程序的進程還保持了原進程的下列特征:

  • 進程ID和父進程ID。
  • 實際用戶ID和實際組ID。
  • 附加組ID。
  • 進程組ID。
  • 會話ID。
  • 控制終端。
  • 鬧鐘尚余留的時間。
  • 當前工作目錄。
  • 根目錄。
  • 文件模式創建屏蔽字。
  • 文件鎖。
  • 進程信號屏蔽。
  • 未處理信號。
  • 資源限制。
  • tms_utime、tms_stime、tms_cutime以及tms_cstime值。

對打開文件的處理與每個描述符的執行時關閉(close-on-exec)標志值有關。進程中每個打開描述符都有一個執行時關閉標志。若此標志設置,則在執行exec時關閉該描述符,否則該描述符仍打開。除非特地用fcntl設置了該標志,否則系統默認操作是在執行exec后仍保持這種描述符打開。

POSIX.1明確要求在執行exec時關閉打開的目錄流。這通常是opendir函數實現的,它調用fcntl函數為對應于打開目錄流的描述符設置執行時關閉標志。

注意,在執行exec前后實際用戶ID和實際組ID保持不變,而有效ID是否改變則取決于所執行程序文件的設置用戶ID位和設置組ID位是否設置。如果新程序的設置用戶ID位已設置,則有效用戶ID變成程序文件所有者的ID,否則有效用戶ID不變。對組ID的處理方式與此相同。

在很多UNIX實現中,這6個函數中只有execve是內核的系統調用。另外5個只是庫函數,它們最終都要調用該系統調用

1366632408_8808

程序清單8-8 exec函數實例

[root@localhost apue]# cat PRog8-8.c#include "apue.h"#include <sys/wait.h>char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL };intmain(void){        pid_t   pid;        if((pid = fork()) < 0)        {                err_sys("fork error");        }        else if(pid == 0) /*specify pathname, specify environment */        {                if(execle("/home/zhu/apue/echoall", "echoall", "myarg1", "MY ARG2", (char *)0, env_init) < 0)                        err_sys("execle error");        }        if(waitpid(pid, NULL, 0) < 0)                err_sys("wait error");        if((pid = fork()) < 0)        {                err_sys("fork error");        }        else if(pid == 0) /* specify filename, inherit environment */        {                if(execlp("echoall", "echoall", "only 1 arg", (char *)0) < 0)                        err_sys("execlp error");        }        exit(0);}

注意,我們將第一個參數(新程序中的argv[0])設置為路徑名的文件名分量。某些shell將此參數設置為完整的路徑名。這只是一個慣例。我們可將argv[0]設置為任何字符串。

程序清單8-8中要執行的程序echoall示于程序清單8-9中。這是一個很普通的程序,它回送其所有命令行參數及全部環境表。

程序清單8-9 回送所用命令行參數和所有環境字符串

[root@localhost apue]# cat echoall.c#include "apue.h"intmain(int argc, char *argv[]){        int         i;        char        **ptr;        extern char **environ;        for(i=0; i<argc; i++)   /* echo all command-line args */                printf("argv[%d]: %s/n", i, argv[i]);        for(ptr = environ; *ptr != 0; ptr++)    /*and all env strings */                printf("%s/n", *ptr);        exit(0);}

執行程序清單8-8得到

[root@localhost apue]# ./prog8-8argv[0]: echoallargv[1]: myarg1argv[2]: MY ARG2USER=unknownPATH=/tmpargv[0]: echoallargv[1]: only 1 argSSH_AGENT_PID=4279HOSTNAME=localhost.localdomainDESKTOP_STARTUP_ID=SHELL=/bin/bash......

 

最后總結一下使用exec函數時需要考慮哪些參數:首先,要執行的新程序名(帶不帶路徑);其次,命令行參數(列表形式還是指針數組形式);最后,環境表(要不要傳遞環境表)

 

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 左云县| 赤峰市| 白沙| 甘孜县| 新和县| 郴州市| 海晏县| 嵊州市| 虞城县| 上蔡县| 阜城县| 农安县| 化德县| 杭锦后旗| 灌云县| 桂阳县| 大余县| 新乡县| 南乐县| 彰化市| 福州市| 陇西县| 昌乐县| 沽源县| 涟水县| 徐汇区| 寿光市| 云阳县| 阿瓦提县| 蓬安县| 县级市| 建平县| 三明市| 阿瓦提县| 鄂托克旗| 南郑县| 应城市| 张掖市| 商都县| 曲麻莱县| 卢湾区|