freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

[計算機軟件及應(yīng)用]第10章系統(tǒng)調(diào)用-資料下載頁

2025-10-07 23:18本頁面
  

【正文】 ) perror(Err on execvp)。 if(fork()==0) if(execve(/usr/bin/env, argv_execve, envp)0) perror(Err on execve)。 } ? 程序里調(diào)用了 2個 Linux常用的系統(tǒng)命令, echo和 env。 echo會把后面跟的命令行參數(shù)原封不動的打印出來, env用來列出所有環(huán)境變量。 ? 由于各個子進程執(zhí)行的順序無法控制,所以有可能出現(xiàn)一個比較混亂的輸出 各子進程打印的結(jié)果交雜在一起,而不是嚴(yán)格按照程序中列出的次序。 ? 編譯并運行: $ cc o exec $ ./exec executed by execl PATH=/tmp USER=lei STATUS=testing executed by execlp excuted by execv executed by execvp PATH=/tmp USER=lei STATUS=testing 可以看到, execle輸出的結(jié)果跑到了 execlp前面。 ? 在平時的編程中,如果用到了 exec函數(shù)族,一定記得要加上錯誤判斷語句。因為與其他系統(tǒng)調(diào)用比起來, exec很容易受傷,被執(zhí)行文件的位置,權(quán)限等很多因素都能導(dǎo)致該調(diào)用的失敗。最常見的錯誤是: ( 1)找不到文件或路徑,此時 errno被設(shè)置為ENOENT; ( 2)數(shù)組 argv和 envp忘記用 NULL結(jié)束,此時errno被設(shè)置為 EFAULT; ( 3)沒有對要執(zhí)行文件的運行權(quán)限,此時 errno被設(shè)置為 EACCES。 與進程管理相關(guān)的系統(tǒng)調(diào)用實戰(zhàn) ? 下面用 2個實例演示了已經(jīng)學(xué)習(xí)的內(nèi)容。其一是 Mini Shell,模仿常見的 Bash,但對其作了大大簡化;其二是一個 Daemon程序,可以使讀者一窺服務(wù)器編程的端倪。 Mini Shell ? Linux Shell在登錄后自動執(zhí)行,打印出一個 $符號,然后等待輸入命令。 Linux下最常用的 Shell應(yīng)用程序是 Bash,絕大部分Linux發(fā)行版默認(rèn)安裝的都是它。下面動手編寫一個 Shell程序,這個 Shell遠遠不如Bash復(fù)雜,但也能滿足一般的使用。 ? 首先,給這個 Shell取一個名字,不妨就叫做 Mini Shell。 ? Linux系統(tǒng)的命令分為內(nèi)部命令和外部命令兩種,內(nèi)部命令由 Shell程序?qū)崿F(xiàn),如 cd、 echo等。而每一個 Linux外部命令都是一個單獨的應(yīng)用程序,這些命令都以可執(zhí)行文件的形式存在,絕大部分放在目錄 /bin和 /sbin中。這樣,只需要實現(xiàn)很有限的內(nèi)部命令,對于其它的輸入統(tǒng)統(tǒng)當(dāng)作應(yīng)用程序來執(zhí)行。為了簡單起見, Mini Shell只實現(xiàn)了 2個內(nèi)部命令: ( 1) cd 用于切換目錄,和熟悉的命令 cd類似,除了沒有那么多的附加功能。 ( 2) quit 用于退出 Mini Shell。 ? 下面是程序清單: 1: // 2: include 1: include 3: include 4: include 5: include 6: include 7: 9: void do_cd(char *argv[])。 10: void execute_new(char *argv[])。 11: 12: main( ) 13: { 14: char *cmd=(void *)malloc(256*sizeof(char))。 //定義字符串cmd,用于接收用戶輸入的命令行。 15: char *cmd_arg[10]。 //定義指針數(shù)組 cmd_arg,它的形式和作用都與熟悉的 char *argv[]一樣。 //從以上 2個定義可以看出 Mini Shell對命令輸入的 2個限制: //首先,用戶輸入的命令行必須在 255個字符之內(nèi)(除去字符串結(jié)束標(biāo)志39。\039。); //其次,命令行的參數(shù)個數(shù)不得超過 10個(包括命令本身在內(nèi))。 16: int cmdlen,i,j,tag。 17: 18: do{ //進入一個 dowhile循環(huán),這個循環(huán)是本程序的主體部分, //基本思想是 等待輸入命令 處理已輸入命令 等待輸入命令 。 19: // 初始化 cmd 20: for(i=0。i255。i++) cmd[i]=39。\039。 21: 22: printf(=Mini Shell=*| )。 //打印輸入提示信息。在Mini Shell中使用了 =Mini Shell=*| //作為輸入提示信息,如果不喜歡,可以用任意的字符替換。 23: fgets(cmd,256,stdin)。 //接收用戶輸入。 24: 25: cmdlen=strlen(cmd)。 // fgets接受輸入時,會將輸入字符串時末尾的換行符( \n)起接受, //這是不需要的,所以要把它去掉。 2527行中簡單的用字符串結(jié)束標(biāo)志 39。\039。覆蓋了字符串 cmd的最后 //一個字符來實現(xiàn)這個目的。 26: cmdlen。 27: cmd[cmdlen]=39。\039。 ? 28: ? 29: // 把命令行分解為指針數(shù)組 cmd_arg ? 30: for(i=0。i10。i++) cmd_arg[i]=NULL。 //初始化指針數(shù)組cmd_arg。 ? 31: i=0; j=0; tag=0。 ? 32: while(i10){ //3242行:對輸入進行分析,將 cmd中參數(shù)間的空格用 39。\039。填充,并把各參數(shù)的 ? //起始地址分別賦與 cmd_arg數(shù)組。這樣就把 cmd分解成了cmd_arg,但分解后的各命令參數(shù)仍然使用 ? //著 cmd的內(nèi)存空間,所以在命令執(zhí)行結(jié)束前不宜對 cmd另外賦值。 ? 33: if(cmd[i]==39。 39。){ ? 34: cmd[i]=39。\039。 ? 35: tag=0。 ? 36: }else{ ? 37: if(tag==0) ? 38: cmd_arg[j++]=cmd+i。 ? 39: tag=1。 ? 40: } ? 41: i++。 ? 42: } ? 43: ? 44: // 如果參數(shù)超過 10個,就打印錯誤,并忽略當(dāng)前輸入 ? 45: if(j=10 amp。amp。 iCMDLEN){ //如果還未分析到輸入字符串的末尾( i=10),就認(rèn)為輸入的 ? //命令行超出了 10個參數(shù)的限制,打印錯誤并重新接收命令。 ? 46: printf(TOO MANY ARGUMENTS\n)。 ? 47: continue。 ? 48: } ? 49: ? 50: // 命令 quit:退出 Mini Shell ? 51: if(strcmp(cmd_arg[0],quit)==0) //5152行:內(nèi)部命令 quit:字符串 cmd_arg[0]就是命令本身, ? //如果命令是 quit,則退出循環(huán),也就等于退出該程序。 ? 52: break。 ? 53: ? 54: // 5558行:內(nèi)部命令 cd:調(diào)用函數(shù) do_cd()完成 cd命令的動作。 ? 55: if(strcmp(cmd_arg[0],cd)==0){ ? 56: do_cd(cmd_arg)。 ? 57: continue。 ? 58: } ? 59: ? 60: //61行 ,對于其它的外部命令或應(yīng)用程序,調(diào)用函數(shù)execute_new()執(zhí)行。 ? 61: execute_new(cmd_arg)。 ? 62: }while(1)。 ? 63: } ? 64: ? 65: //函數(shù) do_cd實現(xiàn) cd的功能 ? 66: void do_cd(char *argv[]) ? 67: { ? 68: if(argv[1]!=NULL){ // 僅僅考慮緊跟在命令后面的參數(shù)argv[1],而不再考慮其它的參 ? //數(shù)。如果這個參數(shù)存在,就把它作為要轉(zhuǎn)換的目錄。 ? 69: if(chdir(argv[1])0) // 調(diào)用系統(tǒng)調(diào)用 chdir切換當(dāng)前目錄, ? 70: switch(errno){ //7082行:對 chdir可能出現(xiàn)的錯誤進行處理。 ? 71: case ENOENT: ? 72: printf(DIRECTORY NOT FOUND\n)。 ? 73: break。 ? 74: case ENOTDIR: ? 75: printf(NOT A DIRECTORY NAME\n)。 ? 76: break。 ? 77: case EACCES: ? 78: printf(YOU DO NOT HAVE RIGHT TO ACCESS\n)。 ? 79: break。 ? 80: default: ? 81: printf(SOME ERROR HAPPENED IN CHDIR\n)。 ? 82: } ? 83: } ? 84: ? 85: } ? 86: ? 87: // 執(zhí)行外部命令或應(yīng)用程序的函數(shù) execute_new ? 88: void execute_new(char *argv[]) ? 89: { ? 90: pid_t pid。 ? 91: ? 92: pid=fork()。 //調(diào)用系統(tǒng)調(diào)用 fork產(chǎn)生新的子進程。 ? 93: if(pid0){ //如果返回負(fù)值,說明 fork調(diào)用出現(xiàn)錯誤。 ? 94: printf(SOME ERROR HAPPENED IN FORK\n)。 ? 95: exit(2)。 ? 96: }else if(pid==0){ //如果返回 0,說明當(dāng)前進程是子進程 ? 97: if(execvp(argv[0],argv)0) //調(diào)用 execvp執(zhí)行新的應(yīng)用程序,檢測調(diào)用是否出錯 (返回負(fù)值 )。 ? //這里使用 execvp的原因是它可以自動在各默認(rèn)目錄里尋找目標(biāo)應(yīng)用程序的位置, ? //而不必自己編程實現(xiàn)。 ? 98: switch(errno){ //98107行:對 execvp可能出現(xiàn)的錯誤進程處理 ? 99: case ENOENT: ? 100: printf(COMMAND OR FILENAME NOT FOUND\n)。 ? 101: break。 ? 102: case EACCES: ? 103: printf(YOU DO NOT HAVE RIGHT TO ACCESS\n)。 ? 104: break。 ? 105: default: ? 106: printf(SOME ERROR HAPPENED IN EXEC\n)。 ? 107: } ? 108: exit(3)。 //如果 execvp的執(zhí)行出現(xiàn)錯誤,子進程在這里終止。表面上看起來,這個 exit是接著 97行的錯誤判斷的下一行語句,而非 if語句的一部分,似乎無論調(diào)用execvp成功與否都會接著執(zhí)行 exit。但事實上,如果execvp調(diào)用成功的話,這個進程將會被新的程序代碼填充,因而根本不可能執(zhí)行到這一行。反之,如果執(zhí)行到了這一行,說明前面的 execvp調(diào)用一定出現(xiàn)了錯誤。這樣的效果和 exit被包含在 if語句中的效果是完全一樣的。 ? 109: }else //如果 fork返回其它值,說明當(dāng)前進程是父進程。 ? 110: wait(NULL)。 //調(diào)用系統(tǒng)調(diào)用 wait。 ? 111: } ? 110行的 wait在這里有兩個作用: (1) 使父進程在此暫停,等待子進程執(zhí)行完畢。這樣,就可以等子進程的所有信息全部輸出完畢后才打印命令提示符,等待下一條命令的輸入,從而避免了命令提示符和應(yīng)用程序輸出混雜在一起的現(xiàn)象。 (2) 收集子進程退出后留下的僵尸進程。編程生成的子進程由自己設(shè)計的父進程負(fù)責(zé)收集,從命令行執(zhí)行的所有進程最后都是由 shell收集。
點擊復(fù)制文檔內(nèi)容
教學(xué)課件相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1