天天看點

使用skyeye運作《Linux裝置驅動開發詳解》的執行個體(二)

<a>編譯和安裝</a>

<a>選中三個子產品:</a>

<a>─── driver examples in 'Explain Linux Device Drivers in detail' ─────────────────────────────┐   │  Arrow keys navigate the menu.  &lt;Enter&gt; selects submenus ---&amp;gt;.  Highlighted letters are hotkeys.  Pressing &lt;Y&gt;        │     │  includes, &lt;N&gt; excludes, &lt;M&gt; modularizes features.  Press &lt;Esc&gt;&lt;Esc&gt; to exit, &lt;?&gt; for Help, &lt;/&gt; for Search.  Legend:  │     │  [*] built-in  [ ] excluded  &lt;M&gt; module  &lt; &gt; module capable                                                           │     │                                                                                                                       │     │ ┌───────────────────────────────────────────────────────────┐ │     │ │                      --- driver examples in 'Explain Linux Device Drivers in detail'                              │ │     │ │                      &lt;M&gt;   Hello World                                                                            │ │     │ │                      &lt;M&gt;   globalmem                                                                              │ │     │ │                      &lt;M&gt;   globalfifo                                                                             │ │     │ │                                                                                                                   │ │</a>

<a>在linux-2.6.31下運作:</a>

<a>bhsong@bhsong-laptop:~/develop/svn/ldd6410/linux-2.6.31$ make modules</a>

<a>以loopback方式mount根檔案系統,譬如對于skyeye的initrd.img運作如下指令:</a>

<a>...skyeye/training-simulation$ sudo mount -o loop initrd.img initrd</a>

<a>将所有子產品安裝到根檔案系統:</a>

<a>make INSTALL_MOD_PATH=/home/bhsong/develop/training/skyeye/training-simulation/initrd modules_install</a>

<a>請根據你的路徑,正确的設定INSTALL_MOD_PATH。安裝之後,所有子產品以及子產品間依賴關系進入根檔案系統:</a>

<a>啟動Linux,對于skyeye為:</a>

<a>sudo skyeye -e vmlinux -c skyeye-standalone.conf ... Welcome to      _      _____      __   __    _      _     / \    /  __ \    /  \_/  \  | |    |_|                     / _ \   | |  | |  / /\   /\ \ | |     _ ____  _   _  _  _    / /_\ \  | |__| | / /  \_/  \ \| |    | |  _ \| | | |\ \/ / / /___\ \ | |__\ \ | |       | || |___ | | |_| | |_| |/    \ /_/     \_\| |   \_\|_|       |_||_____||_|_| |_|\____|\_/\_/             ARMLinux for Lihacker LDD6410 For further information please check: http://www.lihacker.com/ http://www.linuxdriver.cn/ For technical support, please subscribe mail list [email protected] and post there. The url is http://groups.google.com/group/linuxdriver. #</a>

<a>加載子產品:</a>

<a>modprobe hello modprobe globalmem  globalmem_major=250 modprobe globalfifo globalfifo_major=251</a>

<a>skyeye對insmod的支援有些問題,加載子產品時會出現:</a>

<a># modprobe hello Unable to handle kernel paging request at virtual address bf000000 pgd = c05f0000 [bf000000] *pgd=00000000 Internal error: Oops: 807 [#1] Modules linked in: CPU: 0    Not tainted  (2.6.31.6-svn79 #21) PC is at __memzero+0x24/0x80 LR is at 0x0 pc : [&lt;c0107404&gt;]    lr : [&lt;00000000&gt;]    psr: 20000013 sp : c182bf0c  ip : 00000000  fp : 00000005 r10: c2807230  r9 : c2807000  r8 : c2807388 r7 : 00000004  r6 : c2807168  r5 : 00000012  r4 : bf000000 r3 : 00000000  r2 : 00000000  r1 : 00000464  r0 : bf000000 Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user Control: 0000317f  Table: c05f0000  DAC: 00000015 Process modprobe (pid: 795, stack limit = 0xc182a270) Stack: (0xc182bf0c to 0xc182c000) bf00:                            c005fba0 00000979 00000000 c2807518 c2807608  bf20: c28072dc c1139e60 c28078a0 00000010 000000c5 c2807388 c182a000 c2807630  bf40: 00000000 c008c178 00000171 00000000 0015ec79 00000287 00000001 00000008  bf60: 00000000 00000979 0015e2f0 00000000 0015e300 c002bf48 c182a000 00000000  bf80: 00000000 c0060878 c1c1a2c0 c1c2f3a0 00000003 00000979 0015e2f0 0015dfa8  bfa0: 00000080 c002bda0 00000979 0015e2f0 0015e300 00000979 0015e2f0 00000000  bfc0: 00000979 0015e2f0 0015dfa8 00000080 0015e2a0 0015dfbc 00000001 00000000  bfe0: bea65958 bea65948 000177f8 00009350 20000010 0015e300 ab081000 11000006  [&lt;c0107404&gt;] (__memzero+0x24/0x80) from [&lt;00000000&gt;] (0x0) Code: e52de004 e1a0c002 e1a0e002 e2511040 (a8a0500c)  ---[ end trace 1e19dcbb1e19dcba ]--- Segmentation fault</a>

