日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项

發布時間:2024/9/21 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用戶地址檢測 簡單模塊調試 以及一些雜項

檢測用戶空間地址的有效性

上一節中提到在read write時候要檢測用戶空間傳遞的參數地址是否是有效地址,有的內核函數會自行檢測,但是在調用輕量級的內核函數時候,就可能不去檢測用戶空間的地址是否有效,如果此時用戶無傳遞一個無效地址,而內核函數去操作了它,這時棘手的問題出現了,輕則內核oops 關機重啟就OK了,在特別嚴重的情況下,可能你的系統就崩潰了(我又遇到過),所以,我們在驅動程序中操作用戶空間地址時候要小心加小心。如果電腦配置可以就在虛擬機中玩, 或者在開發板上試,當然這邊的測試代碼我都有試過,不至于讓你系統崩潰的。
如何檢測呢?
調用一個access_ok函數去檢測
[cpp]?view plaincopy
  • #define?access_ok(type,addr,size)??
  • type 標識讀寫操作VERIFY_READ表示地址可讀,VERIFY_WRITE表示地址可寫
    addr 用戶傳入的地址
    size 讀寫的長度
    此代碼在有內存管理的芯片與無內存管理之間有區別

    我們 看一段內核代碼 (path : arch/arm/include/asm/uaccess.h)

    [cpp]?view plaincopy
  • #define?access_ok(type,addr,size)???(__range_ok(addr,size)?==?0)??
  • #ifdef?CONFIG_MMU??
  • ...??
  • #define?__range_ok(addr,size)?({?\??
  • ????unsigned?long?flag,?roksum;?\??
  • ????__chk_user_ptr(addr);???\??
  • ????__asm__("adds?%1,?%2,?%3;?sbcccs?%1,?%1,?%0;?movcc?%0,?#0"?\??
  • ????????:?"=&r"?(flag),?"=&r"?(roksum)?\??
  • ????????:?"r"?(addr),?"Ir"?(size),?"0"?(current_thread_info()->addr_limit)?\??
  • ????????:?"cc");?\??
  • ????flag;?})??
  • #else??
  • ...??
  • #define?__range_ok(addr,size)<span?style="white-space:pre">???</span>(0)??

  • 即在有內存管理并配置了內存管理的芯片內調用次函數會執行檢測操作,而在沒有配置內存管理的芯片中此函數總是返回真,而做驅動的不應該做這些假設,所以傳入的參數在有必要的情況下還是要自行檢測再看看copy_to_user函數 [cpp]?view plaincopy
  • static?inline?unsigned?long?__must_check?copy_to_user(void?__user?*to,?const?void?*from,?unsigned?long?n)??
  • {??
  • ????if?(access_ok(VERIFY_WRITE,?to,?n))??
  • ????????n?=?__copy_to_user(to,?from,?n);??
  • ????return?n;??
  • }??
  • 可以看到他在函數內部做了這種檢測

    而當我們調用

    [cpp]?view plaincopy
  • __copy_to_user??
  • __copy_from_user??
  • get_user??
  • __get_user??
  • put_user??
  • __put_user??
  • 時都需要檢測用戶地址是否可用

    簡單模塊調試技術

    為什么要加簡單呢? 因為這邊只介紹了用打印來調試程序。
    看了LDD3上邊介紹的很多調試技術 ?查詢調試 觀察調試之類
    我覺得 打印調試來的最簡單最直接 雖然他有一些限制
    1、大量的使用printk會使系統變慢
    2、沒次打印一行都會引起磁盤操作
    ...
    在printk中有7中 消息的選項 表示著不同的消息等級
    KERN_GMERG<0>用于緊急消息, 常常是那些崩潰前的消息.
    KERN_ALERT<1>需要立刻動作的情形.
    KERN_CRIT<2>嚴重情況, 常常與嚴重的硬件或者軟件失效有關.
    KERN_ERR<3>用來報告錯誤情況; 設備驅動常常使用 來報告硬件故障.
    KERN_WARNING<4>有問題的情況的警告, 這些情況自己不會引起系統的嚴重問題
    KERN_NOTICE<5>正常情況, 但是仍然值得注意. 在這個級別一些安全相關的情況會報告.
    KERN_INFO<6>信息型消息. 比如 :打印它們發現的硬件的信息.
    KERN_DEBUG<7>用作調試消息.
    內核中定義了 DEFAULT_MESSAGE_LOGLEVEL (在printk.c中)默認數值小于它的消息類型才會被答應到終端,我們可以把他設置為8則所有的信息都會被終端打印出來。
    在系統中我們 可以使用? echo 8 >?/proc/sys/kernel/printk ?來調整這個數值(要root權限) 使信息全部被打印出來。
    當然我們 也可以通過dmesg來查看所有的打印信息 (有一點不適用,就是當系統出現oops的時候 就不行了 因為你已經死機了 也就輸不了這個命令 就看不到打印信息了)
    [cpp]?view plaincopy
  • #if?SIMPLE_DEBUG??
  • #define?D(...)?printk(KERN_DEBUG?__VA_ARGS__)??
  • #define?WAR(...)?printk(KERN_WARNING?__VA_ARGS__)??
  • #else??
  • #define?D(...)?((void)0)??
  • #define?WAR(...)?((void)0)??
  • #endif??
  • 在需要調試的時候,我們去定義SIMPLE_DEBUG這個宏,在驅動代碼測試都OK可以發行時候,去掉這個定義。
    在需要打印的地方我們就使用
    [cpp]?view plaincopy
  • D(“print?the?log?int?func:%s?line:%d”,?__func__?,__LINE__);??
  • 當然要修改成有意義的debug信息

    打印當前進程信息
    內核模塊不像應用程序一樣順序執行,只用應用進程調用到想關聯的函數才會到內核模塊中call這個接口,那可不可以 打印調用進程的信息呢?
    答案是肯定的,linux中定義了 current 這個變量(<linux/sched.h>)current指向了當前的進程,他是一個 task_struct 類型
    其中有兩個重要的成員
    comm 表示了 當前的命令名名
    pid 表示了當前進程號
    [cpp]?view plaincopy
  • D("[process:?%s]?[pid:?%d]?xxx\n"?,?current->comm,?current->pid);??

  • 內核的container_of函數
    在寫字符設備驅動時候我們都會去自定義一個結構,其中包含了cdev結構
    [cpp]?view plaincopy
  • struct?simple_dev{??
  • ????char?*data;??
  • ????loff_t?count;??
  • ????struct?cdev?cdev;??
  • ????struct?semaphore?semp;??
  • };??
  • 在open方法中除了上一節看到的那樣用一個次設備好來獲取結構(有時候會出錯 如果我們次設備號不是從0開始分配)
    所以需要尋求一種安全的方法
    container_of為我們提供了這么一個很好的接口
    [cpp]?view plaincopy
  • /**?
  • ?*?container_of?-?cast?a?member?of?a?structure?out?to?the?containing?structure?
  • ?*?@ptr:????the?pointer?to?the?member.?
  • ?*?@type:???the?type?of?the?container?struct?this?is?embedded?in.?
  • ?*?@member:?the?name?of?the?member?within?the?struct.?
  • ?*?
  • ?*/??
  • #define?container_of(ptr,?type,?member)???
  • 再解釋一下?
    ptr是指結構體一個成員的地址
    type 指要獲得的結構體
    member ptr指向的成員在結構體中的名字 [cpp]?view plaincopy
  • /*container_of(pointer,?container_type,?container_fild)?
  • ?we?can?get?the?container_type?with?one?number?in?the?container?
  • ?by?this?function.?container_fild?is?the?one?of?the?number?in?the?
  • ?container_type?,?pointer?point?to?confain_field?type??
  • */??
  • temp_dev?=?container_of(inodp->i_cdev,?struct?simple_dev,?cdev);??
  • 上邊的E文 是我寫的 poor English

    container_of 的實現基本原理是這樣的:
    知道了結構體中某個成員的地址, ?又可以求的該成員在改結構體中得偏移,拿成員的地址減去這個偏移,就得到了整個結構的地址,太佩服寫內核的人了
    [cpp]?view plaincopy
  • #define?container_of(ptr,?type,?member)?({??????????\??
  • ????const?typeof(((type?*)0)->member)?*?__mptr?=?(ptr);??\??
  • ????(type?*)((char?*)__mptr?-?offsetof(type,?member));?})??
  • 總結

    以上是生活随笔為你收集整理的Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 永久免费在线播放 | 一级在线| 天天宗合 | 久久久久久久久久久99 | 自拍偷拍第二页 | 免费欧美黄色 | 九九精品在线观看视频 | 99热国产 | 亚洲无人禁区 | 久草五月天 | 精品人妻一区二区三区久久 | 亚洲熟女乱色一区二区三区久久久 | 亚洲精品二区 | 粉嫩av一区二区夜夜嗨 | 黄瓜视频在线观看 | 91丝袜在线| 在线欧美一区 | 日本免费中文字幕 | 欧美性极品xxxx做受 | 视频一区三区 | 久久av免费 | 国产又爽又黄无码无遮挡在线观看 | 奇米影视777在线观看 | 国产婷婷色一区二区三区在线 | 国产欧美日韩另类 | 国产亚洲色婷婷久久99精品 | 亚洲情侣av | www视频在线免费观看 | 成人黄色av网址 | 日韩免费a| 黄色一节片 | 国产欧美一区二区三区精华液好吗 | 日韩人妻精品一区二区三区视频 | 五月婷婷丁香在线 | 久久久99国产精品免费 | 波多野结衣导航 | 亚洲六月婷婷 | 国产欧美综合一区 | 体内射精一区二区 | 免费成人av | 91网站在线观看视频 | 久草国产在线 | 殴美一级视频 | 一级免费毛片 | 国产一级大片在线观看 | 国产色无码精品视频 | 91精品视频一区二区三区 | 最色网站| 免费看的黄色网 | 欧美大片视频在线观看 | 青青青草视频在线 | 真实偷拍激情啪啪对白 | 中文字幕av影视 | 日韩一级成人 | 国产精品操| 午夜福利电影 | 欧美美女性生活 | 97精品国产97久久久久久春色 | 日韩性网站 | 日本高清视频在线播放 | 日本乱偷中文字幕 | 调教亲女小嫩苞h文小说 | 99热精品在线播放 | 久久久国产精品 | 精品国产一区二区三区久久久蜜月 | 国产高潮视频在线观看 | 午夜天堂av| 做爰无遮挡三级 | 森林影视官网在线观看 | 精品动漫一区二区三区在线观看 | 国产成人av一区二区三区不卡 | 国产一级在线免费观看 | 狠狠躁日日躁夜夜躁av | 亚洲a人| 三级国产网站 | 成人av第一页 | 亚洲乱论 | 久久精品导航 | 深夜久久久| 不卡的一区二区 | 欧美日韩国产91 | 清清草视频| 521av在线 | 欧美高清性 | 欧美xxxx精品 | 亚洲自拍偷拍网 | 香蕉视频在线观看www | 四川黄色一级片 | 永久免费精品视频 | 99视频精品在线 | a级片在线观看视频 | 国产综合网站 | 国产成人一区二区三区小说 | 国产三级久久 | 精品视频在线观看一区二区 | 黑人多p混交群体交乱 | 日本精品视频在线播放 | 国产精品偷乱一区二区三区 | 亚洲无线观看 |