導航:首頁 > 數據分析 > 數據怎麼傳到內核

數據怎麼傳到內核

發布時間:2022-12-13 19:16:52

❶ 消息隊列通信方式為什麼在內核和用戶空間進行四次的數據拷貝,描述一下拷貝過程

消息隊列和管道基本上都是4次拷貝,而共享內存(mmap, shmget)只有兩次。
4次:1,由用戶空間的buf中將數據拷貝到內核中。2,內核將數據拷貝到內存中。3,內存到內核。4,內核到用戶空間的buf.
2次: 1,用戶空間到內存。 2,內存到用戶空間。

消息隊列和管道都是內核對象,所執行的操作也都是系統調用,而這些數據最終是要存儲在內存中執行的。因此不可避免的要經過4次數據的拷貝。但是共享內存不同,當執行mmap或者shmget時,會在內存中開辟空間,然後再將這塊空間映射到用戶進程的虛擬地址空間中,即返回值為一個指向一個內存地址的指針。當用戶使用這個指針時,例如賦值操作,會引起一個從虛擬地址到物理地址的轉化,會將數據直接寫入對應的物理內存中,省去了拷貝到內核中的過程。當讀取數據時,也是類似的過程,因此總共有兩次數據拷貝。

linux應用層通過ioctl向內核傳送數據,ioctl的fd參數如何使用

ioctl()和write()等函數使用相似,比如使用ioctl前會定義一個文件描述符fd:
char *fd="/dev/led"; //就是路徑。貌似有句話叫:linux萬物皆為文件

當你要用ioctl()向內核傳遞數據,就要使用fd,不然怎麼知道傳數據到哪去呢!
如: ioctl(fd,xxxxx,xxxxx); //xxxxx為要傳遞的值,具體網路吧,我也不是很清楚

❸ linux用戶空間怎麼傳數據給內核空間

需要使用特定的函數_to_user(),_from_user(),主要是這兩個函數。

❹ Linux內核:用戶空間與內核空間的數據傳遞方式

Linux採用了段頁式存儲管理方式,Linux的虛擬地址空間為0~4G,如圖1,Linux內核將這4G空間分為兩部分,0~3G(0xC0000000~0xFFFFFFFF)的部分為用戶空間,供用戶進程使用,3~4G(0x00000000~0xBFFFFFFF)的部分為內核空間,專門供內核使用[4]。

八種用戶空間與內核空間的數據交換方式,這八種方式各有優劣,下面就每種方式的優劣做一下對比:

❺ Linux網路 - 數據包在內核中接收和發送的過程(轉)

本文將介紹在Linux系統中, 數據包是如何一步一步從網卡傳到進程手中的 以及 數據包是如何一步一步從應用程序到網卡並最終發送出去的

如果英文沒有問題,強烈建議閱讀後面參考里的文章,裡面介紹的更詳細。

本文只討論乙太網的物理網卡,不涉及虛擬設備,並且以一個UDP包的接收過程作為示例.

網卡需要有驅動才能工作,驅動是載入到內核中的模塊,負責銜接網卡和內核的網路模塊,驅動在載入的時候將自己注冊進網路模塊,當相應的網卡收到數據包時,網路模塊會調用相應的驅動程序處理數據。

下圖展示了數據包(packet)如何進入內存,並被內核的網路模塊開始處理:

軟中斷會觸發內核網路模塊中的軟中斷處理函數,後續流程如下

由於是UDP包,所以第一步會進入IP層,然後一級一級的函數往下調:

應用層一般有兩種方式接收數據,一種是recvfrom函數阻塞在那裡等著數據來,這種情況下當socket收到通知後,recvfrom就會被喚醒,然後讀取接收隊列的數據;另一種是通過epoll或者select監聽相應的socket,當收到通知後,再調用recvfrom函數去讀取接收隊列的數據。兩種情況都能正常的接收到相應的數據包。

了解數據包的接收流程有助於幫助我們搞清楚我們可以在哪些地方監控和修改數據包,哪些情況下數據包可能被丟棄,為我們處理網路問題提供了一些參考,同時了解netfilter中相應鉤子的位置,對於了解iptables的用法有一定的幫助,同時也會幫助我們後續更好的理解Linux下的網路虛擬設備。

ndo_start_xmit會綁定到具體網卡驅動的相應函數,到這步之後,就歸網卡驅動管了,不同的網卡驅動有不同的處理方式,這里不做詳細介紹,其大概流程如下:

