Linux系統呼叫(C內嵌彙編)

2021-08-26 19:25:43 字數 4041 閱讀 5203

linux下對檔案操作有兩種方式:系統呼叫(systemcall)和庫函式呼叫(library functions)。可以參考《linux程式設計》(英文原版為《beginning linuxprogramming》,作者是neil matthew和richard stones)第三章: working with files。

1

.系統呼叫

系統呼叫提供的函式如open, close,read, write, ioctl等,需包含標頭檔案unistd.h。以write為例:其函式原型為 size_t write(int fd, constvoid *buf, size_t nbytes),其操作物件為檔案描述符或檔案控制代碼fd(filedescriptor),要想寫乙個檔案,必須先以可寫許可權用open系統呼叫開啟乙個檔案,獲得所開啟檔案的fd,例如fd=open(/"/dev/video/", o_rdwr)。fd是乙個整型值,每新開啟乙個檔案,所獲得的fd為當前最大fd加1。linux系統預設分配了3個檔案描述符值:0-standardinput,1-standardoutput,2-standard error。

系統呼叫通常用於底層檔案訪問(low-levelfile access),例如在驅動程式中對裝置檔案的直接訪問。

系統呼叫是作業系統相關的,因此一般沒有跨作業系統的可移植性。

系統呼叫發生在核心空間,因此如果在使用者空間的一般應用程式中使用系統呼叫來進行檔案操作,會有使用者空間到核心空間切換的開銷。事實上,即使在使用者空間使用庫函式來對檔案進行操作,因為檔案總是存在於儲存介質上,因此不管是讀寫操作,都是對硬體(儲存器)的操作,都必然會引起系統呼叫。也就是說,庫函式對檔案的操作實際上是通過系統呼叫來實現的。例如c庫函式fwrite()就是通過write()系統呼叫來實現的。

這樣的話,使用庫函式也有系統呼叫的開銷,為什麼不直接使用系統呼叫呢?這是因為,讀寫檔案通常是大量的資料(這種大量是相對於底層驅動的系統呼叫所實現的資料操作單位而言),這時,使用庫函式就可以大大減少系統呼叫的次數。這一結果又緣於緩衝區技術。在使用者空間和核心空間,對檔案操作都使用了緩衝區,例如用fwrite寫檔案,都是先將內容寫到使用者空間緩衝區,當使用者空間緩衝區滿或者寫操作結束時,才將使用者緩衝區的內容寫到核心緩衝區,同樣的道理,當核心緩衝區滿或寫結束時才將核心緩衝區內容寫到檔案對應的硬體媒介。

2

.庫函式呼叫

標準c庫函式提供的檔案操作函式如fopen,fread, fwrite, fclose, fflush, fseek等,需包含標頭檔案stdio.h。以fwrite為例,其函式原型為size_tfwrite(const void *buffer, size_t size, size_t item_num, file*pf),其操作物件為檔案指標file*pf,要想寫乙個檔案,必須先以可寫許可權用fopen函式開啟乙個檔案,獲得所開啟檔案的file結構指標pf,例如pf=fopen(/"~/proj/filename/",/"w/")。實際上,由於庫函式對檔案的操作最終是通過系統呼叫實現的,因此,每開啟乙個檔案所獲得的file結構指標都有乙個核心空間的檔案描述符fd與之對應。同樣有相應的預定義的file指標:stdin-standardinput,stdout-standard output,stderr-standard error。

庫函式呼叫通常用於應用程式中對一般檔案的訪問。

庫函式呼叫是系統無關的,因此可移植性好。

由於庫函式呼叫是基於c庫的,因此也就不可能用於核心空間的驅動程式中對裝置的操作

eg

char *str = "helloworld!/n";

void print()

void exit()

void nomain()

**大概意思是nomain()是入口,然後呼叫print()函式,列印"helloworld」,接著呼叫exit()函式,結束程序。這裡的print函式使用了linux的write系統呼叫,exit使用了exit系統呼叫,用內聯彙編實現。

連線命令如下:

gcc –c

-fno-builtin

hello.c

ld–static –e nomain –o hello hello.o

注意,這裡控制了鏈結器的行為,用-e指定了入口函式為nomain

那麼問題來了系統呼叫引數怎麼傳遞的?不懂:

google

了一把,找到了下面解釋c

或組合語言中也需要通過某些途徑來使用作業系統提供的服務,也就是系統呼叫;系統呼叫就是通過與作業系統核心通訊來完成;系統呼叫會把使用者態程式的呼叫轉換成對系統核心服務的呼叫;