# strace modprobe hello

execve("/sbin/modprobe", ["modprobe", "hello"], [/* 7 vars */]) = 0

uname({sys="Linux", node="lihacker", ...}) = 0

brk(0)                                  = 0x15d000

brk(0x15dd02)                           = 0x15dd02

set_tls(0x15d4a0, 0x1573c0, 0, 0x1, 0x15d4a0) = 0

brk(0x17ed02)                           = 0x17ed02

brk(0x17f000)                           = 0x17f000

getuid32()                              = 0

chdir("/lib/modules")                   = 0

chdir("2.6.31.6-svn79")                 = 0

open("/proc/modules", O_RDONLY)         = 3

fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000

read(3, ""..., 1024)                    = 0

close(3)                                = 0

munmap(0x40000000, 4096)                = 0

lstat64("/etc/modprobe.conf", 0xbe846880) = -1 ENOENT (No such file or directory)

lstat64("/etc/modprobe.d", 0xbe846880)  = -1 ENOENT (No such file or directory)

open("modules.dep", O_RDONLY)           = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=17141, ...}) = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40001000

read(3, "/lib/modules/2.6.31.6-svn79/kerne"..., 1024) = 1024

read(3, "nel/net/netfilter/x_tables.ko\n/li"..., 1024) = 1024

read(3, "/net/netfilter/xt_esp.ko: /lib/mo"..., 1024) = 1024

read(3, "ables.ko /lib/modules/2.6.31.6-sv"..., 1024) = 1024

read(3, "es/2.6.31.6-svn79/kernel/net/netf"..., 1024) = 1024

read(3, ".6-svn79/kernel/net/netfilter/nf_"..., 1024) = 1024

read(3, "b/modules/2.6.31.6-svn79/kernel/n"..., 1024) = 1024

read(3, "etfilter/nf_conntrack_ipv4.ko /li"..., 1024) = 1024

read(3, ".6.31.6-svn79/kernel/net/netfilte"..., 1024) = 1024

read(3, "defrag_ipv4.ko\n/lib/modules/2.6.3"..., 1024) = 1024

read(3, "tfilter/nf_conntrack_ipv4.ko /lib"..., 1024) = 1024

read(3, ".6-svn79/kernel/net/ipv4/netfilte"..., 1024) = 1024

read(3, "1.6-svn79/kernel/net/netfilter/x_"..., 1024) = 1024

read(3, "ib/modules/2.6.31.6-svn79/kernel/"..., 1024) = 1024

read(3, "o:\n/lib/modules/2.6.31.6-svn79/ke"..., 1024) = 757

munmap(0x40001000, 4096)                = 0

