/dev/stdin
Linux에는 소켓과 작동하지 않는 성가신 기능이 있습니다 . ENXIO를 반환하도록 하드코딩되어 있습니다. 이 시도:
socat TCP-OPEN:localhost:1234 EXEC:cat\ /dev/stdin,nofork
이는 작동할 것으로 예상되는 매우 합리적인 명령이며 기본적으로 Linux를 제외한 모든 시스템에서 작동합니다. ( cat
나는 사용할 특정 fd를 지정할 수 있는 유일한 방법으로 일반적인 예로 파일 이름을 여는 도구를 사용하고 있습니다.)
Linux 커널은 /dev/stdin
이러한 방식으로 공정한 사용을 금지하도록 명시적으로 작성되었습니다.http://marc.info/?l=ast-users&m=120978595414993.
단방향 기능만 필요한 경우 별도의 프로세스에서 데이터를 버퍼링할 수 있습니다.
socat TCP-OPEN:localhost:1234 SYSTEM:'cat | thingy /dev/stdin'
thingy
Linux의 파이프는 단방향이므로 동일한 fd를 읽고 쓰려는 경우 이는 낭비적이고 더 나쁜 것은 쓸모가 없습니다.
우리 뭐 할까? /dev/stdin
내가 아는 한, Linux에서는 양방향 파이프를 사용하여 파이프라인을 구축할 수 없습니다. 소켓은 읽기 및 쓰기를 위해 단일 fd를 사용하여 양방향 스트림을 생성하는 Linux의 유일한 기본 메커니즘이기 때문입니다(파이프 쌍과 비교). ).
답변1
LD_PRELOAD
Linux가 BSD 방식을 모방하도록 하려면 언제든지 트릭을 사용할 수 있습니다 . fddup.c
:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int whichfd(const char *pathname)
{
unsigned int fd;
if (sscanf(pathname, "/dev/fd/%u", &fd) == 1)
return fd;
else
return -1;
}
int open(const char *pathname, int flags, mode_t mode)
{
static int (*orig)(const char *, int, mode_t) = 0;
int fd = whichfd(pathname);
if (fd >= 0)
return dup(fd);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"open");
if (!orig) abort();
return orig(pathname, flags, mode);
}
}
FILE *fopen(const char *path, const char *mode)
{
static FILE *(*orig)(const char *, const char *) = 0;
int fd = whichfd(path);
if (fd >= 0)
return fdopen(dup(fd), mode);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"fopen");
if (!orig) abort();
return orig(path, mode);
}
}
(이와 같이 더 포장해야 할 수도 있습니다 freopen()
).
gcc -Wall -fPIC -shared -o fddup.so fddup.c -ldl
그런 다음:
socat TCP:localhost:22 'EXEC:env LD_PRELOAD=./ddup.so cat /dev/fd/0,nofork'
Linux와 BSD는 근본적으로 다릅니다. /dev/fd/0
소켓인 경우 열 수 없다는 것이 아니라 /dev/fd/x
fd x에서 열린 파일에 대한 심볼릭 링크라는 것입니다. open()
소켓에서는 할 수 없습니다 . 그건 말이 안 됩니다. BSD와는 완전히 다릅니다 open("/dev/fd/x")
. dup(x)
파일이 파이프일 때 이런 느낌이 들지만 그렇지 않습니다. 실제로 명명된 파이프를 여는 것과 같습니다(다른 모드(읽기 및 쓰기)에서 열어 파이프의 다른 쪽 끝을 가져올 수도 있습니다).
두 방법 모두 장점과 단점이 있습니다. 제가 보기에는 귀하의 응용 프로그램이 fd 번호를 사용하는 대신 매개변수로 사용해야 하는 것 같습니다 /dev/fd/x
. 이는 애초에 해킹이며 예를 들어 fd를 낭비하게 만들 것입니다.