Linux kernel分析前的准备
分析工具
“欲善其事,先利其器”。Linux內核的代碼量非常大,如果沒有一個好的察看分析工具,那將是一件非常繁瑣的事情。
Vim+cscope
cscope,如果你知道ctags,那么它是一個比ctags更強大的工具,如果你不知道ctags,也沒關系,cscope使你可以在一大堆的代碼中進行輕松查找函數、宏、結構體等標示符定義處、使用點,并進行跳轉。
安裝
cscope在Fedora和Ubuntu的源里都有,可以直接yum或apt-get。
Fedora下cscope安裝好后就直接可以與Vim一起使用,但Ubuntu下安裝好cscope后,還要在/ect/vim/vimrc文件的最后添加如下內容:
if has("cscope")set csprg=/usr/bin/cscopeset csto=0set cstset nocsverb" add any database in current directoryif filereadable("cscope.out")cs add cscope.out" else add database pointed to by environmentelseif $CSCOPE_DB != ""cs add $CSCOPE_DBendifset csverb endif這使Vim可以自動加載cscope生成的索引文件。要獲取更多信息,在Vim中輸入“:help cscope"也可以得到。
使用
首先在源碼目錄下用cscope生成cscope索引文件,
cscope -bqR當前目錄下會生成cscope.out,cscope.in.out和cscope.po.out三個索引文件。
其中參數含義如下:
-b 只生成索引文件,并不進入cscope交互界面;
-q 生成cscope.in.out和cscope.po.out兩個文件,加快查找;
-R 遍歷子目錄。
我只用到這三個命令,如果想了解更多,可以察看help或man文檔。
現在就可以用了,如果你不想給自己找一些不必要的麻煩,你應該在有cscope.out,cscope.in.out和cscope.po.out的目錄直接運行Vim:
vim .(或者vim ./)
在這里再介紹一個Vim插件NERD tree,此插件可以使vim中的目錄更好看,效果圖如下:
在Vim中,cscope使用最多的命令是find,可以簡寫為f。想要獲取Vim中cscope的其他命令,可以輸入:
:cs help
來獲取,結果如下:
cscope 命令:
add ?:添加一個新的數據庫 ? ? ? ? ? ? (用法: add file|dir [pre-path] [flags]) find :查詢一個模式 ? ? ? ? ? ? ? ? ? (用法: find c|d|e|f|g|i|s|t name) c: Find functions calling this function d: Find functions called by this function e: Find this egrep pattern f: Find this file g: Find this definition i: Find files #including this file s: Find this C symbol t: Find this text string help :顯示此信息 ? ? ? ? ? ? ? ? ? ? (用法: help) kill :結束一個連接 ? ? ? ? ? ? ? ? ? (用法: kill #) reset:重置所有連接 ? ? ? ? ? ? ? ? ? (用法: reset) show :顯示連接 ? ? ? ? ? ? ? ? ? ? ? (用法: show)我經常使用的有:
c 查找一個函數被那個函數調用,此命令僅限于函數對函數。我一般會用s來代替c,因為可能結構體中也有使用了該函數,那么c命令是查不到的,而s就可以。
f 查找一個文件。
g 查找某個函數的定義處。
s 查找一個標示符,結果會包括c、g命令的結果和其他地方使用了此標示符的地方(標示符不同于字符串,它是獨立存在的,并不是一個字符串的一部分)。
t 此命令是最耗時的命令,它在代碼中查找所有含有此字符串的地方。
最后當你找到你要找的項,輸入數字標號就會跳轉到你要著的那一項。
實例
代碼:Linux內核代碼,版本3.5.4
具體函數為fs/btrfs/acl.c文件中的第一個函數btrfs_get_acl。
查找此函數的定義處
在Vim中輸入:
:cs f g btrfs_get_acl查找此函數的定義處,顯示如下:
Cscope tag: btrfs_get_acl # ? 行 ? ?文件名 / 上下文 / 行 1 ? ? 31 ?fs/btrfs/acl.c <<btrfs_get_acl>> struct posix_acl *btrfs_get_acl(struct inode *inode, int type) 2 ? 3100 ?fs/btrfs/ctree.h <<btrfs_get_acl>> #define btrfs_get_acl NULL我們發現有兩處,但仔細看看,第二項并不是你要找的,第一項才是你要找的。
查找此函數被那些函數調用
:cs f c btrfs_get_acl顯示如下:
Cscope tag: btrfs_get_acl # ? 行 ? ?文件名 / 上下文 / 行 1 ? ? 88 ?fs/btrfs/acl.c <<btrfs_xattr_acl_get>> acl = btrfs_get_acl(dentry->d_inode, type); 2 ? ?207 ?fs/btrfs/acl.c <<btrfs_init_acl>> acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT); 3 ? ?253 ?fs/btrfs/acl.c <<btrfs_acl_chmod>> acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);其中上面的內容簡單介紹一下,1、2、3是標號;后面跟著的數字是在文件中的行號;后面是文件名;雙尖括號里的是調用btrfs_get_acl函數的函數;下面的一行是調用此函數的內容,有時,你可以從文件名和內容猜測是不是你要著的東西。
查找此標示符在那些地方出現
:cs f s btrfs_get_acl 顯示如下: Cscope tag: btrfs_get_acl # ? 行 ? ?文件名 / 上下文 / 行 1 ? 3095 ?fs/btrfs/ctree.h <<GLOBAL>> struct posix_acl *btrfs_get_acl(struct inode *inode, int type); 2 ? 3100 ?fs/btrfs/ctree.h <<GLOBAL>> #define btrfs_get_acl NULL 3 ? 7624 ?fs/btrfs/inode.c <<GLOBAL>> .get_acl = btrfs_get_acl, 4 ? 7629 ?fs/btrfs/inode.c <<GLOBAL>> .get_acl = btrfs_get_acl, 5 ? 7697 ?fs/btrfs/inode.c <<GLOBAL>> .get_acl = btrfs_get_acl, 6 ? 7708 ?fs/btrfs/inode.c <<GLOBAL>> .get_acl = btrfs_get_acl, 7 ? 7722 ?fs/btrfs/inode.c <<GLOBAL>> .get_acl = btrfs_get_acl, 8 ? ? 31 ?fs/btrfs/acl.c <<btrfs_get_acl>> struct posix_acl *btrfs_get_acl(struct inode *inode, int type) 9 ? ? 88 ?fs/btrfs/acl.c <<btrfs_xattr_acl_get>> acl = btrfs_get_acl(dentry->d_inode, type); 10 ? ?207 ?fs/btrfs/acl.c <<btrfs_init_acl>> acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT); 11 ? ?253 ?fs/btrfs/acl.c <<btrfs_acl_chmod>> acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);從上面的查找內容可以看出,除了剛剛上面兩種查找到的結果,其中還有一些其他的項。
其中第一項是此函數的聲明;第二項和第八項是查找定義處時就有的;第三項到第七項是其他地方調用到地方,這些地方是結構體對它調用。
想更好的使用,還需要你去慢慢練習
分析方法
方法有多種,看你怎么用!
如果能找到資料,那我們從資料入手,這是最好的辦法;
如果我們只能找到一些零散的資料,這些資料中并沒有對代碼的分析,只是對這個軟件進行了一些功能介紹,我們可以從這些功能入手,從這些功能的每一個點入手,找關鍵字,然后將這些功能定位到代碼中,接下來再從代碼開始分析;
但有時沒有任何的資料,那就要從代碼中來,你可以先從代碼的入口開始,一般是main函數,但Linux內核代碼太大,如果這樣分析的話,我們面對的是整個內核代碼,這將是一個浩大的工程,你會望而卻步的,所以,你要從點入手,內核代碼非常規程,模塊化特別好,你可以從單個模塊入手,然后在這個模塊中尋找更小的功能點開始。
資料搜索
首選google,其次百度。搜索是可以將想要搜索的信息精簡,放小范圍。
搜索多個結果進行對比。
做筆記,我喜歡用MediaWiki作為我的文檔管理器,MediaWiki可以很好的對你的文檔各個版本進行記錄。你可以回到N天前你修改的文檔。
經驗積累
Linux內核中用到了許多經典的編程思想,我們會經常見到不懂的點,這些點我們可以從網上基本上都能找到,但是,有些點,我們看一遍之后幾天又忘了,這時做筆記就尤為重要。
?
以上都是我的經驗之談,更多還需要自己實踐。
轉載于:https://www.cnblogs.com/snowsolf/p/Linux-kernel-analyse.html
總結
以上是生活随笔為你收集整理的Linux kernel分析前的准备的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Subst - 简单将任意
- 下一篇: 怎么在VS监视DataSet类型的数据