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

正文內(nèi)容

[計(jì)算機(jī)軟件及應(yīng)用]第10章系統(tǒng)調(diào)用-預(yù)覽頁(yè)

 

【正文】 : file format elf32i386 Disassembly of section. text: 00000000 0:89 da mov1 %ebx,%edx 2:8b 4c 24 08 mov1 0x8(%esp,1),%ecx 6:8b 5c 24 04 mov1 0x4(%esp,1),%ebx a:b8 4a 00 00 00 mov1 $0x4a,%eax f:cd 80 int $0x80 11:89 d3 mov1 %edx,%ebx 13:3d 01 f0 ff ff cmp1 $0xfffff001,%eax 18:0f 83 fc ff ff jae la 1d:ff 1a:R_386_PC32 _syscall_error 1e:c3 ret ? 進(jìn)入函數(shù) sethostname()以后,堆棧指針 %esp指向返回地址,而在堆棧指針加 4的地方則是調(diào)用該函數(shù)的第一個(gè)參數(shù) name,加 8是第二個(gè)參數(shù)len。接著檢查放在 %eax中的系統(tǒng)調(diào)用的返回值。最后,在返回之前,將 %eax的內(nèi)容變?yōu)?1。 } ? 系統(tǒng)調(diào)用 time返回從格林尼治時(shí)間 1970年 1月 1日 0:00開(kāi)始到現(xiàn)在的秒數(shù)。 the_time=time((time_t *)0); //調(diào)用 time系統(tǒng)調(diào) 用 printf(The time is %ld\n,the_time)。 ? 它們的作用是形成相應(yīng)的系統(tǒng)調(diào)用函數(shù)原型,供在程序中調(diào)用。 do { if ((unsigned long)(__res) = (unsigned long)(125)) { errno = (__res)。 } ? 可以看出,_syscall1(time_t,time,time_t *,tloc)展開(kāi)成一個(gè)名為 time的函數(shù),原參數(shù)time_t就是函數(shù)的返回類(lèi)型,原參數(shù)time_t *和 tloc分別構(gòu)成新函數(shù)的參數(shù)。 errno不同數(shù)值所代表的錯(cuò)誤消息定義在 ,也可以通過(guò)命令 man 3 errno來(lái)查看。但是,在 Linux的各版本內(nèi)核之間,系統(tǒng)調(diào)用的兼容性表現(xiàn)得并不像想象那么好,這是由 Linux本身的性質(zhì)決定的。 getpid ? 在 , getpid是第 20號(hào)系統(tǒng)調(diào)用,其在 Linux函數(shù)庫(kù)中的原型是: includesys/ // 提供類(lèi)型 pid_t的定義 include // 提供函數(shù)的定義 pid_t getpid(void)。 ? 編譯并運(yùn)行程序 : $gcc o getpid_test $./getpid_test The current process ID is 1980 (運(yùn)行結(jié)果很可能與這個(gè)數(shù)字不一樣,這是很正常的。當(dāng)一個(gè)進(jìn)程調(diào)用它,完成后就出現(xiàn)兩個(gè)幾乎一模一樣的進(jìn)程,也由此得到了一個(gè)新進(jìn)程。在命令行下運(yùn)行應(yīng)用程序時(shí),新的進(jìn)程也是由shell調(diào)用 fork制造出來(lái)的。 //此時(shí)已經(jīng)有兩個(gè)進(jìn)程在同時(shí)運(yùn)行 if(pid0) printf(error in fork!)。 ? 兩個(gè)進(jìn)程中,原先就存在的進(jìn)程被稱(chēng)作 “ 父進(jìn)程 ” ,新出現(xiàn)的那個(gè)被稱(chēng)作 “ 子進(jìn)程 ” 。 ? fork系統(tǒng)調(diào)用出錯(cuò)的可能性很小,而且如果出錯(cuò),一般都為第一種錯(cuò)誤。 exit ? 在 , exit是第 1號(hào)調(diào)用,其在Linux函數(shù)庫(kù)中的原型是: include void exit(int status)。 exit(0)。在實(shí)際編程時(shí),可以用 wait系統(tǒng)調(diào)用接收子進(jìn)程的返回值,從而針對(duì)不同的情況進(jìn)行不同的處理。 exit()函數(shù)定義在 ,而_exit()定義在 。因此,有些人認(rèn)為 exit已經(jīng)不能算是純粹的系統(tǒng)調(diào)用。 ? 請(qǐng)看以下例程: // include main() { printf(output begin\n)。 printf(content in buffer)。 ? 請(qǐng)讀者結(jié)合前面的敘述,思考一下為什么這兩個(gè)程序會(huì)得出不同的結(jié)果。 chdir只有 1個(gè)字符串參數(shù),就是要轉(zhuǎn)去的路徑。 ? 一個(gè)會(huì)話( session)開(kāi)始于用戶(hù)登錄,終止于用戶(hù)退出,在此期間該用戶(hù)運(yùn)行的所有進(jìn)程都屬于這個(gè)會(huì)話,除非進(jìn)程調(diào)用 setsid系統(tǒng)調(diào)用。 僵尸進(jìn)程 ? 在一個(gè)進(jìn)程調(diào)用了 exit之后,該進(jìn)程并非馬上就消失掉,而是留下一個(gè)稱(chēng)為僵尸進(jìn)程( Zombie)的數(shù)據(jù)結(jié)構(gòu)。 ? if(pid0) // 如果出錯(cuò) printf(error occurred!\n)。 // 收集僵尸進(jìn)程 } ? sleep的作用是讓進(jìn)程休眠指定的秒數(shù),在這 60秒內(nèi),子進(jìn)程已經(jīng)退出,而父進(jìn)程正忙著睡覺(jué),不可能對(duì)它進(jìn)行收集,這樣,就能保持子進(jìn)程 60秒的僵尸狀態(tài)。僵尸進(jìn)程的概念是從 UNIX繼承而來(lái)的。下面就對(duì)這兩個(gè)調(diào)用分別作詳細(xì)介紹。 ? 如果成功, wait會(huì)返回被收集的子進(jìn)程的進(jìn)程 ID,如果調(diào)用進(jìn)程沒(méi)有子進(jìn)程,調(diào)用就會(huì)失敗,此時(shí) wait返回 1,同時(shí) errno被置為 ECHILD。 if(pc0) // 如果出錯(cuò) printf(error ocurred!\n)。 // 在這里等待 printf(I catched a child process with pid of %d\n),pr)。 ? 如果參數(shù) status的值不是 NULL, wait就會(huì)把子進(jìn)程退出時(shí)的狀態(tài)取出并存入其中,這是一個(gè)整數(shù)值( int),指出了子進(jìn)程是正常退出還是被非正常結(jié)束的(一個(gè)進(jìn)程也可以被其他進(jìn)程用信號(hào)結(jié)束,將在以后的文章中介紹),以及正常結(jié)束時(shí)的返回值,或被哪一個(gè)信號(hào)結(jié)束的等信息。 pid=0時(shí),等待同一個(gè)進(jìn)程組中的任何子進(jìn)程,如果子進(jìn)程已經(jīng)加入了別的進(jìn)程組, waitpid不會(huì)對(duì)它做任何理睬。 ? 如果使用了 WNOHANG參數(shù)調(diào)用 waitpid,即使沒(méi)有子進(jìn)程退出,它也會(huì)立即返回,不會(huì)像 wait那樣永遠(yuǎn)等下去。 } ? waitpid的返回值比 wait稍微復(fù)雜一些,返回值和錯(cuò)誤一共有 3種情況: ( 1) 當(dāng)正常返回的時(shí)候, waitpid返回收集到的子進(jìn)程的進(jìn)程 ID; ( 2) 如果設(shè)置了選項(xiàng) WNOHANG,而調(diào)用中waitpid發(fā)現(xiàn)沒(méi)有已退出的子進(jìn)程可收集,則返回0; (3) 如果調(diào)用中出錯(cuò),則返回 1,這時(shí) errno會(huì)被設(shè)置成相應(yīng)的值以指示錯(cuò)誤所在; ? 當(dāng) pid所指示的子進(jìn)程不存在,或此進(jìn)程存在,但不是調(diào)用進(jìn)程的子進(jìn)程,waitpid就會(huì)出錯(cuò)返回,這時(shí) errno被設(shè)置為 ECHILD; // include sys/ include sys/ include main() { pid_t pc, pr。 // 睡眠 10秒 exit(0)。 sleep(1)。 ? 因?yàn)檫@只是一個(gè)例子程序,沒(méi)有必要寫(xiě)得太復(fù)雜,所以就讓父進(jìn)程和子進(jìn)程分別睡眠了 10秒鐘和 1秒鐘,代表它們分別作了10秒鐘和 1秒鐘的工作。 int execlp(const char *file, const char *arg, ...)。 int execve(const char *path, char *const argv[], char *const envp[])。 ? 與一般情況不同, exec函數(shù)族的函數(shù)執(zhí)行成功后不會(huì)返回,因?yàn)檎{(diào)用進(jìn)程的實(shí)體,包括代碼段,數(shù)據(jù)段和堆棧等都已經(jīng)被新的內(nèi)容取代,只留下進(jìn)程 ID等一些表面上的信息仍保持原樣。因?yàn)?fork會(huì)將調(diào)用進(jìn)程的所有內(nèi)容原封不動(dòng)的拷貝到新產(chǎn)生的子進(jìn)程中去,這些拷貝的動(dòng)作很消耗時(shí)間,而如果fork完之后馬上就調(diào)用 exec,這些拷貝來(lái)的東西又會(huì)被立刻抹掉,這看起來(lái)非常不劃算,于是人們?cè)O(shè)計(jì)了一種 “ 寫(xiě)時(shí)拷貝 ” ( copyonwrite)技術(shù),使得 fork結(jié)束后并不立刻復(fù)制父進(jìn)程的內(nèi)容,而是到了真正實(shí)用的時(shí)候才復(fù)制,這樣如果下一條語(yǔ)句是 exec,它就不會(huì)白白作無(wú)用功,提高了效率。參數(shù) argc指出了運(yùn)行該程序時(shí)命令行參數(shù)的個(gè)數(shù),數(shù)組 argv存放了所有的命令行參數(shù),數(shù)組 envp存放了所有的環(huán)境變量。 ? 值得一提的是, argv數(shù)組和 envp數(shù)組存放的都是指向字符串的指針,這兩個(gè)數(shù)組都以一個(gè) NULL元素表示數(shù)組的結(jié)尾。 printf(\n ENVP \n)。這與平時(shí)習(xí)慣的說(shuō)法有些不同。 ? 認(rèn)真研究一下這 6個(gè)函數(shù),還可以發(fā)現(xiàn),前3個(gè)函數(shù)都是以 execl開(kāi)頭的,后 3個(gè)都是以execv開(kāi)頭的,凡是 execv開(kāi)頭的函數(shù)是以“ char *argv[]”這樣的形式傳遞命令行參數(shù),而 execl開(kāi)頭的函數(shù)采用了更容易習(xí)慣的方式,把參數(shù)一個(gè)一個(gè)列出來(lái),然后以一個(gè) NULL表示結(jié)束。 ? 還有 2個(gè)以 p結(jié)尾的函數(shù) execlp和 execvp,咋看起來(lái),它們和 execl與 execv的差別很小,事實(shí)也確是如此,除execlp和 execvp之外的 4個(gè)函數(shù)都要求,它們的第 1個(gè)參數(shù) path必須是一個(gè)完整的路徑,如 /bin/ls;而 execlp和 execvp的第 1個(gè)參數(shù) file可以簡(jiǎn)單到僅僅是一個(gè)文件名,如 ls,這兩個(gè)函數(shù)可以自動(dòng)到環(huán)境變量 PATH制定的目錄里去尋找。 char *argv_execve[]={env, NULL}。 if(fork()==0) if(execv(/bin/echo, argv_execv)0) perror(Err on execv)。 echo會(huì)把后面跟的命令行參數(shù)原封不動(dòng)的打印出來(lái), env用來(lái)列出所有環(huán)境變量。因?yàn)榕c其他系統(tǒng)調(diào)用比起來(lái), exec很容易受傷,被執(zhí)行文件的位置,權(quán)限等很多因素都能導(dǎo)致該調(diào)用的失敗。 Mini Shell ? Linux Shell在登錄后自動(dòng)執(zhí)行,打印出一個(gè) $符號(hào),然后等待輸入命令。 ? Linux系統(tǒng)的命令分為內(nèi)部命令和外部命令兩種,內(nèi)部命令由 Shell程序?qū)崿F(xiàn),如 cd、 echo等。 ( 2) quit 用于退出 Mini Shell。 //定義字符串cmd,用于接收用戶(hù)輸入的命令行。\039。 19: // 初始化 cmd 20: for(i=0。 21: 22: printf(=Mini Shell=*| )。 //接收用戶(hù)輸入。\039。\039。 //初始化指針數(shù)組cmd_arg。填充,并把各參數(shù)的 ? //起始地址分別賦與 cmd_arg數(shù)組。){ ? 34: cmd[i]=39。 ? 39: tag=1。 iCMDLEN){ //如果還未分析到輸入字符串的末尾( i=10),就認(rèn)為輸入的 ? //命令行超出了 10個(gè)參數(shù)的限制,打印錯(cuò)誤并重新接收命令。 ? 52: break。 ? 58: } ? 59: ? 60: //61行 ,對(duì)于其它的外部命令或應(yīng)用程序,調(diào)用函數(shù)execute_new()執(zhí)行。如果這個(gè)參數(shù)存在,就把它作為要轉(zhuǎn)換的目錄。 ? 74: case ENOTDIR: ? 75: printf(NOT A DIRECTORY NAME\n)。 ? 80: default: ? 81: printf(SOME ERROR HAPPENED IN CHDIR\n)。 ? 93: if(pid0){ //如果返回負(fù)值,說(shuō)明 fork調(diào)用出現(xiàn)錯(cuò)誤。 ? //這里使用 execvp的原因是它可以自動(dòng)在各默認(rèn)目錄里尋找目標(biāo)應(yīng)用程序的位置, ? //而不必自己編程實(shí)現(xiàn)。 ? 104: break。表面上看起來(lái),這個(gè) exit是接著 97行的錯(cuò)誤判斷的下一行語(yǔ)句,而非 if語(yǔ)句的一部分,似乎無(wú)論調(diào)用execvp成功與否都會(huì)接著執(zhí)行 exit。 ? 109: }else //如果 fork返回其它值,說(shuō)明當(dāng)前進(jìn)程是父進(jìn)程。這樣,就可以等子進(jìn)程的所有信息全部輸出完畢后才打印命令提示符,等待下一條命令的輸入,從而避免了命令提示符和應(yīng)用程序輸出混雜在一起的
點(diǎn)擊復(fù)制文檔內(nèi)容
教學(xué)課件相關(guān)推薦
文庫(kù)吧 www.dybbs8.com
備案圖鄂ICP備17016276號(hào)-1