欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
庫函數和系統調用
庫函數是語(yǔ)言本身的一部分,而系統函數是內核提供給應用程序的接口,屬于系統的一部分。
函數庫調用是語(yǔ)言或應用程序的一部分,而系統調用是操作系統的一部分。你要確保弄懂“trap(自陷)”這個(gè)關(guān)鍵字的含義。系統調用是在操作系統內核發(fā)現一個(gè)“trap”或中斷后進(jìn)行的(其中系統調用是軟中斷)。
函數庫調用 VS 系統調用
函數庫調用
系統調用
在所有的ANSI C編譯器版本中,C庫函數是相同的
各個(gè)操作系統的系統調用是不同的
它調用函數庫中的一段程序(或函數)
它調用系統內核的服務(wù)
與用戶(hù)程序相聯(lián)系
是操作系統的一個(gè)入口點(diǎn)
在用戶(hù)地址空間執行
在內核地址空間執行
它的運行時(shí)間屬于“用戶(hù)時(shí)間”
它的運行時(shí)間屬于“系統”時(shí)間
屬于過(guò)程調用,調用開(kāi)銷(xiāo)較小
需要在用戶(hù)空間和內核上下文環(huán)境間切換,開(kāi)銷(xiāo)較大
在C函數庫libc中有大約300個(gè)函數
在UNIX中大約有90個(gè)系統調用
典型的C函數庫調用:system fprintf malloc
典型的系統調用:chdir fork write brk;
庫函數調用通常比行內展開(kāi)的代碼慢,因為它需要付出函數調用的開(kāi)銷(xiāo)。但系統調用比庫函數調用還要慢很多,因為它需要把上下文環(huán)境切換到內核模式。
系統調用和函數庫的關(guān)系:
◆ 系統調用通過(guò)軟中斷int 0x80從用戶(hù)態(tài)進(jìn)入內核態(tài)。
◆ 函數庫中的某些函數調用了系統調用。
◆ 函數庫中的函數可以沒(méi)有調用系統調用,也可以調用多個(gè)系統調用。
◆ 編程人員可以通過(guò)函數庫調用系統調用。
◆ 高級編程也可以直接采用int 0x80進(jìn)入系統調用,而不必通過(guò)函數庫作為中介。
◆ 如果是在核心編程,也可以通過(guò)int 0x80進(jìn)入系統調用,此時(shí)不能使用函數庫。因為函數庫中的函數是內核訪(fǎng)問(wèn)不到的。
從用戶(hù)調用庫函數到系統調用執行的流程。
1)  假設用戶(hù)調用ssize_t write (int fields, cont void *buff, size_t nbytes);庫函數。
2) 庫函數會(huì )執行int 0x80中斷。因為中斷使得進(jìn)程從用戶(hù)態(tài)進(jìn)入內核態(tài),所以參數通過(guò)寄存器傳送。
3) 0x80中斷對應的中斷例程被稱(chēng)為system call handler。其工作是:
i.存儲大多數寄存器到內核堆棧中。這是匯編代碼寫(xiě)的。
ii.執行真正的系統調用函數――system call service routine。這是C代碼。
iii.通過(guò)ret_from_sys_call ()返回,回到用戶(hù)態(tài)的庫函數。這是匯編代碼。
來(lái)源:http://bbs.chinaunix.net/thread-3641846-1-1.html
********************************************************************
系統調用和庫函數調用
(1)讓我們忽略L(fǎng)inux對段式內存映射的支持。
在保護模式下,我們知道無(wú)論CPU運行于用戶(hù)態(tài)還是核心態(tài),CPU執行程序所訪(fǎng)問(wèn)的地址都是虛擬地址,MMU
必須通過(guò)讀取控制寄存器CR3中的值作為當前頁(yè)面目錄的指針,進(jìn)而根據分頁(yè)內存映射機制(參看相關(guān)文檔)將該虛擬地址轉換為真正的物理地址才能讓CPU真
正的訪(fǎng)問(wèn)到物理地址。
(2)對于32位的Linux,其每一個(gè)進(jìn)程都有4G的尋址空間,但當一個(gè)進(jìn)程訪(fǎng)問(wèn)其虛擬內存空間中的某個(gè)地址時(shí)又是怎樣實(shí)現不與其它進(jìn)程的虛擬空間混淆
的呢?每個(gè)進(jìn)程都有其自身的頁(yè)面目錄PGD,Linux將該目錄的指針存放在與進(jìn)程對應的內存結構task_struct.(struct
mm_struct)mm->pgd中。每當一個(gè)進(jìn)程被調度(schedule())即將進(jìn)入運行態(tài)時(shí),Linux內核都要用該進(jìn)程的PGD指針設
置CR3(switch_mm())。
(3)當創(chuàng )建一個(gè)新的進(jìn)程時(shí),都要為新進(jìn)程創(chuàng )建一個(gè)新的頁(yè)面目錄PGD,并從內核的頁(yè)面目錄swapper_pg_dir中復制內核區間頁(yè)面目錄項至新建進(jìn)程頁(yè)面目錄PGD的相應位置,具體過(guò)程如下:
do_fork() --> copy_mm() --> mm_init() --> pgd_alloc() -->
set_pgd_fast() --> get_pgd_slow() --> memcpy(&PGD +
USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD -
USER_PTRS_PER_PGD) * sizeof(pgd_t))
這樣一來(lái),每個(gè)進(jìn)程的頁(yè)面目錄就分成了兩部分,第一部分為“用戶(hù)空間”,用來(lái)映射其整個(gè)進(jìn)程空間(0x0000 0000-0xBFFF
FFFF)即3G字節的虛擬地址;第二部分為“系統空間”,用來(lái)映射(0xC000 0000-0xFFFF
FFFF)1G字節的虛擬地址??梢钥闯鯨inux系統中每個(gè)進(jìn)程的頁(yè)面目錄的第二部分是相同的,所以從進(jìn)程的角度來(lái)看,每個(gè)進(jìn)程有4G字節的虛擬空間,
較低的3G字節是自己的用戶(hù)空間,最高的1G字節則為與所有進(jìn)程以及內核共享的系統空間。
(4)現在假設我們有如下一個(gè)情景:
在進(jìn)程A中通過(guò)系統調用sethostname(const char *name,seze_t len)設置計算機在網(wǎng)絡(luò )中的“主機名”.
在該情景中我們勢必涉及到從用戶(hù)空間向內核空間傳遞數據的問(wèn)題,name是用戶(hù)空間中的地址,它要通過(guò)系統調用設置到內核中的某個(gè)地址中。讓我們看看這個(gè)
過(guò)程中的一些細節問(wèn)題:系統調用的具體實(shí)現是將系統調用的參數依次存入寄存器ebx,ecx,edx,esi,edi(最多5個(gè)參數,該情景有兩個(gè)
name和len),接著(zhù)將系統調用號存入寄存器eax,然后通過(guò)中斷指令“int
80”使進(jìn)程A進(jìn)入系統空間。由于進(jìn)程的CPU運行級別小于等于為系統調用設置的陷阱門(mén)的準入級別3,所以可以暢通無(wú)阻的進(jìn)入系統空間去執行為int
80設置的函數指針system_call()。由于system_call()屬于內核空間,其運行級別DPL為0,CPU要將堆棧切換到內核堆棧,即
進(jìn)程A的系統空間堆棧。我們知道內核為新建進(jìn)程創(chuàng )建task_struct結構時(shí),共分配了兩個(gè)連續的頁(yè)面,即8K的大小,并將底部約1k的大小用于
task_struct(如#define alloc_task_struct() ((struct task_struct *)
__get_free_pages(GFP_KERNEL,1))),而其余部分內存用于系統空間的堆??臻g,即當從用戶(hù)空間轉入系統空間時(shí),堆棧指針
esp變成了(alloc_task_struct()+8192),這也是為什么系統空間通常用宏定義current(參看其實(shí)現)獲取當前進(jìn)程的
task_struct地址的原因。每次在進(jìn)程從用戶(hù)空間進(jìn)入系統空間之初,系統堆棧就已經(jīng)被依次壓入用戶(hù)堆棧SS、用戶(hù)堆棧指針ESP、EFLAGS、
用戶(hù)空間CS、EIP,接著(zhù)system_call()將eax壓入,再接著(zhù)調用SAVE_ALL依次壓入ES、DS、EAX、EBP、EDI、ESI、
EDX、ECX、EBX,然后調用sys_call_table+4*%EAX,本情景為sys_sethostname()。
(5)在sys_sethostname()中,經(jīng)過(guò)一些保護考慮后,調用copy_from_user(to,from,n),其中to指向內核空間
system_utsname.nodename,譬如0xE625A000,from指向用戶(hù)空間譬如0x8010FE00?,F在進(jìn)程A進(jìn)入了內核,在
系統空間中運行,MMU根據其PGD將虛擬地址完成到物理地址的映射,最終完成從用戶(hù)空間到系統空間數據的復制。準備復制之前內核先要確定用戶(hù)空間地址和
長(cháng)度的合法性,至于從該用戶(hù)空間地址開(kāi)始的某個(gè)長(cháng)度的整個(gè)區間是否已經(jīng)映射并不去檢查,如果區間內某個(gè)地址未映射或讀寫(xiě)權限等問(wèn)題出現時(shí),則視為壞地址,
就產(chǎn)生一個(gè)頁(yè)面異常,讓頁(yè)面異常服務(wù)程序處理。過(guò)程如
下:copy_from_user()->generic_copy_from_user()->access_ok()+__copy_user_zeroing().
(6)小結:
*進(jìn)程尋址空間0~4G
*進(jìn)程在用戶(hù)態(tài)只能訪(fǎng)問(wèn)0~3G,只有進(jìn)入內核態(tài)才能訪(fǎng)問(wèn)3G~4G
*進(jìn)程通過(guò)系統調用進(jìn)入內核態(tài)
*每個(gè)進(jìn)程虛擬空間的3G~4G部分是相同的
*進(jìn)程從用戶(hù)態(tài)進(jìn)入內核態(tài)不會(huì )引起CR3的改變但會(huì )引起堆棧的改變
http://familyj.spaces.live.com/blog/cns!F3D148183B0189EE!566.entry
從程序完成的功能來(lái)看,函數庫提供的函數通常是不需要操作系統的服務(wù),函數是在用戶(hù)空間內執行的,除非函數涉及到I/O操作等,一般是不會(huì )切到核心態(tài)的。系統調用是要求操作系統為用戶(hù)提供進(jìn)程,提供某種服務(wù),通常是涉及系統的硬件資源和一些敏感的軟件資源等。
數庫的函數,尤其與輸入輸出相關(guān)的函數,大多必須通過(guò)Linux的系統調用來(lái)完成。因此我們可以將函數庫的函數當成應用程序設計人員與系統調用程序之間的
一個(gè)中間層,通過(guò)這個(gè)中間層,我們可以用一致的接口來(lái)安全的調用系統調用。這樣程序員可以只要寫(xiě)一次代碼就能夠在不同版本的linux系統間使用積壓種具
體實(shí)現完全不同的系統調用。至于如何實(shí)現對不同的系統調用的兼容性問(wèn)題,那是函數庫開(kāi)發(fā)者所關(guān)心的問(wèn)題。
從程序執行效率來(lái)看,系統調用的
執行效率大多要比函數高,尤其是處理輸入輸出的函數。當處理的數據量比較小時(shí),函數庫的函數執行效率可能比較好,因為函數庫的作法是將要處理的數據先存入
緩沖區內,等到緩沖區裝滿(mǎn)了,再將數據一次寫(xiě)入或者讀出。這種方式處理小量數據時(shí)效率比較高,但是在進(jìn)行系統調用時(shí),因為用戶(hù)進(jìn)程從用戶(hù)模式進(jìn)入系統核心
模式,中間涉及了許多額外的任務(wù)的切換工作,這些操作稱(chēng)為上下文切換,此類(lèi)的額外工作會(huì )影響系統的執行效率。但是當要處理的數據量比較大時(shí),例如當輸入輸
出的數據量超過(guò)文件系統定義的盡寸時(shí),利用系統調用可獲得較高的效率。
從程序的可移植性的角度來(lái)看,相對于系統調用,C語(yǔ)言的標準備函數庫(ANSI C) 具備較高的可移植性,在不同的系統環(huán)境下,只要做很少的修改,通常情況是不需要修改的。
[color="#1f497d"]Linux C中庫函數和系統調用的區別
摘自:The Linux Kernel Module Programming Guide
庫函數是高層的,完全運行在用戶(hù)空間,
為程序員提供調用真正的在幕后完成實(shí)際事務(wù)的系統調用的更方便的接口。系統調用在內核態(tài)運行并且由內核自己提供。標準C庫函數printf()可以被看做
是一個(gè)通用的輸出語(yǔ)句,但它實(shí)際做的是將數據轉化為符合格式的字符串并且調用系統調用 write()輸出這些字符串。
是否想看一看printf()究竟使用了哪些系統調用? 這很容易,編譯下面的代碼。
#include
int main(void)
{ printf("hello"); return 0; }
使用命令gcc -Wall -o hello hello.c編譯。用命令 strace hello
跟蹤該可執行文件。是否很驚訝? 每一行都和一個(gè)系統調用相對應。
strace是一個(gè)非常有用的程序,它可以告訴你程序使用了哪些系統調用和這些系統調用的參數,返回值。
這是一個(gè)極有價(jià)值的查看程序在干什么的工具。在輸出的末尾,你應該看到這樣類(lèi)似的一行 write(1, "hello",
5hello)。這就是我們要找的。藏在面具printf() 的真實(shí)面目。既然絕大多數人使用庫函數來(lái)對文件I/O進(jìn)行操作(像 fopen,
fputs, fclose)。 你可以查看man說(shuō)明的第二部分使用命令man 2 write
。man說(shuō)明的第二部分專(zhuān)門(mén)介紹系統調用(像kill()和read())。
man說(shuō)明的第三部分則專(zhuān)門(mén)介紹你可能更熟悉的庫函數(像cosh()和random())。
你甚至可以編寫(xiě)代碼去覆蓋系統調用,正如我們不久要做的。駭客常這樣做來(lái)為系統安裝后門(mén)或木馬。 但你可以用它來(lái)完成一些更有益的事,像讓內核在每次某人刪除文件時(shí)輸出 “ Tee hee, that tickles!” 的信息。
http://familyj.spaces.live.com/blog/cns!F3D148183B0189EE!566.entry
整個(gè)系統調用的過(guò)程可以總結如下:
1. 執行用戶(hù)程序(如:fork)
2. 根據glibc中的函數實(shí)現,取得系統調用號并執行int $0x80產(chǎn)生中斷。
3. 進(jìn)行地址空間的轉換和堆棧的切換,執行SAVE_ALL。(進(jìn)行內核模式)
4. 進(jìn)行中斷處理,根據系統調用表調用內核函數。
5. 執行內核函數。
6. 執行RESTORE_ALL并返回用戶(hù)模式
本文來(lái)自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u2/67750/showart_2161893.html
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Linux內核Crash分析
內存映射及管理
Linux內存管理 下
linux內核分析筆記----進(jìn)程管理
LINUX2.6中進(jìn)程的內核空間共享
X86-64上的Linux VM管理系統
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久