AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 788843
Accepted
Ole Tange
Ole Tange
Asked: 2024-12-30 03:53:08 +0800 CST2024-12-30 03:53:08 +0800 CST 2024-12-30 03:53:08 +0800 CST

为什么我不能拦截`seq`中的`write`?

  • 772

根据限制文件 IO 速度,我构建了https://git.data.coop/tange/tangetools/src/branch/master/iothrottle

它适用于某些程序:

iothrottle -i 10M cat foo > bar # Yes, here you could just use pv
iothrottle -o 1M ffmpeg -i foo.mp3 foo.wav
iothrottle -o 1M cp -a foodir /other/fs/foodir

这不会:

iothrottle -o 1M cp -a foodir /same/fs/foodir

因为在同一个文件系统上每个文件cp使用一次调用copy_file_range。

我可以接受这个限制。

它对 也不起作用seq。当我运行时,strace seq 100000我得到:

write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
write(1, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 4096) = 4096
write(1, "2680\n2681\n2682\n2683\n2684\n2685\n26"..., 4096) = 4096
write(1, "499\n3500\n3501\n3502\n3503\n3504\n350"..., 4096) = 4096
write(1, "18\n4319\n4320\n4321\n4322\n4323\n4324"..., 4096) = 4096
write(1, "7\n5138\n5139\n5140\n5141\n5142\n5143\n"..., 4096) = 4096
write(1, "\n5957\n5958\n5959\n5960\n5961\n5962\n5"..., 4096) = 4096
write(1, "6776\n6777\n6778\n6779\n6780\n6781\n67"..., 4096) = 4096
write(1, "595\n7596\n7597\n7598\n7599\n7600\n760"..., 4096) = 4096
write(1, "14\n8415\n8416\n8417\n8418\n8419\n8420"..., 4096) = 4096
write(1, "3\n9234\n9235\n9236\n9237\n9238\n9239\n"..., 3838) = 3838

因此它似乎在调用write(而不是某些mmap或其他魔法),因此应该起作用。

但是当我运行时:IOTHROTTLE_DEBUG=1 iothrottle -o 1M seq 10000 >/dev/null我得到:

init called: default read_limit=0, write_limit=0
IOTHROTTLE_READ=0
IOTHROTTLE_WRITE=1048576
Final read_limit=0, write_limit=1048576
allowed: 608 written: 0
allowed: 617 written: 0

这告诉我iothrottle仅拦截了 2 次调用write。

我错过了什么?

shared-library
  • 1 1 个回答
  • 38 Views

1 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-12-30T15:24:18+08:002024-12-30T15:24:18+08:00

    您iothrottle可以通过劫持 C 库的函数来完成工作,这些函数最终会执行诸如write()、pwrite()或splice()² 之类的系统调用。

    strace跟踪系统调用,而不是动态库函数调用,ltrace在 GNU 系统上您需要动态库函数调用(ltrace也可以使用 跟踪系统调用-S;在其他系统上,等效命令如truss或tusc(HP/UX)也可以同时执行这两项操作)。

    以下是来自zshDebian 的内容:

    $ ltrace seq 10 |& grep -e{write,put,send}
    fwrite_unlocked("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 21, 1, 0x7f5b1d7185c0) = 1
    
    $ ltrace -S seq 10 |& grep -e{write,put,send}
    fwrite_unlocked("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 21, 1, 0x7fe86c4785c0 <unfinished ...>
    <... fwrite_unlocked resumed> )                  = 1
    write@SYS(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 211
    

    seq正在调用fwrite_unlocked()您未劫持的 stdio 函数,fwrite()这不能解释为什么您的iothrottle操作对其无效。

    $ nm -uD  =seq | grep -e{write,put,send}
                     U fputc_unlocked@GLIBC_2.2.5
                     U fputs_unlocked@GLIBC_2.2.5
                     U fwrite@GLIBC_2.2.5
                     U fwrite_unlocked@GLIBC_2.2.5
    

    显示一些需要的-u未定义的-D动态符号seq(=seq可以在其他 shell 中写入"$(command -v seq)")。

    在动态符号的环境中调用seq,LD_DEBUG=bindings显示关于在哪里为谁找到什么符号的信息,这也可以有所帮助:

    $ LD_PRELOAD=$PWD/iothrottle.so IOTHROTTLE_WRITE=1000 LD_DEBUG=bindings seq 10  |& grep -e{write,put,send,iothrot}
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `init'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_pread'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_write'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_pwrite'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_copy_file_range'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_fwrite'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_writev'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_fflush'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_readv'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_sendfile'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_splice'
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__cxa_finalize' [GLIBC_2.2.5]
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `original_read'
         14982: binding file .../iothrottle.so [0] to seq [0]: normal symbol `stderr' [GLIBC_2.2.5]
         14982: calling init: .../iothrottle.so
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `clock_gettime' [GLIBC_2.17]
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `getenv' [GLIBC_2.2.5]
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strtoull' [GLIBC_2.2.5]
         14982: binding file seq [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `fwrite_unlocked' [GLIBC_2.2.5]
         14982: binding file seq [0] to .../iothrottle.so [0]: normal symbol `fflush' [GLIBC_2.2.5]
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `dlsym' [GLIBC_2.34]
         14982: binding file .../iothrottle.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `fflush'
         14982: binding file .../iothrottle.so [0] to .../iothrottle.so [0]: normal symbol `throttle'
    

    ¹ 或者可能最终像 stdio 那样,通常只填满一些缓冲区而不执行任何 I/O,直到这些缓冲区被刷新。

    ² 顺便说一句,还有更多诸如send()、、之类的函数也可以执行一些 I/O 操作sendto(),并且sendmsg()还有更多 stdio 函数可以执行一些操作,write()例如fput()、、......putchar()printf()

    • 1

相关问题

  • “未使用的直接依赖项”是什么意思?

  • Mint 19 - Pidgin IM - 启动时出错:libpurple.so.0:无法打开共享对象文件

  • 只要版本相同,共享库 ABI 是否兼容?

  • 安装到系统路径时如何安装共享库?

  • Pandoc 缺少库文件 [关闭]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve