linux內核調用
㈠ linux 怎麼調用內核導出的函數
Linux內核沒有導出的函數不能調用,即使包含了頭文件,也會出現符號未定義的警告,並在載入模塊時失敗。
以下是我的測試例子:
#include <linux/mole.h>
#include <linux/syscalls.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linmiaohe");
MODULE_DESCRIPTION("try to evole sys_umount");
extern asmlinkage long sys_umount(char __user *name, int flags);
static int __init sys_umount_init(void)
{
sys_umount("./proc",0);
return 0;
}
static void __exit sys_umount_exit(void)
{
printk(KERN_INFO "***********sys_umount mole has been unregistered*************\n");
}
mole_init(sys_umount_init);
mole_exit(sys_umount_exit);
㈡ Linux的庫函數是如何調用內核函數的
看系統調用,還有庫函數,以前一直不明白,總是以為 系統調用跟庫函數是一樣的,但是今天才知道是不一樣的。
庫函數也就是我們通常所說的應用編程介面API,它其實就是一個函數定義,比如常見read()、write()等函數說明了如何獲得一個給定的服務,但是系統調用是通過軟中斷向內核發出一個明確的請求,再者系統調用是在內核完成的,而用戶態的函數是在函數庫完成的。
系統調用發生在內核空間,因此如果在用戶空間的一般應用程序中使用系統調用來進行文件操作,會有用戶空間到內核空間切換的開銷。事實上,即使在用戶空間使用庫函數來對文件進行操作,因為文件總是存在於存儲介質上,因此不管是讀寫操作,都是對硬體(存儲器)的操作,都必然會引起系統調用。也就是說,庫函數對文件的操作實際上是通過系統調用來實現的。例如C庫函數fwrite()就是通過write()系統調用來實現的。
這樣的話,使用庫函數也有系統調用的開銷,為什麼不直接使用系統調用呢?這是因為,讀寫文件通常是大量的數據(這種大量是相對於底層驅動的系統調用所實現的數據操作單位而言),這時,使用庫函數就可以大大減少系統調用的次數。這一結果又緣於緩沖區技術。在用戶空間和內核空間,對文件操作都使用了緩沖區,例如用fwrite寫文件,都是先將內容寫到用戶空間緩沖區,當用戶空間緩沖區滿或者寫操作結束時,才將用戶緩沖區的內容寫到內核緩沖區,同樣的道理,當內核緩沖區滿或寫結束時才將內核緩沖區內容寫到文件對應的硬體媒介。
系統調用與系統命令:系統命令相對API更高一層,每個系統命令都是一個可執行程序,比如常用的系統命令ls、hostname等,比如strace ls就會發現他們調用了諸如open(),brk(),fstat(),ioctl()等系統調用。
系統調用是用戶進程進入內核的介面層,它本身並非內核函數,但他是由內核函數實現的,進入系統內核後,不同的系統調用會找到各自對應的內核函數,這寫內核函數被稱為系統調用的「服務常式」。也可以說系統調用是服務常式的封裝常式。
㈢ Linux內核中shutdown系統調用
shutdown()系統調用的功能是關閉一個套接字的指定桐尺橋方向上的通信。
函數原型為:
對應的會調用內核中的函數:困睜
以ipv6為例
傳輸層注冊的shutdown函數為tcp_shutdown:局猛
㈣ linux內核調用哪些介面分配內核地址空間的內存
kmalloc/kfree
類似於標准C中的malloc/free,kmalloc/kfree是內核中的用於常規內存分配的介面。
例如,申請1024位元組的內核地址空間:
char*buff;
buff=kmalloc(1024,GFP_KERNEL);
if(!buff)
return-ENOMEM;
還有什麼問題的話,可以私信我哦
㈤ 如何調用Linux內核函數
注意看這個文件
sysdeps/unix/sysv/linux/syscalls.list
裡面記錄著系統調用的名字和一些屬性,具體我也沒有研究過,不懂。
再看select的實現,很讓人驚訝,一旦使用,結果就是「報錯「。
int
__select (nfds, readfds, writefds, exceptfds, timeout)
int nfds;
fd_set *readfds;
fd_set *writefds;
fd_set *exceptfds;
struct timeval *timeout;
{
__set_errno (ENOSYS);
return -1;
}
libc_hidden_def (__select)
stub_warning (select)
weak_alias (__select, select)
這是因為glibc並沒有實現系統調用,而是調用系統調用,
更進一步,連調用系統調用都沒有一個個實現,而是使用了通用的辦法,
理由很簡單,所有的系統調用在linux內核頭文件里都能找到,
所有的系統調用參數類型就那麼幾種,參數個數也是有限的,
因此沒有必要針對所有的系統調用一一封裝,
於是就有了這個list文件,自動生成調用系統調用的函數,
如果生成失敗,也就是你看到的「報錯」。
符號是有強弱的,當自動生成成功的時候,「報錯」的弱符號就被忽略了。
當你在glibc中找到一個系統調用的封裝源碼,是以下原因,
1. 編譯的目標系統不支持這個系統調用,所以自己用另一種方式實現了。
2. 這個系統調用無法使用通用的自動生成方式生成,用特化的方式覆蓋。
3. 針對這個系統調用做了特別的優化。
4. 其它可能的原因。
具體可以留意
SYSCALL, PSEUDO, DO_CALL, INLINE_CALL 等名字
這兩個文件是重點所在
sysdeps/unix/i386/sysdep.h
sysdeps/unix/i386/sysdep.S
要搞清楚具體的自動生成過程,恐怕得研究glibc自身的編譯過程了
㈥ 如何在linux內核中調用用戶空間的程序
教科書里的Linux代碼例子都已作古,所以看到的代碼不能當真,領會意思就行了
比如以前的init進程的啟動代碼
execve(init_filename,argv_init,envp_init);
現在改為
static void run_init_process(char *init_filename)
{
argv_init[0] = init_filename;
kernel_execve(init_filename, argv_init, envp_init);
}
好的,聰明人就發現,linux內核中調用用戶空間的程序可以使用init這樣的方式,調用 kernel_execve
不過內核還是提供了更好的輔助介面call_usermodehelper,自然最後也是調用kernel_execve
調用特定的內核函數(系統調用)是 GNU/Linux 中軟體開發的原本就有的組成部分。但如果方向反過來呢,內核空間調用用戶空間?確實有一些有這種特性的應用程序需要每天使用。例如,當內核找到一個設備,這時需要載入某個模塊,進程如何處理?動態模塊載入在內核通過 usermode-helper 進程進行。
讓我們從探索 usermode-helper 應用程序編程介面(API)以及在內核中使用的例子開始。 然後,使用 API 構造一個示例應用程序,以便更好地理解其工作原理與局限。
usermode-helper API
usermode-helper API 是個很簡單的 API,其選項為用戶熟知。例如,要創建一個用戶空間進程,通常只要設置名稱為 executable,選項都為 executable,以及一組環境變數(指向 execve 主頁)。創建內核進程也是一樣。但由於創建內核空間進程,還需要設置一些額外選項。