在網卡驅動發送數據包過程中,會有一些地方需要和netdevice子系統打交道,比如網卡的隊列滿了,需要告訴上層不要再發了,等隊列有空閑的時候,再通知上層接著發數據。

❻ 在linux編程中若一個用戶程序希望將一組數據傳遞給kernel有幾種方式

教科書里的代碼例子都已作古,所以看到的代碼不能當真,領會意思就行了
比如以前的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 主頁)。創建內核進程也是一樣。但由於創建內核空間進程,還需要設置一些額外選項。

內核版本
本文探討的是 2.6.27 版內核的 usermode-helper API。
表 1 展示的是 usermode-helper API 中一組關鍵的內核函數

表 1. usermode-helper API 中的核心函數

API 函數
描述

call_usermodehelper_setup 准備 user-land 調用的處理函數
call_usermodehelper_setkeys 設置 helper 的會話密鑰
call_usermodehelper_setcleanup 為 helper 設置一個清空函數
call_usermodehelper_stdinpipe 為 helper 創建 stdin 管道
call_usermodehelper_exec 調用 user-land
表 2 中還有一些簡化函數,它們封裝了的幾個內核函數(用一個調用代替多個調用)。這些簡化函數在很多情況下都很有用,因此盡可能使用他們。

表 2. usermode-helper API 的簡化

API 函數
描述

call_usermodehelper 調用 user-land
call_usermodehelper_pipe 使用 stdin 管道調用 user-land
call_usermodehelper_keys 使用會話密鑰調用 user-land
讓我們先瀏覽一遍這些核心函數,然後探索簡化函數提供了哪些功能。核心 API 使用了一個稱為subprocess_info 結構的處理函數引用進行操作。該結構(可在 ./kernel/kmod.c 中找到)集合了給定的 usermode-helper 實例的所有必需元素。該結構引用從 call_usermodehelper_setup 調用返回。該結構(以及後續調用)將會在 call_usermodehelper_setkeys(用於存儲憑證)、call_usermodehelper_setcleanup 以及 call_usermodehelper_stdinpipe 的調用中進一步配置。最後,一旦配置完成,就可通過調用 call_usermodehelper_exec 來調用配置好的用戶模式應用程序。

聲明
該方法提供了一個從內核調用用戶空間應用程序必需的函數。盡管這項功能有合理用途,還應仔細考慮是否需要其他實現。這是一個方法,但其他方法會更合適。
核心函數提供了最大程度的控制,其中 helper 函數在單個調用中完成了大部分工作。管道相關調用(call_usermodehelper_stdinpipe 和 helper 函數 call_usermodehelper_pipe)創建了一個相聯管道供 helper 使用。具體地說,創建了管道(內核中的文件結構)。用戶空間應用程序對管道可讀,內核對管道可寫。對於本文,核心轉儲只是使用 usermode-helper 管道的應用程序。在該應用程序(./fs/exec.c do_coremp())中,核心轉儲通過管道從內核空間寫到用戶空間。
這些函數與 sub_processinfo 以及 subprocess_info 結構的細節之間的關系如圖 1 所示。
圖 1. Usermode-helper API 關系

表 2 中的簡化函數內部執行 call_usermodehelper_setup 函數和 call_usermodehelper_exec 函數。表 2 中最後兩個調用分別調用的是 call_usermodehelper_setkeys 和 call_usermodehelper_stdinpipe。可以在 ./kernel/kmod.c 找到 call_usermodehelper_pipe 和 call_usermodehelper 的代碼,在 ./include/linux/kmod.h 中找到 call_usermodhelper_keys 的代碼。
為什麼要從內核調用用戶空間應用程序?
現在讓我們看一看 usermode-helper API 所使用的內核空間。表 3 提供的並不是專門的應用程序列表,而是一些有趣應用的示例。

表 3. 內核中的 usermode-helper API 應用程序

應用程序
源文件位置

