以下是使用syscall在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对syscall的“风险”或“成本”是什么?
发布于 2020-12-01 09:44:02
发布于 2022-09-28 18:45:40
很可能,如果盒子上存在stty,那么syscall也会出现。似乎它和论点TIOCGWINSZ都是SVR4标准的一部分,这个标准可以追溯到20年前,并且在任何地方都是由Unixes广泛实现的,所以您不太可能需要针对不同OSes的变体代码,ioctl也是可移植的。
当然,运行stty更容易读懂,但是您正在运行一个单独的进程,这需要付出一定的代价。
它速度更慢,成本更高:操作系统正在启动一个新的进程上下文并加载二进制文件;您的代码不仅生成多个系统,而且运行的进程也是如此。
它还伴随着一系列的安全问题。也许您在path上找到的stty是用户放置在其中的一个,这只是一个例子;如果您嵌入了一个路径,那么对于这个特定的操作系统来说可能是错误的)。
https://stackoverflow.com/questions/50986225
复制相似问题