子进程stdin没有得到数据,由父进程发送
Posted
技术标签:
【中文标题】子进程stdin没有得到数据,由父进程发送【英文标题】:Child process stdin doesn't get data, sent by parent process 【发布时间】:2011-09-17 21:37:59 【问题描述】:父进程将字符串"Message\n"
写入子进程stdin。但是子进程没有收到它。代码哪里出了问题?
Qt 4.7.3
父进程代码:
// class TestParent : public QMainWindow
void TestParent::createChildProcess()
childProcess = new QProcess( this );
connect( childProcess, SIGNAL( started() ),
this, SLOT( childProcessStarted() ) );
connect( childProcess, SIGNAL( bytesWritten( qint64 ) ),
this, SLOT( bytesWritten( qint64 ) ) );
childProcess->start( "TestChild.exe", QProcess::ReadWrite );
void TestParent::writeToChildProcessOutput()
qint64 bytesWritten = childProcess->write( "Message\n" );
qDebug() << "ret: " << bytesWritten << " bytes written";
void TestParent::bytesWritten()
qDebug() << "slot: " << bytesWritten << " bytes written";
子进程代码:
// class TestChild : public QMainWindow
void TestChild::TestChild()
// QFile TestChild::input;
connect( &input, SIGNAL( readyRead() ),
this, SLOT( readInput() ) );
input.open( 0, QIODevice::ReadOnly ); // stdin
void TestChild::readInput()
QString line;
line.append( '(' );
line.append( QString::number( input.bytesAvailable() ) )
line.append( ')' );
line.append( input.readAll() );
list.append( line ); // add line to QListView
【问题讨论】:
TestChild 是 QProcess 吗?并且输入是 QIODevice,而不是子类? @Chris:不,TestChild - 子进程的主窗口对象。在父进程中,我们使用childProcess
对象创建子进程。我的错误:input
是 QFile,谢谢。
【参考方案1】:
没有办法在 Qt 事件循环中为 stdin/stdout 事件进行可移植的连接。以下适用于非 Windows 平台:
QSocketNotifier *n1 = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(n1, SIGNAL(activated(int)), this, SLOT(readInputChannel()));
QSocketNotifier *n2 = new QSocketNotifier(0, QSocketNotifier::Exception, this);
connect(n2, SIGNAL(activated(int)), this, SLOT(brokenInputChannel()));
“0”是文件描述符(stdin)。
我将使用上述方法,然后通过从标准输入读取并生成信号的阻塞线程在 Windows 上模拟类似的东西:
class StdinThread : public QThread
Q_OBJECT
signals:
void incomingData(QByteArray data);
public:
void run(void)
char buf[1024];
while (1)
int sz = fread(buf, 1, 1024, stdin);
if (sz == 0)
return;
emit incomingData(QByteArray(buf, sz));
;
那么,在子进程中:
StdinThread *t = new StdinThread(this);
connect(t, SIGNAL(incomingData(QByteArray)), this, SLOT(processInputData(QByteArray)));
connect(t, SIGNAL(finished()), this, SLOT(brokenInputChannel()));
t->run();
【讨论】:
+1。这很有帮助,谢谢。你不知道QProcess::write
(标准输入管道)是否适用于Windows?换句话说:我可以写子进程的标准输入吗?
是的,你可以。 Windows 支持管道。只需注意缓冲即可。【参考方案2】:
文档说QFile
永远不会发出信号readyRead()
。
但有一个私有类:QWinEventNotifier
in src/corelib/kernel/qwineventnotifier_p.h
(link) 可能与 GetStdHandle(STD_INPUT_HANDLE)
一起使用。
另一种选择是在专用线程内使用阻塞循环等待输入:
QTextStream cin(stdin, QIODevice::ReadOnly);
while(!cin.atEnd())
QString line = cin.readLine();
emit newLine(line);
您还可以查看其他 RPC 方法(例如 QLocalSocket
、QSharedMemory
)。
【讨论】:
谢谢,将尝试 QWinEventNotifier。但是问题仍然存在:我已经启动了一个计时器,每个 X 毫秒写入日志文件input.bytesAvailable()
,它总是写入0
。 bytesAvailable()
在这里的用法是否也不正确?
QSharedMemory
没有尝试。但是关于QLocalSocket
、QLocalServer
(Windows 中的命名管道):我仍然需要交换管道名称(每个QLocalServer
1 个)。除了标准输入/标准输出,还有其他简单的方法来发送管道名称吗?
1.您无法使用 C/C++ 标准库查看标准输入缓冲区,因此如果 Qt 也不允许这样做也就不足为奇了。 2.您可以将管道名称作为子流程参数发送。
我应该用什么来进行孩子->父母的交流?还在使用标准输出?
"然后您可以通过调用 write() 写入进程的标准输入,并通过调用 read()、readLine() 和 getChar() 读取标准输出。" (doc.qt.nokia.com/latest/qprocess.html)【参考方案3】:
我认为您需要做的是从实际的 QProcess 对象中读取数据(在本例中为 childProcess,如果我理解正确的话)。
注意QProcess实际上是QIODevice的子类,还要特别注意以下函数:
QProcess::setReadChannel()
QProcess::readAllStandardOutput()
您应该能够使用 QProcess 对象的 readyRead() 信号,而不是创建 QFile 来尝试读取标准输入。这不起作用的原因是您的 QFile 与您的 MainWindow 关联的进程,而不是您的子进程。
【讨论】:
没有。childProcess
是父进程中的控制对象。使用childProcess
对象父进程打印字符串到子进程的stdin
(TestParent::writeToChildProcessOutput()
)。子进程应该从stdin
读取该字符串。所以在子进程中QFile input
对象的readyRead()
信号应该被发射(但没有readyRead()
信号发射,TestChild::readInput()
槽没有被调用)。以上是关于子进程stdin没有得到数据,由父进程发送的主要内容,如果未能解决你的问题,请参考以下文章