在Linux中读写Pseudo Terminal的问题

时间:2012-10-26 05:33:46

标签: c++ c linux mono pty

我正在编写一个与外部进程交互的C ++程序。外部进程用C#编写,并在单声道上运行。请注意,我不能修改C#代码,因为它不是我编写的程序。

在这方面,我首先使用管道开始,当然我后来意识到它是完全缓冲的,因此我遇到了很多同步问题。本质上,外部进程必须在每次写入后刷新其输出,这是不可能的。

接下来我要尝试的是文件,但是我发现在我的情况下使用伪终端会更容易。以下是我编写的一些示例代码:

int main()
{
    int fdm, fds, rc, pid;
    bool rValue;
    /* Setup Master pty*/
    rValue = rValue && (fdm = posix_openpt(O_RDWR)) >= 0 &&
             (rc = grantpt(fdm)) == 0 && (rc = unlockpt(fdm) == 0);
    if (rValue) {
        /* Open Slave pty */
        fds = open(ptsname(fdm), O_RDWR);
        pid = fork();
        if(pid < 0)
            perror("fork failed");
        else if(pid == 0) //child
        {
            close(fdm); //close master
            struct termios slave_orig_term_settings;
            struct termios new_term_settings;
            tcgetattr(slaveTTY, &slave_orig_term_settings);
            new_term_settings = slave_orig_term_settings;
            cfmakeraw(&new_term_settings);
            tcsetattr(slaveTTY, TCSANOW, &new_term_settings);

            //redirect I/O of this process
            close(0);
            close(1);
            close(2);
            dup(slaveTTY);
            dup(slaveTTY);
            dup(slaveTTY);

            close(slaveTTY);

            setsid();
            ioctl(0, TIOCSCTTY, 1);

            //launch the external process and replace its image in this process
            execve(argv[0],...);
        }
        else
        {
            close(fds); //close slave
            //Perform some interaction
            write(something using fdm);
            //Assume fdsets declared and set somewhere here
            select(fdm +1,&fdset,NULL,NULL,NULL);
            int readBytes = read(someting using fds);
        }
    }
    return EXIT_SUCCESS;
}

假设正在处理select的fdset和fdclr。

在父流程中观察到以下问题:

  1. 有时读取返回readBytes&gt; 0但缓冲区中没有任何内容
  2. 有时写回终端的内容会被回读
  3. 某些垃圾值,例如^]] 49] 1R正在转储终端(这是实际的终端,即我的输出窗口)
  4. P.S:当外部进程用C / C ++编写时,不会出现此问题。只有当我以单声道运行C#程序时才会这样做。

1 个答案:

答案 0 :(得分:0)

我认为如果您不必在C++中执行此操作,python中的pexpect是一个不错的选择,它将为您节省大量时间。此外,您还可以使用pyinstaller之类的python冻结工具将您的python脚本转换为独立的二进制文件。