Linux pty文件描述符读取超时失败

Linux pty文件描述符读取超时失败,linux,pty,termios,Linux,Pty,Termios,我试图在表示PTY的文件描述符上设置读取超时。我在termios中设置了VMIN=0和VTIME=10,我希望在有字符可用时返回,或者在没有字符可用时在一秒钟后返回。然而,我的程序永远处于读取调用中 PTY有什么特别的地方使它不起作用吗?是否有其他TERMIOS设置导致此功能正常工作?我在stdin文件描述符上尝试了相同的配置,它按预期工作 #define _XOPEN_SOURCE #include <stdio.h> #include <stdlib.h> #incl

我试图在表示PTY的文件描述符上设置读取超时。我在termios中设置了VMIN=0和VTIME=10,我希望在有字符可用时返回,或者在没有字符可用时在一秒钟后返回。然而,我的程序永远处于读取调用中

PTY有什么特别的地方使它不起作用吗?是否有其他TERMIOS设置导致此功能正常工作?我在stdin文件描述符上尝试了相同的配置,它按预期工作

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>

#define debug(...) fprintf (stderr, __VA_ARGS__)

static void set_term (int fd)
{
    struct termios termios;
    int res;

    res = tcgetattr (fd, &termios);
    if (res) {
        debug ("TERM get error\n");
        return;
    }

    cfmakeraw (&termios);
    termios.c_lflag &= ~(ICANON);
    termios.c_cc[VMIN] = 0;
    termios.c_cc[VTIME] = 10;        /* One second */

    res = tcsetattr (fd, TCSANOW, &termios);
    if (res) {
        debug ("TERM set error\n");
        return;
    }

}

int get_term (void)
{
    int fd;
    int res;
    char *name;

    fd = posix_openpt (O_RDWR);
    if (fd < 0) {
        debug ("Error opening PTY\n");
        exit (1);
    }

    res = grantpt (fd);
    if (res) {
        debug ("Error granting PTY\n");
        exit (1);
    }

    res = unlockpt (fd);
    if (res) {
        debug ("Error unlocking PTY\n");
        exit (1);
    }

    name = ptsname (fd);
    debug ("Attach terminal on %s\n", name);

    return fd;
}

int main (int argc, char **argv)
{
    int read_fd;
    int bytes;
    char c;

    read_fd = get_term ();

    set_term (read_fd);
    bytes = read (read_fd, &c, 1);
    debug ("Read returned\n");

    return 0;
}
定义源代码
#包括
#包括
#包括
#包括
#定义调试(…)fprintf(stderr、\uu VA\u ARGS\uuuu)
静态无效集_项(int-fd)
{
结构termios termios;
国际关系;
res=tcgetattr(fd和termios);
如果(res){
调试(“术语获取错误\n”);
回来
}
cfmakeraw(和termios);
termios.c_lflag&=~(ICANON);
termios.c_cc[VMIN]=0;
termios.c_cc[VTIME]=10;/*一秒*/
res=tcsetattr(fd、TCSANOW和termios);
如果(res){
调试(“术语集错误\n”);
回来
}
}
int get_术语(无效)
{
int-fd;
国际关系;
字符*名称;
fd=posix_openpt(O_RDWR);
如果(fd<0){
调试(“打开PTY时出错”);
出口(1);
}
res=赠款(fd);
如果(res){
调试(“授予PTY时出错\n”);
出口(1);
}
res=解锁(fd);
如果(res){
调试(“解锁PTY时出错\n”);
出口(1);
}
name=ptsname(fd);
调试(“将终端连接到%s\n”,名称);
返回fd;
}
int main(int argc,字符**argv)
{
int read_fd;
整数字节;
字符c;
read_fd=get_term();
设置术语(读取fd);
字节=读取(读取和c,1);
调试(“读取返回\n”);
返回0;
}

来自linux
pty
(7)手册页(斜体是我的):

伪终端(有时缩写为“pty”)是一对虚拟字符设备,用于 提供双向通信通道。通道的一端称为 主人另一端称为从机。伪终端的从属端提供 一种与传统终端行为完全相同的接口

但是,您的程序正在从主设备读取数据,不能期望主设备的行为与终端设备完全相同

如果您更改/展开
get\u term
的最后几行,则

int slave_fd =  open (name, O_RDWR); /* now open the slave end..*/
if (slave_fd < 0) {
   debug ("Error opening slave PTY\n");
   exit (1);
}

return slave_fd; /* ... and use it instead of the master..*/
int slave_fd=open(name,O_RDWR);/*现在打开从端*/
如果(从机fd<0){
调试(“打开从属PTY时出错”);
出口(1);
}
返回从站\u fd;/*。。。用它来代替大师*/

。。。您的示例程序将按预期运行。

当然,这就引出了一个问题:为什么Faz原始程序中的主程序上的tcsetattr()会成功,以及它到底实现了什么。我相信(但在任何地方都找不到)它设置了从终端属性。在任何情况下,只要读取在从端完成,示例程序中tcsetattr()使用的两个文件描述符中的哪一个不会对其行为产生任何影响。有关Solaris和Linux上主和从的区别的更多信息
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>

#define debug(...) fprintf (stderr, __VA_ARGS__)

static void set_term (int fd)
{
    struct termios termios;
    int res;

    res = tcgetattr (fd, &termios);
    if (res) {
        debug ("TERM get error\n");
        return;
    }

    cfmakeraw (&termios);
    termios.c_lflag &= ~(ICANON);
    termios.c_cc[VMIN] = 0;
    termios.c_cc[VTIME] = 10;        /* One second */

    res = tcsetattr (fd, TCSANOW, &termios);
    if (res) {
        debug ("TERM set error\n");
        return;
    }

}

int get_term (void)
{
    int fd;
    int res;
    char *name;

    fd = posix_openpt (O_RDWR);
    if (fd < 0) {
        debug ("Error opening PTY\n");
        exit (1);
    }

    res = grantpt (fd);
    if (res) {
        debug ("Error granting PTY\n");
        exit (1);
    }

    res = unlockpt (fd);
    if (res) {
        debug ("Error unlocking PTY\n");
        exit (1);
    }

    name = ptsname (fd);
    debug ("Attach terminal on %s\n", name);

    return fd;
}

int main (int argc, char **argv)
{
    int read_fd;
    int bytes;
    char c;

    read_fd = get_term ();

    set_term (read_fd);
    bytes = read (read_fd, &c, 1);
    debug ("Read returned\n");

    return 0;
}