关于PeekNamedPipe的问题??

lanlansky 2002-08-24 12:20:11
以下小弟使用创建子进程,或对其输出重定向
但是有点问题
Sleep(500);/////////************问题点************
当初没加这句话

导致cntReadedChar 是零,也就使得szMessage 成了只有[\0]的数组
没有得到子进程的输出

谁讲讲这是为什么?

{
SECURITY_ATTRIBUTES lsa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE hReadPipe, hWritePipe;
char szOutput[DEFAULT_BUFFER_LEN+10];
DWORD cntReadedChar=0;


lsa.nLength = sizeof(SECURITY_ATTRIBUTES);
lsa.lpSecurityDescriptor = NULL;
lsa.bInheritHandle = TRUE;

if(!CreatePipe(&hReadPipe, &hWritePipe, &lsa, 0))
{
printf("CreateProcess error!\n");
return FALSE;
}

memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hWritePipe; //use to redirect

if(!CreateProcess(NULL,"core", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
printf("CreateProcess error!\n");
return FALSE;
}

Sleep(500);/////////************问题点************
if(!PeekNamedPipe(hReadPipe, szOutput, 1, &cntReadedChar, NULL, 0)) //CONFIRM IF HAVE SOME OTHER OUTPUT STRING
printf("no output!!\n");
printf("%d\n",cntReadedChar);
if(cntReadedChar) //HAVE UN-READED THING
{
if(!ReadFile(hReadPipe, szOutput, DEFAULT_BUFFER_LEN, &cntReadedChar, NULL))
szOutput[cntReadedChar] = '\0';
}
else
if(WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0)
Sleep(1000);


strcpy(szMessage , szOutput);
printf("%s\n",szOutput);


CloseHandle(hReadPipe);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(hWritePipe);
return TRUE;
}
...全文
2943 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
snsins 2002-08-25
  • 打赏
  • 举报
回复
我没试过,但是你把
(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0);
写到循环外面来

循环体里面就负责PeekNamePipe,一旦管道里有了数据,马上跳出循环
除非你你的管道里一直没有数据可读
不然怎么会死循环?
不过你上面不是说可以读出管道里的数据吗?
这样根本不可能死循环的
lanlansky 2002-08-25
  • 打赏
  • 举报
回复
to snsins:你试过那样么?那样会死循环的
象这样
while(1)
{
if(!PeekNamedPipe(hReadPipe, chrOutput, 1, &cntReadedChar, NULL, 0)) //CONFIRM IF HAVE SOME OTHER OUTPUT STRING
// Sleep(100);
if(cntReadedChar) //HAVE UN-READED THING
{
if(!ReadFile(hReadPipe, chrOutput, DEFAULT_BUFFER_LEN, &cntReadedChar, NULL))
{break;}
chrOutput[cntReadedChar]='\0';
}
else //HAVE nothing
if(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0) //and child process is end
{break;}
}



to Sustain:你的一样死循环
snsins 2002-08-25
  • 打赏
  • 举报
回复
fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);

dwWritten得到值是多少?
WriteFile成功了吗?

今天家里停电
我在网吧
等晚上我回家后来电了给你调试调试
lanlansky 2002-08-25
  • 打赏
  • 举报
回复
WaitForSingleObject 什么时候 返回 WAIT_OBJECT_0

The state of the specified object is signaled
是什么意思?
signaled怎么解释?
lanlansky 2002-08-25
  • 打赏
  • 举报
回复
chBuf---你可以自己负点值
lanlansky 2002-08-25
  • 打赏
  • 举报
回复
// The code for the child process.

#include <windows.h>
#define BUFSIZE 4096

VOID main(VOID)
{
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL fSuccess;

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if ((hStdout == INVALID_HANDLE_VALUE) ||
(hStdin == INVALID_HANDLE_VALUE))
ExitProcess(1);

fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
}


你说说哪有问题?


我第一贴的内容就可以算是父进程,你把两个程序编译一下,看看时不是死循环,把子进程的名字启为core
snsins 2002-08-25
  • 打赏
  • 举报
回复
这段写在父进程中,不死循环才怪,PeekNamedPipe一直被执行,子进程根本得不到cpu,他怎么结束,
================================================================

一个新进程被创建后,父进程基本上就与他无关了,新的进程是一个独立的进程
有自己的地址空间,他得不得CPU时间是系统的问题,与父进程根本没关系
snsins 2002-08-25
  • 打赏
  • 举报
回复
你说的子进程究竟是什么东西?
是线程还是进程?
如果是开始你用CreateProcess创建了一个新进程
那么这个进程创建后得不得到CPU根本与创建他的父进程无关,

是你自己写的程序有问题吧

我上面贴了我的那个完整例子,不知道你看懂了没有
就是创建一个CMD.EXE的进程,然后接管了CMD.EXE的输入和输出
并不存在你说的什么得不到CPU的情况

我那程序运行得一直很好



lanlansky 2002-08-25
  • 打赏
  • 举报
回复
“我没试过,但是你把
(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0);
写到循环外面来


靠!哥哥,你还是动手试试看吧!
光说是没用的!
while(1)
{
PeekNamedPipe(hReadPipe, chrOutput, 1, &cntReadedChar, NULL, 0);
if (cntReadedChar)
break;
}
WaitForSingleObject(pi.hProcess, INFINITE);