linux平台下有兩種方式來使用系統呼叫:一種是利用封裝後的c庫(libc),另一種是通過彙編直接呼叫;其中,通過組合語言來直接呼叫系統呼叫,是最高效地使用linux核心服務的方法,因為最終生成的程式不需要與任何庫進行連線,而是直接與核心通訊;

與dos一樣,linux下的系統呼叫也是通過中斷(int0x80)方式來實現的;

在執行"int$0x80"指令時,暫存器eax中存放的是系統呼叫的功能號(即:中斷功能號,dos下存放在ah中),所有的系統呼叫功能號都可以再檔案/usr/include/bits/syscall.h中找到,為了便於使用,它們都是用"sys_"這樣的巨集來定義的;如:sys_write、sys_exit等;

系統呼叫的引數傳遞規則:

傳遞給系統呼叫的引數則必須按照引數順序依次存放到暫存器ebx,ecx,edx,esi,edi中,當系統呼叫完成之後,返回值存放在eax中;

a.當系統呼叫所需引數的個數不超過5個的時候,執行"int$0x80"指令時,需在eax中存放系統呼叫的功能號,傳遞給系統呼叫的引數則按照引數順序依次存放到暫存器ebx,ecx,edx,esi,edi中,當系統呼叫完成之後,返回值存放在eax中;

比如,經常用到的write函式的定義如下:

ssize_twrite(int fd, const void* buf, size_t count);

該函式的功能最終通過sys_write這一系統呼叫來實現的;根據上面的引數傳遞規則可知,引數fd存放在ebx中,引數buf存放在ecx中,引數count存放在edx中,而系統呼叫功能號sys_write則存放在暫存器eax中;系統呼叫執行完成之後,返回值可以從eax中得到;

b.當系統呼叫的引數超過5個的時候,執行"int$0x80"指令,需在eax中存放系統呼叫的功能號,所不同的只是全部的引數應該依次存放在一塊連續的記憶體區域裡,同時在暫存器ebx中儲存指向該記憶體區域的指標(即:該連續記憶體塊的首位址),返回值仍然儲存在暫存器eax中;由於只是需要一塊連續的記憶體區域來儲存系統呼叫所需要的引數,因此,完全可以像普通的函式呼叫一樣使用棧來傳遞系統呼叫所需要的引數;但是要注意一點:linux採用的是c語言的呼叫模式,這就意味著所有引數必須以相反的順序進棧,即:最後乙個引數最先進棧,而第乙個引數最後進棧;如果採用棧來傳遞系統呼叫所需要的引數,在執行"int$0x80"指令時,還應將棧指標的當前值(棧頂位址)複製到暫存器ebx中;

例如,系統呼叫mmap()的引數個數就超過5個:

void*mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

使用這個系統呼叫時,系統呼叫功能號儲存到eax中,mmap()所需要的所有引數存放到一塊連續的記憶體區域中,這塊連續記憶體區域的首位址存放到ebx中,即可;

c庫函式的引數傳遞規則:

1、引數從右向左依次入棧(push);

2、庫函式的返回值存放在暫存器eax中;

3、系統呼叫exit()的引數值在exit()呼叫結束程式退出的時候會被傳遞給系統shell,通過列印$?的值可看到;

彙編函式的返回值:

只要是函式,一般都需要返回值;組合語言中約定:對於32位的返回值,存放在暫存器eax中返回;對於64位的返回值,存放在暫存器eax和edx中返回,高位字放在edx中,低位字放在eax中;

參考鏈結

源文件 <>

源文件 <>

Linux系統呼叫(C內嵌彙編)

linux下對檔案操作有兩種方式 系統呼叫 systemcall 和庫函式呼叫 library functions 可以參考 linux程式設計 英文原版為 beginning linuxprogramming 作者是neil matthew和richard stones 第三章 working w...

linux中c語言常用內嵌彙編

原始碼位址 main2.c allen created by allenboy on 2018 1 20.編譯不過 可以生成.檔案 gcc s main2.cpp gcc version 7.2.0 ubuntu 7.2.0 8ubuntu3 include int a 10 int b 20 in...

Linux下彙編語法和內嵌彙編

做了乙個小例子 例子程式 使用了內嵌彙編 int main 彙編 使用gcc s 獲得 file test.c text globl main type main,function main leal 4 esp ecx andl 16,esp pushl 4 ecx pushl ebp movl ...