內核模塊調用 ./kernel/kmod.c
電源管理 ./kernel/sys.c
控制組 ./kernel/cgroup.c
安全密匙生成 ./security/keys/request_key.c
內核事件交付 ./lib/kobject_uevent.c
最直接的 usermode-helper API 應用程序是從內核空間載入內核模塊。request_mole 函數封裝了 usermode-helper API 的功能並提供了簡單的介面。在一個常用的模塊中,內核指定一個設備或所需服務並調用 request_mole 來載入模塊。通過使用 usermode-helper API,模塊通過 modprobe 載入到內核(應用程序通過 request_mole 在用戶空間被調用)。
與模塊載入類似的應用程序是設備熱插拔(在運行時添加或刪除設備)。該特性是通過使用 usermode-helper API,調用用戶空間的 /sbin/hotplug 工具實現的。
關於 usermode-helper API 的一個有趣的應用程序(通過 request_mole) 是文本搜索 API(./lib/textsearch.c)。該應用程序在內核中提供了一個可配置的文本搜索基礎架構。該應用程序使用 usermode-helper API 將搜索演算法當作可載入模塊進行動態載入。在 2.6.30 內核版本中,支持三個演算法,包括 Boyer-Moore(./lib/ts_bm.c),簡單固定狀態機方法(./lib/ts_fsm.c),以及 Knuth-Morris-Pratt 演算法(./lib/ts_kmp.c)。
usermode-helper API 還支持 Linux 按照順序關閉系統。當需要系統關閉電源時,內核調用用戶空間的 /sbin/poweroff 命令來完成。其他應用程序如 表 3 所示,表中附有其源文件位置。
Usermode-helper API 內部
在 kernel/kmod.c 中可以找到 usermode-helper API 的源代碼 和 API(展示了主要的用作內核空間的內核模塊載入器)。這個實現使用 kernel_execve 完成臟工作(dirty work)。請注意 kernel_execve是在啟動時開啟 init 進程的函數,而且未使用 usermode-helper API。
usermode-helper API 的實現相當簡單直觀(見圖 2)。usermode-helper 從調用call_usermodehelper_exec 開始執行(它用於從預先配置好的 subprocess_info 結構中清除用戶空間應用程序)。該函數接受兩個參數:subprocess_info 結構引用和一個枚舉類型(不等待、等待進程中止及等待進程完全結束)。subprocess_info(或者是,該結構的 work_struct 元素)然後被壓入工作隊列(khelper_wq),然後隊列非同步執行調用。

圖 2. usermode-helper API 內部實現

當一個元素放入 khelper_wq 時,工作隊列的處理函數就被調用(本例中是__call_usermodehelper),它在 khelper 線程中運行。該函數從將 subprocess_info 結構出隊開始,此結構包含所有用戶空間調用所需信息。該路徑下一步取決於 wait 枚舉變數。如果請求者想要等整個進程結束,包含用戶空間調用(UMH_WAIT_PROC)或者是根本不等待(UMH_NO_WAIT),那麼會從 wait_for_helper 函數創建一個內核線程。否則,請求者只是等待用戶空間應用程序被調用(UMH_WAIT_EXEC),但並不完全。這種情況下,會為____call_usermodehelper() 創建一個內核線程。
在 wait_for_helper 線程中,會安裝一個 SIGCHLD 信號處理函數,並為 ____call_usermodehelper 創建另一個內核線程。但在 wait_for_helper 線程中,會調用 sys_wait4 來等待____call_usermodehelper 內核線程(由 SIGCHLD 信號指示)結束。然後線程執行必要的清除工作(為UMH_NO_WAIT 釋放結構空間或簡單地向 call_usermodehelper_exec() 回送一個完成報告)。
函數 ____call_usermodehelper 是實際讓應用程序在用戶空間啟動的地方。該函數首先解鎖所有信號並設置會話密鑰環。它還安裝了 stdin 管道(如果有請求)。進行了一些安裝以後,用戶空間應用程序通過 kernel_execve(來自 kernel/syscall.c)被調用,此文件包含此前定義的 path、argv 清單(包含用戶空間應用程序名稱)以及環境。當該進程完成後,此線程通過調用 do_exit() 而產生。
該進程還使用了 Linux 的 completion,它是像信號一樣的操作。當 call_usermodehelper_exec 函數被調用後,就會聲明 completion。當 subprocess_info 結構放入 khelper_wq 後,會調用wait_for_completion(使用 completion 變數作為參數)。請注意此變數會存儲到 subprocess_info 結構作為 complete 欄位。當子線程想要喚醒 call_usermodehelper_exec 函數,會調用內核方法complete,並判斷來自 subprocess_info 結構的 completion 變數。該調用會解鎖此函數使其能繼續。可以在 include/linux/completion.h 中找到 API 的實現。
應用程序示例
現在,讓我們看看 usermode-helper API 的簡單應用。首先看一下標准 API,然後學習如何使用 helper 函數使事情更簡單。
在該例中,首先開發了一個簡單的調用 API 的可載入內核模塊。清單 1 展示了樣板模塊功能,定義了模塊入口和出口函數。這兩個函數根據模塊的 modprobe(模塊入口函數)或 insmod(模塊入口函數),以及 rmmod(模塊出口函數)被調用。

