首页
社区
课程
招聘
[求助]LPC的疑惑(附源码)
发表于: 2012-1-19 01:13 8032

[求助]LPC的疑惑(附源码)

2012-1-19 01:13
8032
1.exe --->服务端
2.exe---->客户端

1.exe中的两个线程:
ServerProc: LPC线程 监听新连接
Func: 服务线程 与客户端提供LPC服务

2.exe只有一个线程,就是请求LPC服务的线程

怎么都想不明白的问题。。。当LPC线程ServerProc再次进入NtListenPort准备接受新连接的时候

Func服务线程和2.exe中的客户端线程的通信就会挂起!

1:虽然ServerProc的NtListenPort和Func线程中的NtReplayReceivePort最终调用的是一个函数,但是属于不同的线程,为什么会相互影响呢

有没有达人帮看下,源码见附件,源码略微修改了nvtester大牛的源码。

2:LPC服务线程和客户端线程之间,如果要连续通信,到底要采用何种通信逻辑(API调用)呢

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 2
活跃值: (164)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
初步怀疑是内存访问互斥……但是还没有找到点……
2012-1-19 03:41
0
雪    币: 639
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
发现多线程编程思路还是有点混论,不过你定义了同步事件,貌似没有使用
func线程是在serverProc线程中启动,不知道是否有影响
2012-1-19 11:32
0
雪    币: 2
活跃值: (164)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这么简单清晰的思路你还说混乱,我不知道能说什么。
2012-1-19 11:42
0
雪    币: 2
活跃值: (164)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
看雪的牛人呢?快现身啊
2012-1-19 14:39
0
雪    币: 260
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
这两天在看和这相关的,我觉得LPC服务端接收信息处应该只能有一个线程,NtListenPort和NtReplayReceivePort最终会在同一个ServerPort上等待消息,先等待的会阻塞后等待的,连接和请求都是一个消息,仅仅是Type不同,应在一个线程中接收这些消息。
2012-1-20 15:59
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
问题在于:
1.cpp 189行        ::Sleep(2000);   
注释掉后应该正常。没有测试。大约看了下2个程序,应该是这里了
2012-1-31 10:10
0
雪    币: 2
活跃值: (164)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
如果没有这一句。。。服务线程会因为LPC线程listen而阻塞在监听的那一句……

通信不能成功
2012-2-1 04:30
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
简述下你的逻辑

    Status = NtListenPort(hListenPort,&(ReceiveMessage.Header));

      这句调用产生线程挂起等待客户连接。外围的do while 保证了循环监听。所以不存在需要Sleep的情况

       HANDLE hThread = (HANDLE)_beginthreadex(NULL,0,func,&ReceiveMessage,0,NULL);

      工作线程,去处理连接,应该要完成Accept来接受并使用Complete唤醒

问题一:
      
      如果没有Sleep那么fun线程得到的线程参数指针有可能被破坏,因为线程可能在执行时,调用者已经进入下一个do while循环,栈空间已被破坏。

问题二:

      很有可能,你会产生某个Message无法收到的问题。在你解决了问题1后,他的表现是LPC_REQUEST时发送者无法接受返回的消息而陷入等待。
2012-2-1 10:17
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
即便你Sleep 2s也可能发生异常。而LZ原本的问题,应该是楼上的问题1,问题2的综合表现
2012-2-1 10:22
0
雪    币: 2
活跃值: (164)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢你的解答

问题1:栈破坏的问题,这个问题我试过,我在堆上申请内存(不delete)然后传递到服务线程(func)也是不行的(不sleep),应该不是这个问题

问题2:表现是如果Server线程进入到NtListenPort函数之后,服务线程func会在

        Status = NtReplyWaitReceivePort(hClinet,
            (PVOID*)&a,
            NULL,
            &m_ReceiveMessage.Header
            );


这一句挂起~

