gpt4 book ai didi

linux - 当pty [Pseudo terminal] slave fd设置被 "tcsetattr"改变时,master端如何不延迟的捕捉到这个事件?

转载 作者:IT王子 更新时间:2023-10-29 00:49:40 26 4
gpt4 key购买 nike

slave fd 被另一个应用程序(比如“A”)用作串口设备。

A 将设置其波特率/停止位等。我的应用需要此信息。

顺便说一句,有什么方法可以让只有主 fd 打开的进程收到所有 ioctl() 调用的通知吗?

最佳答案

是的,这是可能的(在 Linux 和 2004 之前的 FreeBSD 中),在数据包模式下使用 pty 并在其上设置 EXTPROcflags。

  • 数据包模式通过ioctl(master, TIOCPKT, &nonzero) 在主端启用。现在主端的每个读取都会产生一个数据包:无论在另一端写入什么,加上一个状态字节,说明从端的情况(“终端(即从端)的写队列被刷新")

  • 然而,这并不意味着主机立即知道从机端的变化,例如master 上的 select()不会在这些更改发生后立即返回,只有在有内容可读时才返回

  • 但是,在 pty 的本地标志字中设置 EXTPROC 之后 - 使用 tcsetattr() - select() 返回为一旦从属状态发生变化,然后就可以检查从属 termios - 直接通过我们在父进程中保持打开的从属 fd,或者,至少在 linux 上,简单地通过 tcgetattr()在主端。

  • 请注意,EXTPROC 会禁用 pty 驱动程序的某些部分,例如本地回显已关闭。

EXTPROC 没有被大量使用(here 是一个可能的用例),不是很便携并且根本没有记录(它至少应该在 linux termiostty_ioctl 联机帮助页)。查看 linux 内核源代码 drivers/tty/n_tty.c 我得出结论,slaves termios 结构中的任何更改都会使主端返回 select() - 但是tcsetattr() 不会改变任何东西。

编辑:为了响应下面 J.F. Sebastians 的请求,我给出了一个示例程序,应该清楚如何在 linux 机器上以数据包模式使用 EXTRPOC:

/* Demo program for managing a pty in packet mode with the slave's
** EXTPROC bit set, where the master gets notified of changes in the
** slaves terminal attributes
**
** save as extproc.c, compile with gcc -o extproc extproc.c -lutil
*/



#include <stdio.h>
#include <pty.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFSIZE 512

void main() {
int master; // fd of master side
pid_t pid;
if((pid = forkpty(&master, NULL, NULL, NULL))) { // we're parent
fd_set rfds, xfds;
int retval, nread, status = 0, nonzero = 1;
char buf[BUFSIZE];

ioctl(master, TIOCPKT, &nonzero); // initiate packet mode - necessary to get notified of
// ioctl() on the slave side
while(1) {
// set stdout unbuffered (we want to see stuff as it happens)
setbuf(stdout, NULL);

// prepare the file descriptor sets
FD_ZERO(&rfds);
FD_SET(master, &rfds);

FD_ZERO(&xfds);
FD_SET(master, &xfds);

// now wait until status of master changes
printf("---- waiting for something to happen -----\n");
select(1 + master, &rfds, NULL, &xfds, NULL);

char *r_text = (FD_ISSET(master, &rfds) ? "master ready for reading" : "- ");
char *x_text = (FD_ISSET(master, &xfds) ? "exception on master" : "- ");

printf("rfds: %s, xfds: %s\n", r_text, x_text);
if ((nread = read(master, buf, BUFSIZE-1)) < 0)
perror("read error");
else {
buf[nread] = '\0';
// In packet mode *buf will be the status byte , and buf + 1 the "payload"
char *pkt_txt = (*buf & TIOCPKT_IOCTL ? " (TIOCPKT_IOCTL)" : "");
printf("read %d bytes: status byte %x%s, payload <%s>\n", nread, *buf, pkt_txt, buf + 1);
}
if (waitpid(pid, &status, WNOHANG) && WIFEXITED(status)) {
printf("child exited with status %x\n", status);
exit(EXIT_SUCCESS);
}
}
} else { // child
struct termios tio;

// First set the EXTPROC bit in the slave end termios structure
tcgetattr(STDIN_FILENO, &tio);
tio.c_lflag |= EXTPROC;
tcsetattr(STDIN_FILENO, TCSANOW, &tio);

// Wait a bit and do an ordinary write()
sleep(1);
write(STDOUT_FILENO,"blah", 4);

// Wait a bit and change the pty terminal attributes. This will be picked up by the master end
sleep(1);
tio.c_cc[VINTR] = 0x07;
tcsetattr(STDIN_FILENO, TCSANOW, &tio);

// Wait a bit and exit
sleep(1);
}
}

输出会是这样的:

---- waiting for something to happen -----
rfds: master ready for reading, xfds: exception on master
read 1 bytes: status byte 40 (TIOCPKT_IOCTL), payload <>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: -
read 5 bytes: status byte 0, payload <blah>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: exception on master
read 1 bytes: status byte 40 (TIOCPKT_IOCTL), payload <>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: -
read error: Input/output error
child exited with status 0

一般来说,pty 的 master 端不需要是 tty(并且有一个关联的 termios 结构),但是在 Linux 下,它是(有一个共享的 termios >: 改变一端会同时改变两个 termios 结构。

也就是说,我们可以修改上面的示例程序,在master端设置EXTPROC,不会有任何区别。

据我所知,所有这些都没有记录在案,当然更难移植。

关于linux - 当pty [Pseudo terminal] slave fd设置被 "tcsetattr"改变时,master端如何不延迟的捕捉到这个事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21641754/

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