4.一樣的精靈,不一樣的api(2)
關於核心空間,我只想說,所有的驅動程式都是執行在核心空間的,核心空間雖然很大,但總是有限的。而在這有限的空間中,其最後乙個page是專門保留的,也就是說,一般人不可能用到核心空間最後乙個page的指標。
換句話說,你在寫裝置驅動程式的過程中,涉及的任何乙個指標,必然有三種情況:一種是有效指標,一種是null(空指標),還有一種是錯誤指標,或者說無效指標。而所謂的錯誤指標就是指其已經到達了最後乙個page。比如對於32bit的系統來說,核心空間最高位址0xffffffff,那麼最後乙個page就是指的0xfffff000~0xffffffff(假設4kb乙個page)。這段位址是被保留的,一般人不得越雷池半步,如果你發現你的乙個指標指向這個範圍中的某個位址,那麼恭喜你,你的**肯定出錯了。
那麼你是不是很好奇,好端端的核心空間幹嘛要留出最後乙個page?這不是明明自己有1000塊錢,非得對自己說只能用900塊。實在不好意思,你說錯了,這裡不僅不是浪費乙個page,反而是充分利用資源,把乙個東西當兩個東西來用。
看見16行那個"max_errno"了嗎?乙個巨集,定義為4095,max_errno就是最大錯誤號,linux核心中,出錯有多種可能,因為有許許多多種錯誤。關於linux核心中的錯誤,我們看include/asm-generic/errno-base.h檔案:
#define eperm 1 /* operation not permitted */最常見的幾個是-ebusy、-einval、-enodev、-epipe、-eagain、-enomem,我相信只要你使用過linux就有可能見過這幾個錯誤,因為它們確實經常出現。#define enoent 2 /* no such file or directory */
#define esrch 3 /* no such process */
#define eintr 4 /* interrupted system call */
#define eio 5 /* i/o error */
#define enxio 6 /* no such device or address */
#define e2big 7 /* argument list too long */
#define enoexec 8 /* exec format error */
#define ebadf 9 /* bad file number */
#define echild 10 /* no child processes */
#define eagain 11 /* try again */
#define enomem 12 /* out of memory */
#define eacces 13 /* permission denied */
#define efault 14 /* bad address */
#define enotblk 15 /* block device required */
#define ebusy 16 /* device or resource busy */
#define eexist 17 /* file exists */
#define exdev 18 /* cross-device link */
#define enodev 19 /* no such device */
#define enotdir 20 /* not a directory */
#define eisdir 21 /* is a directory */
#define einval 22 /* invalid argument */
#define enfile 23 /* file table overflow */
#define emfile 24 /* too many open files */
#define enotty 25 /* not a typewriter */
#define etxtbsy 26 /* text file busy */
#define efbig 27 /* file too large */
#define enospc 28 /* no space left on device */
#define espipe 29 /* illegal seek */
#define erofs 30 /* read-only file system */
#define emlink 31 /* too many links */
#define epipe 32 /* broken pipe */
#define edom 33 /* math argument out of domain of func */
#define erange 34 /* math result not representable */
這些是每個體系結構中都有的,另外各個體系結構也都定義了自己的一些錯誤**。這些東西當然也都是巨集,實際上對應的是一些數字,這些數字就叫做錯誤號。而對於linux核心來說,不管任何體系結構,錯誤號最多不會超過4095,而4095又正好是比4kb小1,即4096-1。而我們知道乙個page可能是4kb,也可能是更多,比如8kb,但至少它也是4kb,所以留出乙個page出來就可以讓我們把核心空間的指標來記錄錯誤了。
什麼意思呢?比如我們這裡的is_err(),它就是判斷kthread_run()返回的指標是否有錯,如果指標並不是指向最後乙個page,那麼沒有問題,申請成功了,如果指標指向了最後乙個page,那麼說明實際上這不是乙個有效的指標,這個指標裡儲存的實際上是一種錯誤**。而通常很常用的方法就是先用is_err()來判斷是否是錯誤,然後如果是,那麼就呼叫ptr_err()來返回這個錯誤**。只不過這裡沒有呼叫ptr_err()而已,因為起決定作用的還是is_err(),而ptr_err()只是返回錯誤**,也就是提供乙個資訊給呼叫者,如果你只需要知道是否出錯,而不在乎因為什麼而出錯,那你當然不用呼叫ptr_err()了。當然,這裡如果出錯了的話,最終usb_deregister()會被呼叫,並且usb_hub_init()會返回-1。
4 一樣的精靈,不一樣的API(1)
4 一樣的精靈,不一樣的api 1 usb register 這個函式是用來向usb核心層,即usb core,註冊乙個usb裝置驅動的,而這裡我們註冊的是hub的驅動程式所對應的struct usb driver結構體變數。定義於drivers usb core hub.c中 2841 stati...
不一樣又不一樣的 木板接水
空地上豎立著n個從左到右排列的木板,它們可以把水擋住,但溢位最邊上木板的水將會流到空地上。已知木板間距都是單位1,現給定每個木板的高度,請求出總共能接住的水量?說明一點,這裡只考慮間距 寬度 和高度,不考慮第三個維度,因此水量是平方單位。木板高度分別是2,1,3,那麼我們可以接住2 2 4平方單位的...
一樣的月亮,不一樣的心情
轉眼間,又是一年的中秋佳節,這都是乙個懷鄉思親的節日,自從讀書和工作後,就很難有機會和父母 兄弟姐妹一起過了,在這個只掛燈籠但毫無節日氛圍的城市裡,你可以看到許許多多偽裝的慶祝和喜悅,一樣的月亮一樣的月光一樣的月餅,但心情卻是千差萬別,各顯千秋,最可憐的就是小朋友們了,他們失去了各種自然的 純樸的 ...