linux – 动态文件内容生成:通过’流程执行’满足’文件打开’
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了linux – 动态文件内容生成:通过’流程执行’满足’文件打开’,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3818字,纯文字阅读大概需要6分钟。
内容图文
参见英文答案 > Create a virtual file that is actually a command 3个
我有一个只读文件,F.
我不是作者的程序P需要阅读F.
我希望F的内容来自另一个’生成器’程序G,每当P试图读取F(将F作为普通文件)而不是之前的任何时候.
我尝试过以下操作:
$mkfifo /well-known/path/to/F # line #1
$G > /well-known/path/to/F # line #2
现在,当P启动并尝试读取F时,它似乎能够按照我的意愿读取G生成的输出.但是,它只能这样做一次,因为G毕竟只运行一次!因此,如果P需要在执行后再次读取F,它最终将阻止在fifo上!
我的问题是,除了在某种无限循环中包围第2行以外,还有其他(优雅的)替代方案吗?
我希望的是,某种方法是将“钩子”程序注册到文件打开系统调用中,这样文件打开会导致启动钩子程序和文件读取.钩子程序输出.显然,这里的假设是:读取将从文件开始到文件结束顺序发生,而不是随机搜索.
解决方法:
FUSE软链接(或绑定装载)是一种解决方案,虽然我不认为它“优雅”,但是有很多包袱.
在* BSD上你有一个更简单的选项portalfs,你可以用一个符号链接解决问题 – 多年前它有一个端口连接到Linux,但似乎已被删除,大概是支持FUSE.
你可以很容易地注入一个库来覆盖它所做的所需的open()/ open64()libc调用.例如.:
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <dlfcn.h>
#include <stdarg.h>
// gcc -Wall -rdynamic -fPIC -nostartfiles -shared -ldl -Wl,-soname,open64 \
// -o open64.so open64.c
#define DEBUG 1
#define dfprintf(fmt, ...) \
do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
__FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
typedef int open64_f(const char *pathname, int flags, ...);
typedef int close_f(int fd);
static open64_f *real_open64;
static close_f *real_close;
static FILE *mypipe=NULL;
static int mypipefd=-1;
//void __attribute__((constructor)) my_init()
void _init()
{
char **pprog=dlsym(RTLD_NEXT, "program_invocation_name");
dfprintf("It's alive! argv[0]=%s\n",*pprog);
real_open64 = dlsym(RTLD_NEXT, "open64");
dfprintf("Hook %p open64()\n",(void *)real_open64);
if (!real_open64) printf("error: %s\n",dlerror());
real_close = dlsym(RTLD_NEXT, "close");
dfprintf("Hook %p close()\n",(void *)real_close);
if (!real_close) printf("error: %s\n",dlerror());
}
int open64(const char *pathname, int flags, ...)
{
mode_t tmpmode=0;
va_list ap;
va_start(ap, flags);
if (flags & O_CREAT) tmpmode=va_arg(ap,mode_t);
va_end(ap);
dfprintf("open64(%s,%i,%o)\n",pathname,flags,tmpmode);
if (!strcmp(pathname,"/etc/passwd")) {
mypipe=popen("/usr/bin/uptime","r");
mypipefd=fileno(mypipe);
dfprintf(" popen()=%p fd=%i\n",mypipe,mypipefd);
return mypipefd;
} else {
return real_open64(pathname,flags,tmpmode);
}
}
int close(int fd)
{
int rc;
dfprintf("close(%i)\n",fd);
if (fd==mypipefd) {
rc=pclose(mypipe); // pclose() returns wait4() status
mypipe=NULL; mypipefd=-1;
return (rc==-1) ? -1 : 0;
} else {
return real_close(fd);
}
}
编译并运行:
$gcc -Wall -rdynamic -fPIC -nostartfiles -shared -ldl -Wl,-soname,open64 \
-o open64.so open64.c
$LD_PRELOAD=`pwd`/open64.so cat /etc/passwd
19:55:36 up 1110 days, 9:19, 55 users, load average: 0.53, 0.33, 0.29
根据应用程序的确切工作方式(libc调用),您可能需要处理open()或fopen()/ fclose().上面的方法适用于cat或head,但不是排序,因为它调用fopen()代替(直接将fopen()/ fclose()添加到上面).
您可能需要比上面更多的错误处理和健全性检查(特别是对于长时间运行的程序,以避免泄漏).此代码无法正确处理并发打开.
由于管道和文件有明显的差异,因此程序可能会出现故障.
否则,假设您有daemon和socat,您可以假装没有无限循环:
daemon -r -- socat -u EXEC:/usr/bin/uptime PIPE:/tmp/uptime
这有一点点(这里应该很明显)提供程序开始写然后阻塞,所以你看到一个旧的正常运行时间,而不是按需运行.您的提供商需要使用非阻塞I / O才能正确提供即时数据. (unix域套接字将允许更传统的客户端/服务器方法,但这与您可以插入的FIFO /命名管道不同.)
更新也参见后面的问题,该问题涉及相同的主题,尽管通用于任意进程/读者而不是特定的进程/读者:
How can I make a special file that executes code when read from
(请注意,仅有fifo的答案不能可靠地推广到并发读取)
内容总结
以上是互联网集市为您收集整理的linux – 动态文件内容生成:通过’流程执行’满足’文件打开’全部内容,希望文章能够帮你解决linux – 动态文件内容生成:通过’流程执行’满足’文件打开’所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。