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

正文內(nèi)容

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

2022-10-31 23:18:41 本頁面
 

【正文】 為在錯誤處理過程中,即使像 printf()這樣的函數(shù)出錯時(shí)也會改變 errno的值。 ? 3. errno是什么? 為防止和正常的返回值混淆,系統(tǒng)調(diào)用并不直接返回錯誤碼,而是將錯誤碼放入一個(gè)名為 errno的全局變量中。 } return (time_t) (__res)。事實(shí)上, _syscall后面跟的數(shù)字指明了展開后形成函數(shù)的參數(shù)的個(gè)數(shù),讓看一個(gè)實(shí)例,就是剛剛用過的 time系統(tǒng)調(diào)用: ? _syscall1(time_t,time,time_t *,tloc) 展開后的情形是這樣: time_t time(time_t * tloc) { long __res。 ? 大多數(shù)系統(tǒng)調(diào)用都在各種 C語言函數(shù)庫中有所實(shí)現(xiàn),所以在一般情況下,都可以像調(diào)用普通的庫函數(shù)那樣調(diào)用系統(tǒng)調(diào)用,只在極個(gè)別的情況下,才有機(jī)會用到_syscall*()這幾個(gè)宏。但事實(shí)上,如果把程序改成下面的樣子,程序也可以運(yùn)行得同樣的結(jié)果。 1. 如何使用系統(tǒng)調(diào)用? 先來看一個(gè)例子: includelinux/ //定義宏 _syscall1 include //定義類型 time_t _syscall1(time_t,time,time_t *,tloc)//宏,展開后得到 time() 函數(shù)的原型 main() { time_t the_time。 ? : file format elf32_i386 disassemble of : 00000000 _syscall_error): 0:f7 d8 negl %eax 00000002 _syscall_error_1: 2:50 push1 %eax 3:e8 fc ff ff ff call 4 _syscall_error_1+0x2 4:R_386_PC32 _errno_location 8:59 pop1 %ecx 9:89 08 mov1 %ecx,(%eax) b:b8 ff ff ff ff mov1 0xffffffff,%eax 10:c3 ret file of format elf32i386 disassembly of : 00000000 _errno_location: 0:55 push1 %ebp 1:89 e5 mov1 %esp,%ebp 3:b8 00 00 00 00 mov1 $0x0,%eax 4:R_386_32 errno 8:89 ec mov1 %ebp,%esp a:5d pop1 %ebp b:c3 ret 在 _syscall_error中 , 先將 %eax中的負(fù)值取絕對值 , 得到出錯代碼 , 并將其壓入堆棧。 ? 從系統(tǒng)調(diào)用返回后,先從 %edx中恢復(fù)%ebx原先的內(nèi)容,即在系統(tǒng)調(diào)用之前保存在 %edx中的(第一條指令),而 %edx中的內(nèi)容就丟失了。調(diào)用返回 0表示成功,- 1表示失敗。 Linux下的系統(tǒng)調(diào)用是通過中斷指令“ INT 0x80”實(shí)現(xiàn)的。所以在進(jìn)入和退出系統(tǒng)調(diào)用總控程序時(shí), “ 保護(hù)現(xiàn)場 ” 和 “ 恢復(fù)現(xiàn)場 ”的內(nèi)容并不一定會相同。此標(biāo)志是一個(gè)定義在 /include/linux/ 中的一個(gè)宏: if defined __i386__ amp。當(dāng)系統(tǒng)調(diào)用總控程序執(zhí)行到此語句時(shí), eax中的內(nèi)容即是相應(yīng)系統(tǒng)調(diào)用的編號,此編號即相應(yīng)服務(wù)程序在系統(tǒng)調(diào)用向量表sys_call_table中的編號(系統(tǒng)調(diào)用的編號的有關(guān)說明在/linux/include/asm/)。也就是說,只要用戶程序執(zhí)行 0x80中斷 ( int 0x80 ),就可實(shí)現(xiàn) “ 用戶程序 系統(tǒng)調(diào)用總控程序 ” 的進(jìn)入。 ? 實(shí)際上,很多已經(jīng)被習(xí)以為常的 C語言標(biāo)準(zhǔn)函數(shù),在 Linux平臺上的實(shí)現(xiàn)都是靠系統(tǒng)調(diào)用完成的,所以如果想對系統(tǒng)底層的原理作深入的了解,掌握各種系統(tǒng)調(diào)用是初步的要求。這個(gè)過程檢查系統(tǒng)調(diào)用號,該號碼告訴內(nèi)核進(jìn)程請求哪種服務(wù)。系統(tǒng)調(diào)用的原理是:進(jìn)程先用適當(dāng)?shù)闹堤畛浼拇嫫?,然后調(diào)用一個(gè)特殊的指令跳轉(zhuǎn)一個(gè)事先定義的內(nèi)核中的一個(gè)位置(當(dāng)然,這個(gè)位置是用戶進(jìn)程可讀但是不可寫的)。二者在使用方式上也有相似之處。 系統(tǒng)調(diào)用過程 圖 系統(tǒng)調(diào)用過程示意圖 ? Linux內(nèi)核中設(shè)置了一組用于實(shí)現(xiàn)各種系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用。較詳細(xì)地討論了系統(tǒng)調(diào)用 wait、waitpid和 exec函數(shù)族,并通過兩個(gè)實(shí)際例子來說明系統(tǒng)調(diào)用。 系統(tǒng)調(diào)用概述 ? 所有的操作系統(tǒng)都提供多種服務(wù)的入口點(diǎn),由此程序向內(nèi)核請求服務(wù)。用戶可以通過系統(tǒng)調(diào)用命令在自己的應(yīng)用程序中調(diào)用它們。 ? 隨 Linux核心還提供了一些 C語言函數(shù)庫,這些庫對系統(tǒng)調(diào)用進(jìn)行了一些包裝和擴(kuò)展,因?yàn)檫@些庫函數(shù)與系統(tǒng)調(diào)用的關(guān)系非常緊密,所以習(xí)慣上把這些函數(shù)也稱為系統(tǒng)調(diào)用。硬件知道一旦跳到這個(gè)位置,就不是在限制模式下運(yùn)行的用戶,而是作為操作系統(tǒng)的內(nèi)核。然后內(nèi)核進(jìn)程查看系統(tǒng)調(diào)用表 (sys_call_table)找到所調(diào)用的內(nèi)核函數(shù)入口地址。 Linux下編程高手,其標(biāo)志之一也是能對各種系統(tǒng)調(diào)用有透徹的了解。只是0x80中斷的執(zhí)行語句 int 0x80 被封裝在標(biāo)準(zhǔn) C庫中,用戶程序只需用標(biāo)準(zhǔn)系統(tǒng)調(diào)用函數(shù)就可以了,而不需要在用戶程序中直接寫 0x80中斷的執(zhí)行語句 int 0x80。又因?yàn)橄到y(tǒng)調(diào)用向量表 sys_call_table每項(xiàng)占 4個(gè)字節(jié),所以由 %eax 乘上4形成偏移地址,而 sys_call_table則為基址;基址加上偏移所指向的內(nèi)容就是相應(yīng)系統(tǒng)調(diào)用服務(wù)程序的入口地址。amp。 ? ( 3)特殊的服務(wù)程序:在 Linux內(nèi)核中,有好幾個(gè)系統(tǒng)調(diào)用的服務(wù)程 序都是定義在 /usr/src/linux/kernel/ 中的同一個(gè)函數(shù): asmlinkage int sys_ni_syscall(void) { return ENOSYS; } ? 此函數(shù)除了返回錯誤號之外,什么都沒干。 ? 下面以 sethostname()這個(gè)簡單的系統(tǒng)調(diào)用作為例子,介紹系統(tǒng)調(diào)用中進(jìn)入內(nèi)核空間,以及完成了服務(wù)返回用戶空間的過程。失敗時(shí)可從全局變量 errno 中得到具體的出錯代碼。這是一種約定, gcc在使用寄存器時(shí)會遵守這個(gè)約定。 接著,又調(diào)用 _erron_location(),將全局變?yōu)? errno中。 the_time=time((time_t *)0); //調(diào)用 time系統(tǒng)調(diào)用 printf(The time is %ld\n,the_time)。 include main() { time_t the_time。 ? *()是什么? 在 7個(gè)宏,分別是 _syscall0(type,name) _syscall1(type,name,type1,arg1) _syscall2(type,name,type1,arg1,type2,arg2) _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4, arg4,type5,arg5) _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) ? 它們看起來似乎不太像宏,但其實(shí)質(zhì)和 define MAXSIZE 100 里面的 MAXSIZE沒有任何區(qū)別。 __asm__ volatile(int $0x80 : =a (__res) : 0 (13),b ((long)(tloc)))。 } while (0) 。如果一個(gè)系統(tǒng)調(diào)用失敗,可以讀出 errno的值來確定問題所在。 ? 在絕大多數(shù)的情況下,系統(tǒng)調(diào)用要比自己編寫的代碼可靠而高效的多。 與進(jìn)程管理相關(guān)的系統(tǒng)調(diào)用 ? 下面介紹與 Linux進(jìn)程管理相關(guān)的 4個(gè)重要系統(tǒng)調(diào)用 getpid、 fork、 exit和 _exit,并舉出一些例程說明了它們的特點(diǎn)和使用方法。在 i386架構(gòu)上, pid_t類型是和 int類型完全兼容的,可以用處理整形數(shù)的方法去處理 pid_t類型的數(shù)據(jù),如用 %d把它打印出來。 ? fork系統(tǒng)調(diào)用的作用是復(fù)制一個(gè)進(jìn)程。其他一些庫函數(shù),如 system(),它們實(shí)際上也在內(nèi)部調(diào)用了 fork。 ? //此時(shí)僅有一個(gè)進(jìn)程 pid=fork()。 } ? 編譯并運(yùn)行: $gcc o fork_test $./fork_test I am the parent process, my process ID is 1991 I am the child process, my process ID is 1992 ? 看這個(gè)程序的時(shí)候,必須首先了解:在語句 pid=fork()之前,只有一個(gè)進(jìn)程在執(zhí)行這段代碼,但在這條語句之后,就變成兩個(gè)進(jìn)程在執(zhí)行了,這兩個(gè)進(jìn)程的代碼部分完全相同,將要執(zhí)行的下一條語句都是if(pid==0)…… 。( 2)系統(tǒng)內(nèi)存不足,這時(shí) errno的值被設(shè)置為 ENOMEM。兩個(gè)進(jìn)程里都各有一條它們永遠(yuǎn)執(zhí)行不到的語句。下面的程序: ? // include main() { printf(this process will exit!\n)。 ? exit系統(tǒng)調(diào)用帶有一個(gè)整數(shù)類型的參數(shù)status,可以利用這個(gè)參數(shù)傳遞進(jìn)程結(jié)束時(shí)的狀態(tài),比如說,該進(jìn)程是正常結(jié)束的,還是出現(xiàn)某種意外而結(jié)束的,一般來說, 0表示沒有意外的正常結(jié)束;其他的數(shù)值表示出現(xiàn)了錯誤,進(jìn)程非正常結(jié)束。 ? 隨便一個(gè)懂得 C語言的人都會說, _exit和exit沒有任何區(qū)別,但這兩者之間確實(shí)是有區(qū)別的,這種區(qū)別主要體現(xiàn)在函數(shù)庫中的定義。從圖中可以看出, _exit()函數(shù)的作用最為簡單:直接使進(jìn)程停止運(yùn)行,清除其使用的內(nèi)存空間,并清除其在內(nèi)核中的各種數(shù)據(jù)結(jié)構(gòu); exit()函數(shù)則在這些基礎(chǔ)上作了一些包裝,在執(zhí)行退出之前加了若干道工序。如果有一些數(shù)據(jù),認(rèn)為已經(jīng)寫入了文件,實(shí)際上因?yàn)闆]有滿足特定的條件,它們還只是保存在緩沖區(qū)內(nèi),這時(shí)用 _exit()函數(shù)直接將進(jìn)程關(guān)閉,緩沖區(qū)中的數(shù)據(jù)就會丟失,反之,如果想保證數(shù)據(jù)的完整性,就一定要使用 exit()函數(shù)。 } ? 編譯并運(yùn)行: $gcc o exit2 $./exit2 output begin content in buffer // include main() { printf(output begin\n)。與所有其他文件一樣,它們在打開后也有自己的緩沖區(qū)。進(jìn)程的當(dāng)前工作目錄一般是應(yīng)用程序啟動時(shí)的目錄,一旦進(jìn)程開始運(yùn)行后,當(dāng)前工作目錄就會保持不變,除非調(diào)用 chdir。 ? 2. 系統(tǒng)調(diào)用 setsid include pid_t setsid(void)。 ? 系統(tǒng)調(diào)用 umask可以設(shè)定一個(gè)文件權(quán)限掩碼,用戶可以用它來屏蔽某些權(quán)限,以防止誤操作導(dǎo)致給予某些用戶過高的權(quán)限。 pid=fork()。 // 休眠 60秒,這段時(shí)間里,父進(jìn)程什 么也干不了 wait(NULL)。 ? 系統(tǒng)調(diào)用 exit的作用是使進(jìn)程退出,但僅僅限于將一個(gè)正常的進(jìn)程變成一個(gè)僵尸進(jìn)程,并不能將其完全銷毀。 ? waitpid調(diào)用和 wait調(diào)用都可收集僵尸進(jìn)程留下的信息,同時(shí)使這個(gè)進(jìn)程徹底消失。但如果并不關(guān)心這個(gè)子進(jìn)程是如何死掉的,只是想消滅這個(gè)僵尸進(jìn)程,可將該參數(shù)設(shè)定為 NULL,即:
點(diǎn)擊復(fù)制文檔內(nèi)容
教學(xué)課件相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖片鄂ICP備17016276號-1