2009-01-20 276 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