分享

《linux调试工具fuser的深入分析》

 fym0121 2011-07-12
概述:
fuser命令可以显示使用文件系统或文件的PID.

##################################################
试验前先建立环境:
mount /dev/sdb1 /mnt/
例程如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main ()
{
        int fd;
        fd = open("/mnt/temp", O_WRONLY|O_SYNC|O_CREAT);
        lseek(fd, 80L, SEEK_SET);
        sleep(100);
        close(fd);
        return 0;
}
编译:
gcc test.c -o test
移动test和test.c文件到/mnt/下进行测试
##################################################
以下的测试将对fuser的六种访问状态进行分析,如下:
c      current directory.
e      executable being run.
f      open file. f is omitted in default display mode.
F      open file for writing. F is omitted in default display mode.
r      root directory.
m      mmap'ed file or shared library.
测试1)用fuser显示正在运行的程序,测试ACCESS为e位的情况(executable being run.)
终端1)执行test二进制程序
/mnt/test
终端2)
fuser -v /mnt/test
                     USER        PID ACCESS COMMAND
/mnt/test:          root       2466 ...e. test

注:fuser -v列出/mnt/test程序在运行,同时输出它的PID为2466,ACCESS为e说明它是以一个可执行程序运行的.
##################################################
测试2)用fuser显示被只读方式打开的文件,测试ACCESS为f位的情况(open file. f is omitted in default display mode.)
终端1)用less打开test.c文件
less /mnt/test.c
终端2)
fuser -v /mnt/test.c
                     USER        PID ACCESS COMMAND
/mnt/test.c:         root      10546 f.... less
注:用less打开的文件,fuser显示它的ACCESS位为f,表示打开的方式是只读的.
##################################################

测试3)用fuser显示被可写方式打开的文件,测试ACCESS为F位的情况(open file for writing. F is omitted in default display mode.)
终端1)用vi打开test.c文件
vi /mnt/test.c
终端2)
fuser -vm  /mnt/
                     USER        PID ACCESS COMMAND
/mnt/:               root     kernel mount /mnt
                     root      10488 ..c.. bash
                     root      10625 F.... vi
注:用vi打开的文件,fuser显示它的ACCESS位为F,表示打开的方式为可写.
另外如果用fuser -v /mnt/test.c将看不到输出,因为vi打开的文件实际是/mnt/.test.c.swp,在存盘时才会写到test.c中.
我们也可以用cat > /mnt/test.c的方式进行测试.
##################################################

测试4)用fuser显示的目录是否是用户的当前目录(current directory.)
终端1)用cd命令进入/mnt/目录
cd /mnt/
终端2)
fuser -vm  /mnt/
                     USER        PID ACCESS COMMAND
/mnt/:               root     kernel mount /mnt
                     root       3486 ..c.. bash
                     root      10488 ..c.. bash
注:用cd命令进入/mnt/目录,fuser显示它的ACCESS位为c,表示已经有用户正在这个目录下
##################################################

测试5)用fuser显示的目录是否是根目录(root directory)
终端1)
切换到普通用户test,并进入到/tmp目录
su - test
cd /tmp
fuser -vm /tmp
                     USER        PID ACCESS COMMAND
/tmp:                root     kernel mount /
                     test     11274 .rce. bash
注:如果root用户使用fuser -vm /tmp会看到大量的输出,原因是/tmp是根系统系统下挂载的目录.
如果用普通用户test,由于权限的原因,这里只输出了自己的进程.
ACCESS为r说明这个进程用到的目录或文件是根目录下的.如果我们用fuser -vm /mnt/则看不到ACCESS为r的输出,因为它是单独的挂载.
这里我们假设/tmp是根分区系统下的目录,而不是单独的分区.
##################################################

测试6)用fuser显示mmap的文件或是共享lib库的文件的使用信息.(mmap'ed file or shared library.)
终端1)创建test2.c源程序,以测试mmap
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#define ERROR(x) do{ perror(x);exit (EXIT_FAILURE); } while(0)
int
main (int argc, char *argv[])
{
    const int nbytes = 4096;
    void *ptr;
    int fd = open("/mnt/test2.dat", O_RDWR|O_CREAT);
    if (fd == -1) ERROR("open");
        ptr = mmap(0, nbytes, PROT_READ|PROT_WRITE,MAP_PRIVATE, fd, 0);
    if (ptr == MAP_FAILED) ERROR("mmap");
    memset(ptr, 1, nbytes);
    sleep(100);
    munmap(ptr, nbytes);
    return 0;
}
gcc test2.c -o /mnt/test2
运行/mnt/teset2
/mnt/test2

终端2)
fuser -v /mnt/test2.dat
                     USER        PID ACCESS COMMAND
/mnt/test2.dat:      root      11525 F...m test2
注:这里我们看到ACCESS位为m,mmap简单的来说就是将文件(/mnt/test2.dat)映射到内存,修改了内存就是修改了文件.
我们最后来看一下fuser查看共享库的试验.
终端1)
fuser -v /lib/libc.so.6
可以看到用到libc.so.6共享库的进程.

测试7)我们这里用两个简单的用例来做为本文的结束
1)杀掉用到/mnt目录的进程
fuser -kvm /mnt/
注:这里我们最好先用fuser -v /mnt/来查看用到/mnt目录有几个进程,同时我们也可以指定-i参数,来对kill的进程进行提示操作.
同时也可以指定kill发送的信号,例如:
fuser -kvim -HUP /mnt/
                     USER        PID ACCESS COMMAND
/mnt/:               root     kernel mount /mnt
                     root       3486 ..c.. bash
Kill process 3486 ? (y/N) y
用fuser -l可以列出可以发送的信号
2)显示所用用到ssh服务端口的进程
fuser ssh/tcp

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多