2009-01-20 279 views
2

我想创建一个文件,其描述符将具有一些可自定义的行为。特别是,我想创建一个文件描述符,当写入时,它会在每行的前面加上进程的名称和pid(也许是时间),但我可以想象它可以用来做其他事情。如何在linux上创建自定义文件描述符

我不想改变编写程序 - 一方面,我希望它可以用于我系统上的所有程序,甚至是shell/perl/etc。脚本,如果不是不可能改变所有东西的源代码,那将是不切实际的。

请注意,管道不会在这种情况下执行,因为当写入过程fork() s时,新创建的子级共享fd并且在管道的读取端与其父级无法区分。

有会做的方法,但是我认为他们是相当笨拙:

  1. 创建一个内核模块,将创建这样的FDS。例如,你可以打开一些/dev/customfd然后指示模块做一些改造等,或将数据发送到用户空间或插座等
  2. 使用LD_PRELOAD将覆盖FD操作功能,做这些事情上的“特殊“fd。

但是,这两种方法都非常费力,所以我想知道是否有更好的方法或任何基础设施(如现成的库)可以提供帮助。

我更喜欢不涉及内核更改的解决方案,但如果需要,我已准备好接受它们。

只是一个想法:FUSE会是答案吗?

回答

4

你有很多的选择,因为你提到使用)的LD_PRELOAD包装写(读/()函数是一个不错的办法。

我建议你使用UNIX的ptrace(2)抓住了所需的系统调用和传递参数给自己的函数。

例子:

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <linux/user.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 
int main() 
{ pid_t child; 
    long orig_eax, eax; 
    long params[3]; 
    int status; 
    int insyscall = 0; 
    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl("/bin/ls", "ls", NULL); 
    } 
    else { 
     while(1) { 
      wait(&status); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        child, 4 * ORIG_EAX, NULL); 
      if(orig_eax == SYS_write) { 
      if(insyscall == 0) { 
       /* Syscall entry */ 
       insyscall = 1; 
       params[0] = ptrace(PTRACE_PEEKUSER, 
            child, 4 * EBX, 
            NULL); 
       params[1] = ptrace(PTRACE_PEEKUSER, 
            child, 4 * ECX, 
            NULL); 
       params[2] = ptrace(PTRACE_PEEKUSER, 
            child, 4 * EDX, 
            NULL); 
       printf("Write called with " 
         "%ld, %ld, %ld\n", 
         params[0], params[1], 
         params[2]); 
       } 
      else { /* Syscall exit */ 
       eax = ptrace(PTRACE_PEEKUSER, 
          child, 4 * EAX, NULL); 
        printf("Write returned " 
          "with %ld\n", eax); 
        insyscall = 0; 
       } 
      } 
      ptrace(PTRACE_SYSCALL, 
        child, NULL, NULL); 
     } 
    } 
    return 0; 
} 
+0

谢谢您的回答。我也必须抓住fork(),但这应该是可行的。然而,这是否足够表现明智,例如。如果我在系统上追踪很多进程?这个解决方案会影响追踪的程序吗? – jpalecek 2009-01-20 17:30:13