这段写在父进程中,不死循环才怪,PeekNamedPipe一直被执行,子进程根本得不到cpu,他怎么结束,当然pipe中没东西,也就一直死循环
In355Hz 2002-08-25
  • 打赏
  • 举报
回复
好像Pipe没有对应的阻塞读出的函数吧,ReadFile和PeekNamedPipe的区别只是后者读完后不会抹掉pipe里的数据。
退一步,即使有阻塞读出的函数,仍然不能避免让主进程在读取Pipe时失去响应。
一般的解决方法是创建一个负责从Pipe中读出数据的子线程,线程函数就像snsins写的那样,用循环来模拟阻塞的方式读出Pipe中数据。
还有一个方法是写一个消息泵,来保证主进程的窗口能载读取时获得消息,如:
while(1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

PeekNamedPipe(hReadPipe, chrOutput, 1, &cntReadedChar, NULL, 0);
if (cntReadedChar)
...

if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, 0))
break;
}
lanlansky 2002-08-25
  • 打赏
  • 举报
回复
请将结果发到myMailSpace@163.com
snsins 2002-08-25
  • 打赏
  • 举报
回复
除非你的管道里一直没有数据
snsins 2002-08-25
  • 打赏
  • 举报
回复
while(1)
{
PeekNamedPipe(hReadPipe, chrOutput, 1, &cntReadedChar, NULL, 0);
if (cntReadedChar)
break;

}
................
WaitForSingleObject(pi.hProcess, INFINITE);
.............
这样怎么会死循环?


snsins 2002-08-24
  • 打赏
  • 举报
回复
建议你去掉那个sleep(500)
采用一个循环来调用PeekNamePipe判断
snsins 2002-08-24
  • 打赏
  • 举报
回复
static void WINAPI ThreadProc(void* pVoid)
{
WSADATA wsa;
SOCKET serverFD;
char Buff[1024];


WSAStartup(MAKEWORD(2,2),&wsa);//初始化套接字

serverFD = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

struct sockaddr_in server;

server.sin_family = AF_INET;
server.sin_port = htons(iport);
server.sin_addr.s_addr=ADDR_ANY;
int ret=bind(serverFD,(sockaddr *)&server,sizeof(server));
ret=listen(serverFD,4);
int iAddrSize = sizeof(server);

re: SOCKET clientFD=accept(serverFD,(sockaddr *)&server,&iAddrSize);
SECURITY_ATTRIBUTES sa;
sa.nLength=12;
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=true;
HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;

ret=CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0); ret=CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0);

STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = hReadPipe2;
si.hStdOutput = si.hStdError = hWritePipe1;
char cmdLine[] = "cmd.exe";
PROCESS_INFORMATION ProcessInformation;
ret=CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);

unsigned long lBytesRead;

while(1)
{
ret=PeekNamedPipe(hReadPipe1,Buff,1024,&lBytesRead,0,0);
if(lBytesRead)
{
ret=ReadFile(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);
if(!ret)
break;
ret=send(clientFD,Buff,lBytesRead,0); if(ret<=0)
break;
}
else
{
lBytesRead=recv(clientFD,Buff,1024,0);
if(lBytesRead<=0)
break;
ret=WriteFile(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);//
send(clientFD,Buff,lBytesRead,0);//这一句就是增加命令回显功能,在标准TELNET里,输入的命令是没有回显的,加了这一句就有了回显功能
if(!ret) break;
}
}
goto re;//这一句作用是当客户端断开连接后可以连接

return;
}


我的代码,给你参考参考
至于PeekNamePipe是用来看管道里是否有数据可读,
Sustain 2002-08-24
  • 打赏
  • 举报
回复
>to Sustain(支点) :haha那样和直接写Sleep(1000)有什么区别?
不一样,我的是等待直到结束。

>有没有和PeekNamedPipe个功能相似,而阻塞的函数?
不明白你要阻塞函数干嘛?你的意思是把管道堵住,直到水流过来???
snsins 2002-08-24
  • 打赏
  • 举报
回复
你用的是if(WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0)

根本就没等待
第二个参数是等待时间
你也可以设置一个时间
让WaitForSingleObject在规定的时间内返回

DWORD reason=WaitForSingleObject(pi.hProcess, 5000);
if reason==WAIT_OBJECT_0
{
MessageBox("OK!");
}
if reason==WAIT_TIMEOUT
{
//说明在规定的时间内子进程没有结束
}
snsins 2002-08-24
  • 打赏
  • 举报
回复
if(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0)
{
}
这样就可以知道子进程是不是结束了

INFINITE是一直等待到子进程结束的意思
lanlansky 2002-08-24
  • 打赏
  • 举报
回复
用WaitForSingleObject 不能知道子进程是否结束么?


to Sustain(支点) :haha那样和直接写Sleep(1000)有什么区别?
lanlansky 2002-08-24
  • 打赏
  • 举报
回复
to snsins:
那其实跟我原来的那个区别不大,我那个子进程只需要很短的时间就会返回,坐不做循环,不作也不会有什么问题
我的那个已经可以成功得到输出

现在只是想对PeekNamedPipe WaitForSingleObject
由进一步的了解,msdn看的不是很明白
加载更多回复(6)

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