Linux 문제: /dev/stdin이 소켓에서 작동하지 않습니다.

Linux 문제: /dev/stdin이 소켓에서 작동하지 않습니다.

/dev/stdinLinux에는 소켓과 작동하지 않는 성가신 기능이 있습니다 . 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'

thingyLinux의 파이프는 단방향이므로 동일한 fd를 읽고 쓰려는 경우 이는 낭비적이고 더 나쁜 것은 쓸모가 없습니다.

우리 뭐 할까? /dev/stdin내가 아는 한, Linux에서는 양방향 파이프를 사용하여 파이프라인을 구축할 수 없습니다. 소켓은 읽기 및 쓰기를 위해 단일 fd를 사용하여 양방향 스트림을 생성하는 Linux의 유일한 기본 메커니즘이기 때문입니다(파이프 쌍과 비교). ).

답변1

LD_PRELOADLinux가 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/xfd x에서 열린 파일에 대한 심볼릭 링크라는 것입니다. open()소켓에서는 할 수 없습니다 . 그건 말이 안 됩니다. BSD와는 완전히 다릅니다 open("/dev/fd/x"). dup(x)파일이 파이프일 때 이런 느낌이 들지만 그렇지 않습니다. 실제로 명명된 파이프를 여는 것과 같습니다(다른 모드(읽기 및 쓰기)에서 열어 파이프의 다른 쪽 끝을 가져올 수도 있습니다).

두 방법 모두 장점과 단점이 있습니다. 제가 보기에는 귀하의 응용 프로그램이 fd 번호를 사용하는 대신 매개변수로 사용해야 하는 것 같습니다 /dev/fd/x. 이는 애초에 해킹이며 예를 들어 fd를 낭비하게 만들 것입니다.

관련 정보