1.spinlock原理
為了解決這個spinlock的不公平問題,linux 2.6.25內核以后,spinlock采用了一種"FIFO ticket-based"算法的spinlock機制,可以很好的實現先來先搶占的思想。具體的做法如下:
(1)、spinlock的核心字段有owner和next,在初始時,owner=next=0
(2)、當第一個進程搶占spinlock時,會在進程函數本地保存下next的值,也就是next=0,并將spinlock的next字段加1;
(3)、當獲取spinlock的進程的本地next和spinlock的owner相等時,該進程就獲取到spinlock;
(4)、由于第一個進程本地的next=0,并且spinlock的owner為0,所以第一個CPU獲取到spinlock;
(5)、接著當第二個進程搶占spinlock,此時spinlock的next值為1,保存到本地,然后將spinlock的next字段加1。而spinlock的owner字段依然為0,第二個進程的本地next 不等于spinlock的owner,所以一直自旋等待spinlock;
(6)、第三個進程搶占spinlock,得到本地next值為2,然后將spinlock的next字段加1。此時spinlock的owner字段還是為0,所以第三個進程自旋等待。
(7)、當第一個進程處理完臨界區以后,就釋放spinlock,執行的操作是將spinlock的owner字段加1;
(8)、由于第二個進程和第三個進程都還在等待spinlock,他們會不停第獲取spinlock的owner字段,并和自己本地的next值進行比較。當第二個進程發現自己的next值和spinlock的owner字段相等時(此時next == owner == 2),第二個進程就獲取到spinlock。第三個進程的本地next值是3,和spinlock的owner字段不相等,所以繼續等待;
(9)、只有在第二個進程釋放了spinlock,就會將spinlock的owner字段加1,第三個進程才有機會獲取spinlock。
crash | ||
whatis | 因為mm_struct的mmap_sem成員的offset就是104(0x68), 用whatis命令可以查看結構體的聲明,如 whatis -o mm_struct | |
mach | crash> mach | grep SIZE ??????? MEMORY SIZE: 1 GB ????????? PAGE SIZE: 4096 ? KERNEL STACK SIZE: 16384 ???? IRQ STACK SIZE: 16384 OVERFLOW STACK SIZE: 4096 | |
task -R stack | PID: 128????? TASK: ffff0000034f9b80? CPU: 1??? COMMAND: "insmod" ? stack = 0xffff800012b20000, | |
set | set 128 進程128 上下文 | |
bt -sS 0x11 | 給一個錯誤地址,會打印出進程128的實際棧地址 | |
bt -T | 將內核棧的內容都打印出來 | |
bt -f/-p | (-p) 只打印panic的內核棧,-f 列出堆棧中的所有數據 | |
bt -lf | (-l)顯示每層棧的源碼和所在的行數 | |
rd | 打印指針范圍的棧內容 rd ffffff8990 -e fffff9ffff > mm.txt | |
task <pid> | 打印進程的task_struct 內容 | |
dis <sym|addr> | 參數可以使地址、符號(函數名、變量名),對其反匯編得到該地址 對應的匯編源碼 | |
mod -s <module> | 加載指定安裝模塊的符號調試信息 | |
mod -d xxxmodule | 刪除指定模塊的符號表和調試信息 | |
例如 insmod modules_list.ko后,dis 模塊中的函數,發現沒有反匯編 出源碼 要先加載符號表 mod -s module_list.ko,后 dis <function> | ||
vm [pid]? | 進程虛擬地址空間 | |
help -m | 查看每個cpu的中斷棧 | |
irq_stack_size: 16384 ???????? irq_stacks[0]: ffff800010000000 ???????? irq_stacks[1]: ffff800010008000 ???????? irq_stacks[2]: ffff800012688000 ???????? irq_stacks[3]: ffff800012690000 | ||
普通的全局變量 | 普通的全局變量的值很好查看,直接p后面接函數名即可? >p jiffies_64 | |
percup全局變量 | >struct rq.clock,nr_running,cfs.h_nr_running runqueues:0,2,6? 冒號后指定 CPU | |
局部變量 | ATPCS規則可知:函數調用時傳遞的參數,當參數數量小于等于8個時, 使用x0~x7傳遞,大于8個時,多余的參數使用棧傳遞; 函數返回時返回值保存在x0中 | |
下面命令對父函數cpu_stopper_thread函數進行反匯編, 其中"/s"參數表示顯示匯編在C文件中的行數 disassemble /s cpu_stopper_thread | ||
哪些線程正在訪問/訪問過 指定的變量/內存/鎖 | 哪些線程正在訪問/訪問過指定的變量 再介紹最后一個實用技巧,有時候我們在分析dump的時候經常會有這樣的需求: 已經知道某一把鎖在內存中的地址,我們想知道有哪些線程在等這把鎖; 已經知道某個全局變量的地址或名稱,我們想知道有哪些任務正在訪問這個全局變量; 已經知道某個函數名稱,我們想知道有哪些任務的調用棧中會調用到這個函數; 這時候我們就可以使用下面命令格式,來對系統中所有的任務的調用棧進行搜索了,其中-t是對所有的任務進行搜索,不區分任務的狀態。而-T則表示只對系統中正在running的任務的調用棧進行搜索 search -t/T <變量名|變量地址|函數名|函數地址|內存地址> |