# gcc testlsof.c -o testlsof # ./testlsof & [1] 3125 # strace -o lsof.strace lsof -p 3125 |
我们以"/tmp/foo"为关键字搜索输出文档lsof.strace,结果只有一条:
# grep '/tmp/foo' lsof.strace readlink("/proc/3125/fd/3", "/tmp/foo", 4096) = 8 |
原来lsof巧妙的利用了/proc/nnnn/fd/目录(nnnn为 pid):Linux内核会为每一个进程在/proc/建立一个以其pid为名的目录用来保存进程的相关信息,而其子目录fd保存的是该进程打开的任何文档的fd。目标离我们很近了。好,我们到/proc/3125/fd/看个究竟:
# cd /proc/3125/fd/ # ls -l total 0 lrwx------ 1 root root 64 Nov 5 09:50 0 -> /dev/pts/0 lrwx------ 1 root root 64 Nov 5 09:50 1 -> /dev/pts/0 lrwx------ 1 root root 64 Nov 5 09:50 2 -> /dev/pts/0 lr-x------ 1 root root 64 Nov 5 09:50 3 -> /tmp/foo # readlink /proc/3125/fd/3 /tmp/foo |
答案已很明显了:/proc/nnnn/fd/目录下的每一个fd文档都是符号链接,而此链接就指向被该进程打开的一个文档。我们只要用readlink()系统调用就能够获取某个fd对应的文档了,代码如下:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> int get_pathname_from_fd(int fd, char pathname[], int n) { char buf[1024]; pid_t pid; bzero(buf, 1024); pid = getpid(); snprintf(buf, 1024, "/proc/%i/fd/%i", pid, fd); return readlink(buf, pathname, n); } int main(void) { int fd; char pathname[4096]; bzero(pathname, 4096); fd = open("/tmp/foo", O_CREAT|O_RDONLY); get_pathname_from_fd(fd, pathname, 4096); printf("fd=%d; pathname=%s\n", fd, pathname); return 0; } |
出于安全面的考虑,在FreeBSD 5 之后系统默认已不再自动装载proc文档系统,因此,要想使用truss或strace跟踪程式,您必须手工装载proc文档系统:mount -t procfs proc /proc;或在/etc/fstab中加上一行:
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!