go - golang 中的终端 : syscall vs os/exec stty

标签 go terminal system-calls stty

这是在 go 中使用系统调用获得 (POSIX) 终端大小的方法:

func getTermDim() (width, height int, err error) {
    var termDim [4]uint16
    if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(0), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&termDim)), 0, 0, 0); err != 0 {
        return -1, -1, err
    }
    return int(termDim[1]), int(termDim[0]), nil
}

现在,同样的事情,用 os/exec 调用 stty:
func getTermDim() (width, height int, err error) {
        cmd := exec.Command("stty", "size")
        cmd.Stdin = os.Stdin
        var termDim []byte
        if termDim, err = cmd.Output(); err != nil {
                return
        }
        fmt.Sscan(string(termDim), &height, &width)
        return
}

在实践中,第一个解决方案可能会变得非常繁重和不可读,当必须将终端置于原始模式、设置选项等时。当一个人习惯于 stty(例如在 shell 脚本中)时,第二个解决方案要容易得多!

所以我的问题是:使用第一个解决方案有什么好处?是速度吗?是不是我们不能依赖主机上安装stty命令?还有什么我没想到的吗?

简而言之,使用 stty 与系统调用的“风险”或“成本”是多少?

最佳答案

关于风险:

  • stty : 如果 stty,您的程序将无法正常运行命令在 $PATH 中不可用| .或者如果 stty $PATH 中的命令不是您期望的(这可能是一个安全问题)。或者,如果程序在占用空间极小的 Docker 容器中运行:您必须输入 stty在图像中。
  • 系统调用:您的程序依赖于操作系统。只要您将该函数写在受 build tags 保护的文件中就可以了以确保在不受支持的操作系统上构建将在编译时失败。

  • 关于性能,就写个benchmark使用包testing .但我已经可以告诉你 exec.Command意味着多个系统调用比 IOCTL 成本高得多/TIOCGWINSZ .

    关于go - golang 中的终端 : syscall vs os/exec stty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50986225/

    相关文章:

    file - 通过多次追加来检索写入文件的 gob

    go - 根据 Golang 中 hashmap 的值获取键的简单方法

    java - SSH 服务器应该向客户端发送什么作为对用户按退格键的响应?

    ffmpeg concat 过滤器正在丢弃第二个视频的第一秒

    linux - 如何查找程序使用了哪种类型的系统调用

    c - 为什么 mkdir() 和 rmdir() POSIX 系统调用在不同的头文件中?

    templates - 在你的 go 二进制文件中包含模板/html 文件

    linux - 如何通过 ssh 或 telnet 将终端大小更改发送到命令行应用程序?

    c - c 中的简单 shell : waitpid system call not working

    go - 在运行时以编程方式创建结构 - 可能吗?