用我自己的close()函数替换Linux中的close()函数

时间:2014-04-28 16:09:30

标签: c linux shared-libraries ld-preload

我正在尝试在Linux中提供我自己的close()函数实现。为什么?因为我发现你可以做到这一点,听起来很有趣。

这是myclose.c:

#include <stdio.h>

int close(int fd) {
    printf("Closing fd: %d\n", fd);
    return 0;
}

这是我的makefile:

all: myclose.so my-close.so

%.so: %.o
    gcc -shared -o $@ $<

%.o:%.c
    gcc -c -fPIC -o $@ $<

clean:
    rm -f *.so *.o

编译完成后,我运行:

export LD_PRELOAD=`pwd`/myclose.so

然后我跑:

cat myclose.c

我得到的输出是:

#include <stdio.h>

int close(int fd) {
    printf("Closing fd: %d\n", fd);
    return 0;
}
Closing fd: 3

耶!工作对吗?几乎。 cat不止一次调用close(),但我们只看到一行输出。根据{{​​1}}(和常识),也应该为文件描述符1和2调用strace。如果我运行close()并捕获目录中的所有文件,我会看到“关闭fd:3”,“关闭fd:4”等,直到目录中的最后一个文件。由于所有这些文件描述符都大于2,我想可能在关闭特殊文件描述符(stdout和stderr)时存在问题。但是,当我运行cat *时,我只看到常规输出而没有“关闭fd:”行,这意味着它也不适用于ls,即使ls显示{{ 1}}运行strace时。

关于什么可能出错的任何想法?

2 个答案:

答案 0 :(得分:2)

这种“替代”仅适用于动态链接的程序。

任何与实现close - 调用的库静态链接的程序都无法将其“替换”。

后者将是实现原始close()本身的库中每次调用close()的情况。标准文件描述符012似乎也是如此,因为它们最有可能在同一个库中实现,即在libc实现中使用

答案 1 :(得分:1)

我感到惊讶它的效果和它一样好!

您正在替换close()的C库条目,而不是系统调用。但是,C库的其他部分仍然用于这些程序。可能有一些直接链接到前3个文件句柄。看看你正在使用的C库的来源。