c - Fork Process/Read Write through pipe 慢

标签 c linux tcp pipe lame

回答

https://stackoverflow.com/a/12507520/962890

太琐碎了..args!但收到了很多好的信息。感谢大家。

编辑

github 链接:https://github.com/MarkusPfundstein/stream_lame_testing

原帖

我有一些关于通过管道进行 IPC 的问题。我的目标是接收每个 TCP/IP 流的 MP3 数据,通过 LAME 将其解码为 wav,进行一些数学运算并将其存储在磁盘上(作为 wav)。我在整个过程中都使用非阻塞 IO。 让我有点恼火的是,tcp/ip 读取比管道线槽快得多。当我发送 ~3 MB mp3 时,文件会在几秒钟内在客户端读取。一开始,我还可以写入 lame 进程的标准输入,然后它停止写入,它读取 mp3 的其余部分,如果它完成,我可以再次写入 lame。 4096 字节大约需要 1 秒(从 lame 写入和读取)。这很慢,因为我想解码我的 wav min 128kbs。

该微型计算机上的操作系统是 debian 2.6 内核:

https://www.olimex.com/dev/imx233-olinuxino-maxi.html

65 MB 内存 400兆赫

ulimit -n | grep pipe 返回 512 x 8 ,表示 4096 没问题。它是一个 32 位系统。

奇怪的是

我的进程 | lame --decode --mp3input - output.wav

速度很快。

这是我的 fork_lame 代码(它将本质上将我的流程的 stout 连接到 lame 的标准输入,反之亦然)

static char * const k_lame_args[] = {
  "--decode",
  "--mp3input",
  "-",
  "-",
  NULL
};

static int
fork_lame()
{
  int outfd[2];
  int infd[2];
  int npid;
  pipe(outfd); /* Where the parent is going to write to */
  pipe(infd); /* From where parent is going to read */
  npid = fork();
  if (npid == 0) {
    close(STDOUT_FILENO);
    close(STDIN_FILENO);
    dup2(outfd[0], STDIN_FILENO);
    dup2(infd[1], STDOUT_FILENO);
    close(outfd[0]); /* Not required for the child */
    close(outfd[1]);
    close(infd[0]);
    close(infd[1]);
    if (execv("/usr/local/bin/lame", k_lame_args) == -1) {
      perror("execv");
      return 1;
    }
  } else {
    s_lame_pid = npid;
    close(outfd[0]); /* These are being used by the child */
    close(infd[1]);
    s_lame_fds[WRITE] = outfd[1];
    s_lame_fds[READ] = infd[0];
  }
  return 0;
}

这是读写函数。请不要在 write_lame_in 中那样做。当我写入 stderr 而不是 s_lame_fds[WRITE] 时,输出几乎是即时的,所以它肯定是通过 lame 的管道。但是为什么?

static int
read_lame_out() 
{
  char buffer[READ_SIZE];
  memset(buffer, 0, sizeof(buffer));
  int i;
  int br = read(s_lame_fds[READ], buffer, sizeof(buffer) - 1);
  fprintf(stderr, "read %d bytes from lame out\n", br);
  return br;
}

static int
write_lame_in()
{
  int bytes_written;
  //bytes_written = write(2, s_data_buf, s_data_len);
  bytes_written = write(s_lame_fds[WRITE], s_data_buf, s_data_len);
  if (bytes_written > 0) {
    //fprintf(stderr, "%d bytes written\n", bytes_written);
    s_data_len -= bytes_written;
    fprintf(stderr, "data_len write: %d\n", s_data_len);
    memmove(s_data_buf, s_data_buf + bytes_written, s_data_len);
    if (s_data_len == 0) {
      fprintf(stderr, "finished\n");
    }
  } 

  return bytes_written;
}

static int
read_tcp_socket(struct connection_s *connection)
{
  char buffer[READ_SIZE];
  int bytes_read;
  bytes_read = connection_read(connection, buffer, sizeof(buffer)-1);
  if (bytes_read > 0) {
    //fprintf(stderr, "read %d bytes\n", bytes_read);
    if (s_data_len + bytes_read > sizeof(s_data_buf)) {
      fprintf(stderr, "BUFFER OVERFLOW\n");
      return -1;
    } else {
      memcpy(s_data_buf + s_data_len,
             buffer,
             bytes_read);
      s_data_len += bytes_read;
    }
    fprintf(stderr, "data_len: %d\n", s_data_len);
  }
  return bytes_read;
}

选择内容是非常基本的选择逻辑。当然,所有 block 都是非阻塞的。

有人知道吗?我真的很感激任何帮助;-)

最佳答案

糟糕!你检查过你的 LAME 输出了吗?

特别是查看您的代码

static char * const k_lame_args[] = {
  "--decode",
  "--mp3input",
  "-",
  "-",
  NULL
};

if (execv("/usr/local/bin/lame", k_lame_args) == -1) {

意味着你不小心省略了 --decode 标志,因为对于 LAME 它将是 argv[0],而不是第一个参数(argv[1 ])。你应该使用

static char * const k_lame_args[] = {
  /* argv[0] */  "lame",
  /* argv[1] */  "--decode",
  /* argv[2] */  "--mp3input",
  /* argv[3] */  "-",
  /* argv[4] */  "-",
                 NULL
};

相反。

我认为您看到速度变慢是因为您不小心重新压缩了 MP3 音频。 (我在一分钟前注意到了这一点,所以没有检查如果您省略 --decode 标志,LAME 是否会这样做,但我相信它会。)

关于c - Fork Process/Read Write through pipe 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12472703/

相关文章:

linux - 编译错误

tcp - 我可以将 ZeroMQ 与基于软件的负载均衡器 HAProxy 一起使用吗?

ssl - 为什么 QUIC 协议(protocol)使用在 TCP 上运行的 TLS 数据包时却被说是基于 UDP 构建的?

c - fread:如何知道缓冲区的大小?

c - 如何只删除字符串中的第一个空格? C语言

c - 用多线程修改一个结构c编程

c - 系统范围页表

linux - 切换用户并输出变量内容

linux - rsync 错误 : received SIGINT, SIGTERM 或 SIGHUP(代码 20)位于 rsync.c(544) [sender=3.0.6]

c - 在 C 中通过 TCP 套接字发送视频的最佳方式