access驱动程序_Linux驱动程序学习二 (续) scull 源码在内核5.4.0上的编译调试
《LINUX設備驅動程序》第三章提供了源碼scull,但是由于我用的是5.4.0內核,書中的是2.6.10內核,內核發生了很大的變化,因此編譯scull源碼花費了不少時間,下面是編譯調試記錄。(這個編譯調試記錄應該是目前網絡上適應內核版本最高的,所以也希望給近期加入《LINUX設備驅動程序》學習的小白們一個參考)。
一、main.c
1、make出現以下兩個錯誤:
/home/valian/scull/main.c:17:26: fatal error: linux/config.h: 沒有那個文件或目錄 /home/valian/scull/main.c:32:46: fatal error: asm/system.h: 沒有那個文件或目錄直接在main.c中刪除這兩個頭文件.在新的內核里棄用了這兩個.
2、copy_to_user copy_from_user
/home/valian/scull/main.c:324:6: error: implicit declaration of function ‘copy_to_user’ [-Werror=implicit-function-declaration]if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) {^ /home/valian/scull/main.c: In function ‘scull_write’: /home/valian/scull/main.c:373:6: error: implicit declaration of function ‘copy_from_user’ [-Werror=implicit-function-declaration]if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) {新內核修改了這兩個函數名稱,更改如下:
copy_to_user()改為raw_copy_to_user(); copy_from_user()改為raw_copy_from_user();3、access_ok
/home/valian/scull/main.c:414:68: error: macro "access_ok" passed 3 arguments, but takes just 2err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));^ /home/valian/scull/main.c:414:10: error: ‘access_ok’ undeclared (first use in this function)err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));^ /home/valian/scull/main.c:414:10: note: each undeclared identifier is reported only once for each function it appears in /home/valian/scull/main.c:416:68: error: macro "access_ok" passed 3 arguments, but takes just 2err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));從錯誤提示看,大概是新內核的access_ok的參數為2個,但是原來內核為3個。
通過以下指令在源碼中查找access的出出處:
find /lib/modules/5.4.0/build/include/linux -type f -exec grep "access_ok" {} ; -print得到以下提示:
從提示看到新的access_ok的參數為(ptr,len),于是修改代碼如下:
err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); 改為err = !access_ok((void __user *)arg, _IOC_SIZE(cmd));4 、.ioctl (可參考CSDN-專業IT技術社區-登錄)
make -C /lib/modules/5.4.0/build M=/home/valian/scull LDDINC=/home/valian/scull/../include modules make[1]: Entering directory '/usr/src/linux-5.4'CC [M] /home/valian/scull/main.o /home/valian/scull/main.c:558:2: error: unknown field ‘ioctl’ specified in initializer.ioctl = scull_ioctl,^ /home/valian/scull/main.c:558:14: error: positional initialization of field in ‘struct’ declared with ‘designated_init’ attribute [-Werror=designated-init].ioctl = scull_ioctl,ioctl是未知域,同樣檢索ioctl
find /lib/modules/5.4.0/build/include/linux -type f -exec grep "ioctl" {} ; -print得到(在/lib/modules/5.4.0/build/include/linux/fs.h)
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); // 5.4.0int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long); // 2.6.10 網絡上查找對比發現.ioctl變為.unlocked_ioctl,函數指針的原型也變了,少了struct inode * 這個指針參數,而且函數類型也由int變為long。修改如下;
.ioctl = scull_ioctl改為 .unlocked_ioctl = scull_ioctl;函數scull_ioctl改為(main.c 和scull.h)
long scull_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); // int 改為long,struct inode* 刪除5、init_MUTEX
/home/valian/scull/main.c: In function ‘scull_init_module’: /home/valian/scull/main.c:653:3: error: implicit declaration of function ‘init_MUTEX’ [-Werror=implicit-function-declaration]init_MUTEX(&scull_devices[i].sem);
通過以下命令
查找,結果沒有找到,應該是這個函數名稱被棄用。在網絡中找到解決方法init_MUTEX(&sem)被sema_init(&sem,1)替換了。
init_MUTEX(&scull_devices[i].sem); 改為sema_init((&scull_devices[i].sem),1);sema_init的定義可參考/lib/modules/5.4.0/build/include/linux/semaphore.h
static inline void sema_init(struct semaphore *sem, int val)pipe.c
1:init_MUTEX
同main.c,init_MUTEX改為sema_init;
//init_MUTEX(&scull_p_devices[i].sem); sema_init((&scull_p_devices[i].sem),1);2、signal_pending
/home/valian/scull/pipe.c: In function ‘scull_getwritespace’: /home/valian/scull/pipe.c:172:7: error: implicit declaration of function ‘signal_pending’ [-Werror=implicit-function-declaration]if (signal_pending(current))從錯誤代碼查找關鍵詞signal_pending的定義:
查找命令
find /lib/modules/5.4.0/build/include/linux -name '*.h' | xargs grep -w "signal_pending"得到如下信息:
valian@valian-TM1703:~/scull$ find /lib/modules/5.4.0/build/include/linux -name '*.h' | xargs grep -w "signal_pending" /lib/modules/5.4.0/build/include/linux/sched/signal.h:static inline int signal_pending(struct task_struct *p)從signal_pending定義看函數參數沒有改變,但是沒有包含/linux/sched/signal.h頭文件。
加上頭文件:
#include <linux/sched/signal.h>access.c
1、.ioctl 錯誤,參考上面的改正方法。
2、init_MUTEX
init_MUTEX(&(lptr->device.sem));改為sema_init(&(lptr->device.sem),1);3、SPIN_LOCK_UNLOCKED
/home/valian/scull/access.c:98:34: error: ‘SPIN_LOCK_UNLOCKED’ undeclared here (not in a function)static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;從提示看沒有定義。查找關鍵詞
find /lib/modules/5.4.0/build/include/linux -type f -exec grep "SPIN_LOCK_UNLOCKED" {} ; -print得到以下信息
#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x) /lib/modules/5.4.0/build/include/linux/spinlock_types.h根據以上信息與源碼中“static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;”對比發現,宏定義 DEFINESPINLOCK(x) 代替了源碼中spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED。因此按以下修改即可。
//static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED; //static spinlock_t scull_c_lock = SPIN_LOCK_UNLOCKED; //static spinlock_t scull_w_lock = SPIN_LOCK_UNLOCKED;static DEFINE_SPINLOCK(scull_u_lock) ;static DEFINE_SPINLOCK(scull_c_lock) ;static DEFINE_SPINLOCK(scull_w_lock) ;4、uid euid
/home/valian/scull/access.c:108:29: error: ‘struct task_struct’ has no member named ‘uid’(scull_u_owner != current->uid) && /* allow user */^ /home/valian/scull/access.c:109:29: error: ‘struct task_struct’ has no member named ‘euid’(scull_u_owner != current->euid) && /* allow whoever did su */查找關鍵詞struct task_struct
find /lib/modules/5.4.0/build/include/linux -type f -exec grep "struct task_struct" {} ; -print眾多信息中找到定義在/lib/modules/5.4.0/build/include/linux/sched.h
struct task_struct { ........... } /lib/modules/5.4.0/build/include/linux/sched.h但是查找sched.h中struct task_struct的定義,沒有找到“uid,euid”。網絡搜尋得知新的struct taskstruct 定義有變化,uid和euid在cred結構體中(在頭文件/lib/modules/5.4.0/build/include/linux/cred.h中)。如下圖找到uid,euid,其類型為kuid_t。
在</lib/modules/5.4.0/build/include/linux/uidgid.h>中查到kuid_t為結構體類型,定義如下:
typedef struct {uid_t val; } kuid_t;access.c中scull_u_owner的類型為static uid_t scull_u_owner。因此需要修改代碼如下:
(current->uid改為current->cred->uid,current->euid改為current->cred->euid)
//scull_w_owner == current->uid || //scull_w_owner == current->euid || 改為 scull_w_owner == current->cred->uid.val || scull_w_owner == current->cred->euid.val ||// (scull_u_owner != current->uid) && /* allow user */ // (scull_u_owner != current->euid) && /* allow whoever did su */ 改為(scull_u_owner != current->cred->uid.val) && /* allow user */(scull_u_owner != current->cred->euid.val) && /* allow whoever did su */過程中出現以下錯誤可參考[PATCH 0/5] PMFS: Rebase to Linux 3.9
/home/valian/SLAM/linux/scull/access.c:115:19: error: invalid operands to binary != (have ‘uid_t {aka unsigned int}’ and ‘kuid_t {aka const struct <anonymous>}’)(scull_u_owner != current->cred->uid) && /* allow user */^ /home/valian/SLAM/linux/scull/access.c:116:19: error: invalid operands to binary != (have ‘uid_t {aka unsigned int}’ and ‘kuid_t {aka const struct <anonymous>}’)(scull_u_owner != current->cred->euid) && /* allow whoever did su */5、struct signal_struct
/home/valian/SLAM/linux/scull/access.c:283:22: error: dereferencing pointer to incomplete type ‘struct signal_struct’if (!current->signal->tty) {錯誤提示可能是沒有聲明對應結構體定義的頭文件。查找struct signal_struct的定義:
find /lib/modules/5.4.0/build/include/linux -type f -exec grep "struct signal_struct" {} ; -print得到以下結果,在/lib/modules/5.4.0/build/include/linux/sched/signal.h。
struct signal_struct { static inline void signal_set_stop_flags(struct signal_struct *sig, static inline int signal_group_exit(const struct signal_struct *sig) /lib/modules/5.4.0/build/include/linux/sched/signal.h在assess.c中加上頭文件;
#include <linux/sched/signal.h>至此scull源碼在內核linux5.4.0上編譯通過。
總結
以上是生活随笔為你收集整理的access驱动程序_Linux驱动程序学习二 (续) scull 源码在内核5.4.0上的编译调试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言整数反转用while函数,7.整数
- 下一篇: linux 其他常用命令