gpt4 book ai didi

rust - 在ioctl中应该使用哪个文件描述符来了解终端屏幕的大小?

转载 作者:行者123 更新时间:2023-12-03 11:39:52 25 4
gpt4 key购买 nike

我想可靠地知道终端大小,即使应用程序在子 shell 中运行也是如此。
似乎唯一可行的方法是使用stdin fd,但是我想知道为什么有指向证明它的文档的链接。
有很多问题,例如为什么甚至要使用stdout(或stdin)fd来知道终端大小?

fn main() {
let mut size = winsize {
ws_row: 0,
ws_col: 0,
ws_xpixel: 0,
ws_ypixel: 0,
};
let fd = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")
.map(|file| file.as_raw_fd())
.unwrap()
;
unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) };
println!("/dev/tty cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdout cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDERR_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stderr cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDIN_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdin cols: {}, lines: {}", size.ws_row, size.ws_col);
}


我在鱼 shell 中运行了 echo (cargo run 2>&1)并得到了这个:
   Compiling test_term_size v0.1.0 (/home/m/code/test_term_size) warning: unused import: `File`  --> src/main.rs:2:15   | 2 | use std::fs::{File};   |               ^^^^   |   = note: `#[warn(unused_imports)]` on by default  warning: unused imports: `O_RDWR`, `open`  --> src/main.rs:4:5   | 4 |     O_RDWR,   |     ^^^^^^ 5 |     open, ioctl, winsize, STDIN_FILENO,   |     ^^^^      Finished dev [unoptimized + debuginfo] target(s) in 0.21s      Running `target/debug/test_term_size` /dev/tty cols: 0, lines: 0 stdout cols: 0, lines: 0 stderr cols: 0, lines: 0 stdin cols: 52, lines: 106
strace -e trace=ioctl,open target/debug/test_term_size
ioctl(3, TIOCGWINSZ, 0x7ffdb9805578) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
strace -e trace=ioctl,open cargo run
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/test_term_size`
ioctl(3, TIOCGWINSZ, 0x7ffea819b008) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
echo (strace -e trace=ioctl,open cargo run 2>&1)
ioctl(2, TCGETS, 0x7ffdae149cb0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149540) = -1 ENOTTY (Inappropriate ioctl for device) warning: unused import: `File` --> src/main.rs:2:15 | 2 | use std::fs::{File}; | ^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused imports: `O_RDWR`, `open` --> src/main.rs:4:5 | 4 | O_RDWR, | ^^^^^^ 5 | open, ioctl, winsize, STDIN_FILENO, | ^^^^ Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/test_term_size` ioctl(3, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++

最佳答案

TTY信息的正确来源始终是/dev/tty。不要使用stdin或任何其他怪异的技巧。这就是为什么它对您不起作用的原因:

let fd = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")
.map(|file| file.as_raw_fd())
.unwrap()
;

您正在打开/dev/tty并获取其FD,但是在使用该文件之前,先删除该文件,然后将其关闭,因此该文件上的ioctl会失败,并显示EBADF“错误的文件描述符”。要解决此问题,请在使用完FD之后,使文件保持 Activity 状态。

关于rust - 在ioctl中应该使用哪个文件描述符来了解终端屏幕的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61294762/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com