傍受したいライブラリ呼び出しがわかっている場合は、LD_PRELOAD
でロードされた共有オブジェクトを呼び出して介入できます。
shortread.c:
#include <sys/types.h>
#include <dlfcn.h>
#define MAX_FDS 1024
static int short_read_array[ MAX_FDS ];
// #define these to match your system's values
// (need to be really careful with header files since
// getting open() declared would make things very
// difficult - just try this with open(const char *, int, ...);
// declared to see what I mean...)
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
// note that the mode bits for read/write are
// not a bitwise-or - they are distinct values
#define MODE_BITS 3
// it's much easier to *NOT* even deal with the
// fact that open() is a varargs function
// but that means probably having to do some
// typedef's and #defines to get this to compile
// typedef some function points to make things easier
typedef int (*open_ptr_t)(const char *name, int flags, mode_t mode);
typedef ssize_t (*read_ptr_t)(int fd, void *buf, size_t bytes);
typedef int (*close_ptr_t)(int fd);
// function points to the real IO library calls
static open_ptr_t real_open = NULL;
static read_ptr_t real_read = NULL;
static close_ptr_t real_close = NULL;
// this will return non-zero if 'filename' is a file
// to cause short reads on
static int shortReadsOnFd(const char *filename)
{
// add logic here based on the file name to
// return non-zero if you want to do
// short reads on this file
//
// return(1);
return(0);
}
// interpose on open()
int open(const char *filename, int flags, mode_t mode)
{
static pthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER;
int fd;
pthread_mutex_lock(&open_mutex);
if (NULL == real_open)
{
real_open = dlsym(RTLD_NEXT, "open");
}
pthread_mutex_unlock(&open_mutex);
fd = real_open(filename, flags, mode);
if ((-1 == fd) || (fd >= MAX_FDS))
{
return(fd);
}
int mode_bits = flags & MODE_BITS;
// if the file can be read from, check if this is a file
// to do short reads on
if ((O_RDONLY == mode_bits) || (O_RDWR == mode_bits))
{
short_read_array[ fd ] = shortReadsOnFd(filename);
}
return(fd);
}
ssize_t read(int fd, void *buffer, size_t bytes)
{
static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
if ((fd < MAX_FDS) && (short_read_array[ fd ]))
{
// read less bytes than the caller asked for
bytes /= 2;
if (0 == bytes)
{
bytes = 1;
}
}
pthread_mutex_lock(&read_mutex);
if (NULL == real_read)
{
real_read = dlsym(RTLD_NEXT, "read");
}
pthread_mutex_unlock(&read_mutex);
return(real_read(fd, buffer, bytes));
}
int close(int fd)
{
static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&close_mutex);
if (NULL == real_close)
{
real_close = dlsym(RTLD_NEXT, "close");
}
pthread_mutex_unlock(&close_lock);
if (fd < MAX_FDS)
{
short_read_array[ fd ] = 0;
}
return(real_close(fd));
}
コンパイルのようなもので:次に
gcc -shared [-m32|-m64] shortread.c -o libshortread.so
:
export LD_PRELOAD=/path/to/libshortread.so
は、LD_PRELOADと非常に注意してください - プロセスツリーのすべてのプロセスライブラリをロードするよう強制されます。 64ビット・ライブラリをロードする必要がある場合、32ビット・プロセスは実行されません。また、64ビット・プロセスは32ビット・ライブラリのロードを強制されます。上記のソースに、環境変数LD_PRELOAD
を削除するinit関数を追加することができます(または何かに無害に設定する)。
open()
にO_DIRECT
フラグを使用するアプリケーションがある場合は、おそらく注意が必要です。読み込まれるバイト数を変更すると、ページ・サイズのIO操作だけがサポートされる可能性があるため、一部のLinuxファイル・システムおよび/または実装では、直接IOを破損する可能性があります。
このコードでは、read()
しか処理しません。 creat()
も処理する必要があります。またpread()
、readat()
、aio_read()
、およびlio_listio()
(それは私が現時点で思い出すことのできないいくつかの他のもの)でもそうは思わない。また、大きなファイルを処理する32ビットプロセスには注意してください。私はそれらを扱って以来、しばらくしていますが、それは私が思い出したように醜いことができます。
もう一つの注意点は、open()
とread()
ライブラリコールを呼び出すことはできませんし、直接関連するシステムコールを発行することができるようにfopen()
とfread()
として呼び出しです。その場合、これらの呼び出しの動作を簡単に変更することはできません。 fgets()
などのデータを読み取ることができるSTDIOベースの呼び出しのファミリ全体に介入することは、何かを壊すことなく実行することは非常に難しいことです。
がを知っている場合、アプリケーションはシングルスレッドであるため、ミューテックスを削除できます。
最も簡単なのか、最も柔軟少なくとも、おそらく 'はmkfifo()'や 'mknodを()'名前付きパイプを作成することです。 – Will
通常、単に関連する 'read()'バリアントを呼び出してフルサイズを返す 'cover'関数を呼び出しますが、必要に応じて短い量を返すように設定できます。 'ssize_t tst_read(void * buffer、size_t size、int fd){ssize_t nbytes =読み出し(バッファ、サイズ、fd); if(...適切なテスト条件...)nbytes - = 13; nbytesを返す。 } '。リンスし、テストする必要がある読み込みのような機能ごとに繰り返します。 @JonathanLefflerが提案されているよう –
ええとが、ええ、あなただけの読み取りをカプセル化することができるかどうか*その*はもちろんの最高:) – Will