********************************************
原因猜测:
NtListenPort内部也是调用NtReplyWaitReceivePort的,所以可能跟这个有关

   但是即使是同一个函数,他们等待的端口一个是hListen(监听端口),一个是hClinet(通信端口),怎么会卡住呢?

   所以我猜测,hListen和hClinet虽然数值和含义都不同,但是可能两者是在同一个端口上等待,至于是哪一个我就搞不清楚了……
2012-2-1 21:02
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最近比较忙,贴段我的代码
BOOLEAN CPort::ListenPort(
	__in HANDLE hPortHandle,
	__in PPACKET PacketBuffer
	)
{
	NTSTATUS status;
	PVOID PortContext = NULL;

	status = m_pPoolObject->m_tSystemApis.NtReplyWaitReceivePortEx(
		hPortHandle,
		(PVOID *)&PortContext,
		(PPORT_MESSAGE)NULL,
		(PPORT_MESSAGE) PacketBuffer,
		&m_tTimePreListen
		);	

	if(status == STATUS_TIMEOUT) {
		return FALSE;
	}

	if ( !NT_SUCCESS(status) ) {
		return FALSE;
	}


BOOLEAN CPort::MessageLoop(
	__in HANDLE hPortHandle,
	__in PPORT_CLIENT_DESCRIPTOR ClientInfo,
	__in PPACKET PacketBuffer
	)
{
	NTSTATUS status;
	PVOID PortContext = NULL;

	//if(IsFlagOn(m_pPortObject->Flags, PORT_STATUS_DELETE_PEDING)) {
	//	return TRUE;
	//}

	//if(ClientInfo->ServerMode.IsTerminatePeding) {
	//	return TRUE;
	//}

	status = m_pPoolObject->m_tSystemApis.NtReplyWaitReceivePortEx(
		hPortHandle,
		(PVOID *)&PortContext,
		(PPORT_MESSAGE)NULL,
		(PPORT_MESSAGE) PacketBuffer,
		&m_tTimePreListen
		);	

	if(status == STATUS_TIMEOUT) {
		return FALSE;
	}

	if ( !NT_SUCCESS(status) ) {
		return FALSE;
	}


有空我编译下调试好在看看。
2012-2-2 16:24
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这2个函数都是在do while中调用。
2012-2-2 16:30
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
hListen以及hClinet被唤醒后都要对LPC的各种类型做处理
所以。我每个等待后都处理:
[CODE]

        __try
        {
                switch(PacketBuffer->Lpc.u2.s2.Type)
                {
                case LPC_CONNECTION_REQUEST:
                        // 处理链接请求
                        NewClientConnected(PacketBuffer,&PacketBuffer->Connect.Context);
                        break;
                        // 如果端口没有完全关闭,仅通讯端口关闭
                case LPC_PORT_CLOSED:
                        // 对方端口句柄关闭
                        {
                                CloseClientConnection(PacketBuffer, PortContext, LPC_PORT_CLOSED);
                                return TRUE;
                        }
                       
                case LPC_CLIENT_DIED:
                        // 通讯过程被结束,客户端才有的消息
                        {
                                CloseClientConnection(PacketBuffer, PortContext, LPC_CLIENT_DIED);
                                break;
                        }
                case LPC_DATAGRAM:
                        RecvMessage(PacketBuffer, PortContext, LPC_DATAGRAM);
                        break;
                case LPC_REQUEST:
                        RecvRequest(PacketBuffer, PortContext);
                        break;

                default:
                        //
                        // We received a message type we didn't expect, probably due to
                        // error.  BUGBUG - write an event
                        //
                        m_pPoolObject->PrintInfo("Message Loop # Unknow.\n");

                        break;
                }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
                //KdPrint(( "[DSW] Unexpected exception on LPC port: %08X\n",GetExceptionCode()));
        }
[CODE]
2012-2-2 16:32
0
游客
登录 | 注册 方可回帖
返回
//