flip_close Oops问题排查

来源:互联网 发布:anaconda 包含python 编辑:程序博客网 时间:2024/06/05 08:19

1、问题描述

Oops[#1]:
Cpu 0
$ 0   : 00000000 00000001 64206e6f 838ceae0
$ 4   : 838ceae0 83816140 00000001 00000007
$ 8   : 0000080f 00000004 00000020 83934668
$12   : 82fdb128 ffffffff 00000001 823c39b0
$16   : 00000000 838ceae0 83816140 00000010
$20   : 83816148 00000001 011a0000 00000017
$24   : 00000000 80011558                  
$28   : 83b3a000 83b3bd90 06c00000 8006c314
Hi    : 00000000
Lo    : 00000001
epc   : 64206e6f 0x64206e6f
    Tainted: P          
ra    : 8006c314 filp_close+0x5c/0x90
Status: 1100ff03    KERNEL EXL IE 
Cause : 00800008
BadVA : 64206e6e
PrId  : 0001974c (MIPS 74Kc)
Modules linked in: ar9344_watchdog ath_pktlog(P) umac ath_dev(P) ath_dfs(P) ath_rate_atheros(P) ath_hal(P) asf(P) adf ar9344_button ar9344_led athrs_gmac [last unloaded: ar9344_watchdog]
Process agent (pid: 209, threadinfo=83b3a000, task=838b8dc0, tls=00000000)
Stack : 83446a10 834540d4 ffffff9c 00000000 83816140 00000007 00000000 8002596c
        0000000f 838b8dc0 83b3bea0 82abfe40 0000000f 838b8dc0 83b3bea0 82abfe40
        83b04da4 800270d8 00000008 00000007 00000008 838b9164 838b9164 83b3bea0
        0000000f 83b04e64 83b3bea0 82abfe40 83b04da4 83b3bf30 011a0000 00000017
        06c00000 80027544 83b3bf30 838b9164 83b3bea0 82abfe40 00000009 800305e0
        ...
Call Trace:
[<8002596c>] put_files_struct+0xa4/0x128
[<800270d8>] do_exit+0x178/0x568
[<80027544>] do_group_exit+0x7c/0xa8
[<800305e0>] get_signal_to_deliver+0x328/0x3c8
[<8006c90c>] nameidata_to_filp+0x3c/0x60
[<800088f0>] do_notify_resume+0x60/0x2bc
[<8006c528>] do_sys_open+0xc8/0xec
[<800642f0>] sys_brk+0x11c/0x140
[<80006188>] work_notifysig+0xc/0x14
[<800f27b0>] __bzero+0xd4/0x164
[<8006c554>] sys_open+0x0/0x1c

Code: (Bad address in epc)
c/rc.d/rc.bridgeFatal exception: panic in 5 seconds

2、环境描述

进程2: 进程1的子进程,由进程1 调用system函数生成。(注: system函数调用了fork函数和execl函数)

进程1: 进程2的父进程 

驱动1:该驱动为字符设备驱动,进程1通过open函数打开其提供的字符设备文件(/dev/test)

3、问题分析

执行过程: 父进程退出(killall 命令强制退出)后,卸载驱动1(通常打开的文件没有释放的话, 无法卸载驱动; 但由于当前驱动1在struct file_operations 中并没有初始化ower=THIS_MODULE,故可成功卸载驱动),并重新启动,此时出现上述的Oops现象。

问题分析: 由于子进程共享文件描述符,在父进程退出时并没有真正的关闭open函数打开的struct file文件(killall 父进程,仅仅将struct file对应的引用计数(f_count)减1,只有当其为0时,才会调用驱动release函数并释放打开的文件),系统重新启动时,系统将关闭该文件,但此时驱动已经被卸载。


4、解决方案

在进程1中添加如下代码,其实质就是设置fd的属性,当调用exec族函数时,关闭子进程中的对应的文件描述符。

     int fd=open("foo.txt",O_RDONLY);     int flags = fcntl(fd, F_GETFD);     flags |= FD_CLOEXEC;     fcntl(fd, F_SETFD, flags);
具体分析见博客"使用FD_CLOEXEC实现close-on-exec,关闭子进程无用文件描述符"

这样设置之后,killall 父进程,将直接调用驱动中的release函数并释放父进程打开的strcut file文件。

0 0