Linux驅動開發盲點筆記1

1. vim中在找到搜索目標後,使用n與N進行定位查找

2. vim中使用gg到最好第一行,使用xxxG到某一行,否則G直接到最後一行;

3. ln -s 產生的鏈接文件最終指向的目標文件src 新產生的當前軟鏈接文件dst。
ln -s project(磁盤上實際存在的文件或者目錄) a.lnk
ln -s src dst(新產生的文件dst,dst鏈接到src)
symlink功能類似

4 tar -czvf 最終生產的tar打包好的文件 待打包的文件或者文件夾
tar czvf a.tar.bz  a


5. 移植dts的關鍵點是,待編譯的dts文件均需要放置於/arch/arm/boot/dts下面。make時會默認在這裏尋找dts編譯文件入口。然後編譯時以同名的dtb來執行make編譯才能被makefile解析爲目標,再去查找同名的dts由DTC來生產dtb文件。而dtb就是最終根據dts編譯出來的二進制文件,位於arch/arm/boot下

6.在linux內核中斷編程中需要注意:
中斷上下文中不能出現調度休眠的情況。即不能使用互斥,信號量PV操作會引起休眠等方式。
中斷一般需要處理的自旋鎖保護臨界資源時也需要較短時間的。
一般原子上下文中不能出現睡眠。
msleep/wait_event_interrupt等函數都是調度休眠延遲的,故不能出現在中斷上下文中。

7. list_for_each與list_for_each_safe的區別
因此之遍歷鏈表不刪除結點時,可以使用list_for_each(),而當要刪除結點操作時,則要使用list_for_each_safe()。

8. 模塊入口函數編碼注意點
module init/exit函數是無參函數,且應當是int類型的返回值

9. linux編譯模塊時的版本號
使用modinfo可查看編譯出來的ko文件對應的內核版本號
使用uname或者 cat /proc/version 可在目標系統上查看內核版本號。
可查看kernel編譯過程生成的文件: include/generated/utsrelease.h ,確定編譯出來的內核的版本號。

10 df顯示磁盤分區信息如df -h, du -sh來顯示當前目錄下的各文件與目錄的大小信息

11 declare -f xxx用於輸出當前shell支持的函數輸出

12 find -name *xxx 查找文件