open("/lib/modules/2.6.31.6-svn79/kernel/drivers/char/driver_examples/hello.ko", O_RDONLY) = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=2425, ...}) = 0

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\1\0(\0\1\0\0\0\0\0\0\0\0\0\0\0\210"..., 3072) = 2425

read(3, ""..., 647)                     = 0

init_module(0x15e300, 2425, ""Unable to handle kernel paging request at virtual address bf000000

pgd = c0620000

[bf000000] *pgd=00000000

Internal error: Oops: 807 [#1]

Modules linked in:

CPU: 0    Not tainted  (2.6.31.6-svn79 #21)

PC is at __memzero+0x24/0x80

LR is at 0x0

pc : [&lt;c0107404&gt;]    lr : [&lt;00000000&gt;]    psr: 20000013

sp : c069ff0c  ip : 00000000  fp : 00000005

r10: c2807230  r9 : c2807000  r8 : c2807388

r7 : 00000004  r6 : c2807168  r5 : 00000012  r4 : bf000000

r3 : 00000000  r2 : 00000000  r1 : 00000464  r0 : bf000000

Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user

Control: 0000317f  Table: c0620000  DAC: 00000015

Process modprobe (pid: 796, stack limit = 0xc069e270)

Stack: (0xc069ff0c to 0xc06a0000)

ff00:                            c005fba0 00000000 00000000 c2807518 c2807608 

ff20: c28072dc c1139240 c28078a0 00000010 00000000 c2807388 00000000 c2807630 

ff40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 

ff60: 00000000 00000979 0015e2f0 00000000 0015e300 c002bf48 c069e000 00000000 

ff80: 00000000 c0060878 be846958 c002dbe0 00000000 00000979 0015e2f0 0015dfa8 

ffa0: 00000080 c002bf0c 00000979 0015e2f0 0015e300 00000979 0015e2f0 00000000 

ffc0: 00000979 0015e2f0 0015dfa8 00000080 0015e2a0 0015dfbc 00000001 00000000 

ffe0: be846958 be846948 000177f8 00009350 20000010 0015e300 ebff1fc9 e3500000 

[&lt;c0107404&gt;] (__memzero+0x24/0x80) from [&lt;00000000&gt;] (0x0)

Code: e52de004 e1a0c002 e1a0e002 e2511040 (a8a0500c) 

---[ end trace 1e19dcbb1e19dcba ]---

&lt;unfinished ...&gt;

+++ killed by SIGSEGV +++

很明顯,死在核心的linux-2.6.31/kernel/module.c的init_module()函數中,加上幾個printk:

2453 SYSCALL_DEFINE3(init_module, void __user *, umod,

2454         unsigned long, len, const char __user *, uargs)

2455 {

2456     struct module *mod;

2457     int ret = 0;

2458 

2459     printk("%s %d\n", __func__, __LINE__);

2460 

2461     /* Must have permission */

2462     if (!capable(CAP_SYS_MODULE) || modules_disabled)

2463         return -EPERM;

2464 

2465     +printk("%s %d\n", __func__, __LINE__);

2466     

2467     /* Only one module load at a time, please */

2468     if (mutex_lock_interruptible(&amp;module_mutex) != 0)

2469         return -EINTR;

2470 

2471     +printk("%s %d\n", __func__, __LINE__);

2472     

2473     /* Do all the hard work */

2474     mod = load_module(umod, len, uargs);

2475     if (IS_ERR(mod)) {

2476         mutex_unlock(&amp;module_mutex);

2477         return PTR_ERR(mod);

2478     }

2479 

2480     +printk("%s %d\n", __func__, __LINE__);

2481    

再次運作:

# modprobe hello

sys_init_module 2459

sys_init_module 2465

sys_init_module 2471

Unable to handle kernel paging request at virtual address bf000000

pgd = c05f0000

從列印資訊可以看出,panic發生在load_module函數,既然"sys_init_module 2471"被列印而"sys_init_module 2480"未列印。 繼續跟進load_module(),直到最後發現核心崩潰在memset(ptr, 0, mod-&amp;gt;core_size);:

static noinline struct module *load_module(void __user *umod,

                   unsigned long len,

                   const char __user *uargs)

{

...

     ptr = module_alloc_update_bounds(mod-&amp;gt;core_size);

     kmemleak_not_leak(ptr);

     memset(ptr, 0, mod-&amp;gt;core_size);

一路跟蹤源代碼,發現ARM的Kernel會将子產品的記憶體申請在3G-16M到3G的區域,而skyeye在核心空間處理3G以下位址的時候,會發生錯誤:

"Unable to handle kernel paging request at virtual address bf000000"

是以,workaround掉這個bug:

Index: arch/arm/kernel/module.c

===================================================================

--- arch/arm/kernel/module.c    (revision 87)

+++ arch/arm/kernel/module.c    (working copy)

@@ -38,7 +38,7 @@

#ifdef CONFIG_MMU

void *module_alloc(unsigned long size)

-       struct vm_struct *area;

+       /*struct vm_struct *area;

        size = PAGE_ALIGN(size);

        if (!size)

@@ -49,6 +49,9 @@

                return NULL;

        return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);

+*/

+

+       return size == 0 ? NULL : kmalloc(size, GFP_KERNEL);

}

#else /* CONFIG_MMU */

@@ -59,7 +62,7 @@

void module_free(struct module *module, void *region)

-       vfree(region);

+       kfree(region);

int module_frob_arch_sections(Elf_Ehdr *hdr,

由于此workaround使用了kmalloc,如果核心子產品很大,kmalloc申請的記憶體不夠存放,則可以修改: include/linux/slab.h中的KMALLOC_SHIFT_HIGH宏定義。另外,此workaround成立的條件是mem=32M或小于32M。 現在我們可以自由地加載子產品了,看看結果:

加載子產品:

Hello World enter

# modprobe globalmem  globalmem_major=250

# modprobe globalfifo globalfifo_major=251

檢視加載的子產品:

# lsmod

    Not tainted

globalmem 3356 0 - Live 0xc0f66000

hello 1188 0 - Live 0xc1128000

globalfifo 4292 0 - Live 0xc182a000

檢視裝置:

# cat /proc/devices 

Character devices:

  1 mem

  2 pty

  3 ttyp

  4 /dev/vc/0

  4 tty

  4 ttyS

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

  7 vcs

10 misc

13 input

21 sg

29 fb

128 ptm

136 pts

204 s3c2410_serial

250 globalmem

251 globalfifo

建立結點:

# mknod /dev/globalmem c 250 0

# mknod /dev/globalfifo c 251 0

讀寫裝置檔案:

# echo "hello, cisco" &amp;gt; /dev/globalmem

written 13 bytes(s) from 0

# cat /dev/globalmem 

read 4096 bytes(s) from 0

hello, cisco

# cat /dev/globalfifo &amp;

# echo "hello,Linux, I love you" &amp;gt; /dev/globalfifo 

written 24 bytes(s),current_len:24

# read 24 bytes(s),current_len:0

hello,cisco, I love you

 本文轉自 21cnbao 51CTO部落格,原文連結:http://blog.51cto.com/21cnbao/283418,如需轉載請自行聯系原作者

繼續閱讀