清單 1. 模塊樣板函數

#include
#include
#include

MODULE_LICENSE( "GPL" );

static int __init mod_entry_func( void )
{
return umh_test();
}

static void __exit mod_exit_func( void )
{
return;
}

mole_init( mod_entry_func );
mole_exit( mod_exit_func );

usermode-helper API 的使用如 清單 2 所示,其中有詳細描述。函數開始是聲明所需變數和結構。以subprocess_info 結構開始,它包含所有的執行用戶空間調用的信息。該調用在調用call_usermodehelper_setup 時初始化。下一步,定義參數列表,使 argv 被調用。該列表與普通 C 程序中的 argv 列表類似,定義了應用程序(數組第一個元素)和參數列表。需要 NULL 終止符來提示列表末尾。請注意這里的 argc 變數(參數數量)是隱式的,因為 argv 列表的長度已經知道。該例中,應用程序名是 /usr/bin/logger,參數是 help!,然後是 NULL 終止符。下一個所需變數是環境數組(envp)。該數組是一組定義用戶空間應用程序執行環境的參數列表。本例中,定義一些常用的參數,這些參數用於定義 shell 並以 NULL 條目結束。

清單 2. 簡單的 usermode_helper API 測試

static int umh_test( void )
{
struct subprocess_info *sub_info;
char *argv[] = { "/usr/bin/logger", "help!", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };

sub_info = call_usermodehelper_setup( argv[0], argv, envp, GFP_ATOMIC );
if (sub_info == NULL) return -ENOMEM;

return call_usermodehelper_exec( sub_info, UMH_WAIT_PROC );
}

下一步,調用 call_usermodehelper_setup 來創建已初始化的 subprocess_info 結構。請注意使用了先前初始化的變數以及指示用於內存初始化的 GFP 屏蔽第四個參數。在安裝函數內部,調用了kzalloc(分配內核內存並清零)。該函數需要 GFP_ATOMIC 或 GFP_KERNEL 標志(前者定義調用不可以休眠,後者定義可以休眠)。快速測試新結構(即,非 NULL)後,使用 call_usermodehelper_exec 函數繼續調用。該函數使用 subprocess_info 結構以及定義是否等待的枚舉變數(在 「Usermode-helper API 內部」 一節中有描述)。全部完成! 模塊一旦載入,就可以在 /var/log/messages 文件中看到信息。
還可以通過 call_usermodehelper API 函數進一步簡化進程,它同時執行 call_usermodehelper_setup和 call_usermodehelper_exec 函數。如清單 3 所示,它不僅刪除函數,還消除了調用者管理subprocess_info 結構的必要性。

清單 3. 更簡單的 usermode-helper API 測試

static int umh_test( void )
{
char *argv[] = { "/usr/bin/logger", "help!", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };

return call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC );
}

請注意在清單 3 中,有著同樣的安裝並調用(例如初始化 argv 和 envp 數組)的需求。此處惟一的區別是 helper 函數執行 setup 和 exec 函數。

閱讀全文

與數據怎麼傳到內核相關的資料

熱點內容
javalong怎麼寫 瀏覽:937
orc格式文件轉成txt 瀏覽:352
有哪些文件可以刪除可以釋放 瀏覽:738
黃金皓月服武器升級 瀏覽:576
不要u盤能恢復u盤內的文件么 瀏覽:882
華為支持什麼播放文件 瀏覽:883
app什麼時候做壓力測試 瀏覽:361
華為交換機配置文件導出 瀏覽:730
智能雲網路攝像機怎麼連接 瀏覽:249
什麼日語app推薦 瀏覽:797
神州行怎麼升級全球通 瀏覽:459
captureone聯機文件名 瀏覽:173
美國有什麼教育app 瀏覽:272
qq群如何設置群通知 瀏覽:364
u盤關閉了所有文件還是無法彈出 瀏覽:21
蘋果專用win7ios怎麼裝 瀏覽:970
什麼app查詢魔獸角色 瀏覽:816
蘋果葫蘆俠怎麼用 瀏覽:945
怎麼恢復微信的圖片和文件 瀏覽:206
powerpoint可以保存的文件格式有 瀏覽:325

友情鏈接