13 grep "xxx" -r ./*

14  cat /proc/version 查看Ubuntu版本號,  lsb_release -a
cat /etc/issue


15 makefile中的=與:=
前者在賦值時會查看賦值變量的全局性
後者在賦值時,只看被賦值變量再前面是否已經被定義過。

16 &是進程在後臺運行不佔據終端

17 linux設備驅動阻塞與非阻塞方式,阻塞與非阻塞是針對數據的讀寫,即資源的獲取而言的,當無資源時,阻塞會調度進程休眠,而非阻塞則立刻返回
poll函數本質只是來查詢當前設備是否已經可讀或者可寫POLLIN和POLLOUT。
利用select和poll可以去確保對設備的非阻塞操作(select和poll本身就一種阻塞操作,阻塞完成後可表明讀寫資源是ok的,從而確保資源是可讀寫操作的)
而所謂的阻塞操作,是對設備讀寫時直接進行進行進程的調度與休眠,直到數據可讀或者可寫,纔回返回。

在自己定義的fops poll接口中需要實現poll_wait函數,該函數只是將當前需要進程poll_table加入到一個等待隊列頭中去,並不會產生休眠,但真正的休眠調度需要在do_sys_poll中由poll_schedule_timeout來休眠調度。
在等待隊列頭被wake_up喚醒後,會繼續執行一次poll接口調用,再次將自己加入到wait queue中,此後一般是可以POLLIN或者POLLOUT,從而退出do_sys_poll的調用,返回查詢結果給用戶層。


static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
    if (p && p->_qproc && wait_address)
        p->_qproc(filp, wait_address, p);//__pollwait
}

static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
                poll_table *p)
{
    struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
    struct poll_table_entry *entry = poll_get_entry(pwq);
    if (!entry)
        return;
    get_file(filp);
    entry->filp = filp;
    entry->wait_address = wait_address;
    entry->key = p->_key;
    init_waitqueue_func_entry(&entry->wait, pollwake);
    entry->wait.private = pwq;
    add_wait_queue(wait_address, &entry->wait);//將poll進程的wait加入到等待隊列頭
}

18 linux中斷嵌套基本原理
1)linux響應中斷後,將響應程序分成兩部分:頂部和底部;
2)在執行完頂部後,就打開中斷(清掉了相關的中斷標誌);底部由系統調度運行,底部運行時,允許中斷;
3)如果在驅動中,申請中斷request_iqr()時,使用了參數IRQF_DISABLED,則在調用中斷處理函數時,屏蔽所有中斷,從而使中斷得到快速執行。
4)綜合2)和3),可知LINUX允許中斷嵌套。

19 devm_kzalloc可以更好的管理設備的相關資源

20 dts中的lable
瞭解了基本的device tree的結構後,我們總要把這些結構體現在device tree source code上來。在linux kernel中,擴展名是dts的文件就是描述硬件信息的device tree source file,在dts文件中,一個node被定義成:

[label:] node-name[@unit-address] {
  [properties definitions]
  [child nodes]
}

“[]”表示option,因此可以定義一個只有node name的空節點。label方便在dts文件中引用,具體後面會描述。child node的格式和node是完全一樣的,因此,一個dts文件中就是若干嵌套組成的node,property以及child note、child note property描述。

21 dts中include dtsi的處理過程
嘗試了下,貌似label的引用和include的位置無關,應該是提前於加載類似於makefile的include處理,而不是C編譯的處理

22 push-pull open_drain
開漏加上拉,在高電平的時候能提供的電流很小,還有一個問題就是電平的翻轉速度比較慢,總之就是驅動能力不行。但是開漏的方式可以借線與邏輯實現準雙向IO,這一點是推輓做不到的。

浮空,顧名思義就是懸浮在空中,上面用繩子一拉就上去,下面用繩子一拉就沉下去了。
上拉,下拉的設置主要還是看你外接的驅動電路的具體情況配置的。
開漏,就等於輸出口接了個NPN三極管,並且只接了e,b. c極是開路的,你可以直接接一個電阻到3.3V,也可以接一個電阻到5v,這樣在輸出1的時候,就有5V的電壓,也可以輸出3.3V的電壓了,而不接電阻上拉,這個輸出高是不能實現的。
推輓,就是有推有拉,任何時候IO口的點平都是確定的,不需要外接上拉或者下拉電阻


23 dts中的&用法
在root node中如果有一個A:A{}子節點,然後在這個dts中的根節點/{}外面又增加了
&A{
xxxxxx
其他node信息
}
這種方式是不是就是隻是給A節點增加信息,本質就是隻有一個A node,只是分開來描述而已

dts設備節點定義名字定義格式:
[label:] node-name[@unit-address]
如cif:cif@1,其對應的device node name還是cif,[]表示可選擇的存在。


23 ffs函數取最低有效的位置,並置爲1,其餘位清零


24 vmalloc_user
每次vmalloc之後,內核會創建一個vm_struct,用以映射分配到的不連續的內存區域
vma是將物理內存映射到進程的虛擬地址空間而vm_struct是將物理內存映射到內核的線性地址空間
mm_struct是管理整個進程的虛擬地址空間,一般以current->mm來獲取。
vmalloc_user的空間映射回用戶remap_vmalloc_range

25 linux驅動自動加載順序,不同級別按照init的level,同一等級按照makefile中定義的編譯順序來決定,先編譯的模塊則先會被鏈接到同等級中的區域塊
Makefile中定義模塊a和b:
obj-y=a;
obj-y=b;
則同一等級的a、b模塊,a先會被加載,b後加載


26 dts例子
/{
  soc0{
  compatible = "my, soc0";
  node1{
  compatible = "my, node1";                    
  node1_1{
  compatible = "my, node1_1";
  node1_1_1{
  compatible = "my, node1_1_1";
}
}
}
  node2{ }
}
  soc1{ compatible = "my, soc1"; }
}

27 shell腳本函數變量
變量含義
$0當前腳本的文件名
$n傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
$#傳遞給腳本或函數的參數個數。
$*傳遞給腳本或函數的所有參數。
$@傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同,下面將會講到。
$?上個命令的退出狀態,或函數的返回值。
$$當前Shell進程ID。對於 Shell 腳本,就是這些腳本所在的進程ID。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章