[线程][访问][同一]多线程访问同一文件怎么处理

09月 13th, 2008 by admin
Posted in VC/MFC | No Comments »

多线程访问同一文件怎么处理?

如果所有线程都是读文件,则和普通访问方式一样.如果牵扯到写操作,应该加锁,避免冲突.

可以考虑采用完成端口模式。IOCP

查看MSDN文档中的OVERLAPPED读写文件

首先,我认为这个问题与完不完成端口没什么关系。不应该“读写”和“线程”两个关键字一放在一起就想到完成端口。

其次,我同意imluda说的,如果有线程在读,有线程在写时,想要保证读取的线程能够读到完整数据,则要把读写线程用同步对象排队(条件允许的话用Windows消息也行,更方便。)

最后,即便是多个线程都是读取线程,按理说没有逻辑上的冲突,可以不用同步互斥。但是有物理上的冲突有没有想过啊?磁盘是靠一套机械的司服装置来驱动磁头读写的。多个线程同时读,张三和李四的读取位置会不同,但是它们读取的数据可能都是连续的。那么你说是让张三顺序的把数据读完,再跳转磁头,去读取李四的数据好啊?还是频频跳转磁头,来回来去的读好?哪个效率高?

引用 1 楼 ouyh12345 的回复:
加锁,避免冲突

哪来那么多理论

使用事件机制,每个写线程各自使用自己的事件,第二个写启动线程等待第一个写线程结束,依此类推.每个读线程在启动之后,要等待所有写线程的事件变成有信号的再读取数据.

引用 7 楼 paerxiushi 的回复:
使用事件机制,每个写线程各自使用自己的事件,第二个写启动线程等待第一个写线程结束,依此类推.每个读线程在启动之后,要等待所有写线程的事件变成有信号的再读取数据.

agree

引用 7 楼 paerxiushi 的回复:
使用事件机制,每个写线程各自使用自己的事件,第二个写启动线程等待第一个写线程结束,依此类推.每个读线程在启动之后,要等待所有写线程的事件变成有信号的再读取数据.

agree

Tags: , , ,

[文件][作为][线程]可以把EXE文件作为一个线程来启动吗

09月 13th, 2008 by admin
Posted in VC/MFC | No Comments »

我想启动一个EXE文件,但是只想把这个EXE文件作为一个进程的一个模块来启动.也就是说最好是把这个EXE文件作为原有进程的一个线程来启动,这种做法在技术上是可行的吗?有没有什么办法可以实现?

应该不可以。

可以.我试过把一个exe文件当作远程线程注入到其他的进程中去.进去是进去了,至于运行我就没试过了.远程线程的函数是CreateRemoteThread(),我只能提供这么多信息了.其他的也不太清楚了.

搞不懂楼主的最终用意。一个EXE程序运行后,就是系统中的单独一个进程,和启动它的进程是完全隔开的。

当然,可以

为什么非要当作一个线程呢?
可以把他创建成一个子进程
你要是想在进程之间传递数据么? 那样的话有很多种方法可以实现
进程是线程的载体不要把进程和线程弄混了~

引用 3 楼 jesterjy 的回复:
可以.我试过把一个exe文件当作远程线程注入到其他的进程中去.进去是进去了,至于运行我就没试过了.远程线程的函数是CreateRemoteThread(),我只能提供这么多信息了.其他的也不太清楚了.

操作是在进程内部完成的,可以不用CreateRemoteThread. 如果找到Exe的主线程入口地址是不是可以启动这个Exe? 原进程是一个线程全部挂起的进程,必要的时候可以改变原进程环境以及堆栈的状态,只要能够将后面一个Exe启动就可以了.

这个就没有了解了.可以自己试下.不好意思.

可以!

但一个远线程可以完成的

你需要,手动地完成新建进程的过程 从创建文件镜像开始 重定位 And so on

可以!

不是一个远线程可以完成的

你需要,手动地完成新建进程的过程 从创建文件镜像开始 重定位 And so on

这和将DLL文件注入到其它进程中运行没什么大差别,不同的只是要将exe文件的代码在远程进程中重定位.不少木马也是使用方法,不过多数只是将DLL注入(省却要将EXE文件注入到远程进程中要做的功夫).

引用 11 楼 WinEggDrop 的回复:
这和将DLL文件注入到其它进程中运行没什么大差别,不同的只是要将exe文件的代码在远程进程中重定位.不少木马也是使用方法,不过多数只是将DLL注入(省却要将EXE文件注入到远程进程中要做的功夫).

和DLL注入是完全不一样的,DLL注入你只要一个LoadLibrary(文件名)做为一个远线程就可以了

EXE你需要自己Load,而且通常都会以0×40000来对齐,所以要么宿主编译时就让出这个空间,要么目标EXE 重定位,而整个过程 目标EXE是完成不了的,需要你的另一个注入线程来完成

我试过把一个exe文件当作远程线程注入到其他的进程中去.
======================================
据我所知,远程线程注入只能是DLL,EXE文件根本就无法这样做。

应该可以,不过要处理很多东西

这有什么困难的
1。建造DLL工程,设计线程程序
2。编译完成后,将生成的文件改成*.exe形式(注:楼主只说是EXE文件,并没有说是可执行文件)
3。设计启动进程软件,利用LoadLibrary获得线程函数地址
4。启动线程

哈哈

我找到一段代码,干的事情是自己load Exe文件,然后用CreateProcess启动目标进程,在启动的时候让目标进程Suspend, 然后把自己的Exe文件覆盖到远进程的空间中,接着修改EBX,EAX,PEB等等.
问题是我的目标进程绝对不能一开始就Suspend, 那上面的办法可以吗? 有知道的大侠请指教!

不能

用CreateProcess启动不就双进程了么。

这做法让我想到了壳,假设loader.exe 来载入 zhuru.exe
loader中,先VirtualAlloc一段内存,然后往里写入代码,并跳转到该段代码起始处,该段代码作用如下:
模拟PE加载器,分析zhuru.exe,记下oep, 并将.text .data 等加载到当前内存,然后跳转到oep

不知可行否。。

引用 16 楼 zuoluoyun 的回复:
我找到一段代码,干的事情是自己load Exe文件,然后用CreateProcess启动目标进程,在启动的时候让目标进程Suspend, 然后把自己的Exe文件覆盖到远进程的空间中,接着修改EBX,EAX,PEB等等.
问题是我的目标进程绝对不能一开始就Suspend, 那上面的办法可以吗? 有知道的大侠请指教!

你说提僵尸进程,只是借壳生蛋

我想修改PE文件的标志及首选基地址,然后用LoadLibrary尝试让系统映射,然后查找Main方法的入口地址,并进行手工调用,应该是可行的。不过修改了首选基地址貌似地址映射会错误,如果不修改,不知道能不能在备选基地址中找到合适的映射地址,反正尽量用LoadLibrary来修正各个节的基地址比较好

各位可以用用Google浏览器,他的多标签是多进程不是多线程,跑出来的效果还真像exe当线程用
当然这也只是像而已,本质上来说,不可能把exe跑成子线程的

Tags: , , ,

[线程][线程][同步]主线程与子线程同步一个变量,主线程改变了变量值,子线程收不到

09月 3rd, 2008 by admin
Posted in VC/MFC | No Comments »

子线程的代码如下:
while( done <= end3)
{
len = fread(buf, sizeof(char), 10000, pFileRead);
if(len <= 0)
break;

ret = decodeMP3(&mp,buf,len,out,8192,&size);
if(firstbuf)
{
aufile->samplerate = freqs[mp.fr.sampling_frequency];
firstbuf = FALSE;
}
while(ret == MP3_OK)
{
samplesperframe = size/bytespersample;
write_audio_file(aufile, out, samplesperframe, 0);

ret = decodeMP3(&mp,NULL,0,out,8192,&size);
}
done+=len;
int t=100 * done/(end3);
::SendMessage(m_hwnde,WM_EB200WAVE,KaProOK,(long)t);
::EnterCriticalSection(&m_css);
m_lbreak=m_break;
::LeaveCriticalSection(&m_css);
if(m_lbreak)
break;
}

主线程的代码如下:
BOOL CPipe::StopThread()
{
if (tran)
{
::EnterCriticalSection(&m_css);
m_break=TRUE;
::LeaveCriticalSection(&m_css);
if (tran)
{
WaitForSingleObject(tran,INFINITE);
}
CloseHandle(tran);
tran=0;
return TRUE;
}
DeleteCriticalSection(&m_css);
return FALSE;
}

主线程通过改变变量m_break的值,通知子线程退出循环,并且WaitForSingleObject(tran,INFINITE)等待循环退出!
此时出现的问题是,为什么这个,变量值改变了,然而子线程的这个变量值没有改变,依然没有退出循环,因此主线程一直WaitForSingleObject(tran,INFINITE)等待,得不到通知?请高手帮忙!

主线程WaitForSingleObject时,程序假死,子线程什么也不会收到。

自己写一个等待同时处理消息的函数

SendMessage是阻塞模式的,换成PostMessage或SendNotifyMessage

补充一点,子线程里不需要使用m_lbreak,直接读m_break就可以了。因为m_break是布尔型的,基本类型,肯定不会生成不一致的数据。

学习

你可以看一下子线程的m_lbreak的值是不是true,是否运行到了你那句赋值语句

::SendMessage(m_hwnde,WM_EB200WAVE,KaProOK,(long)t);
SendMessage是等待消息处理完后返回,而这个时候主线程在WaitForSingleObject处挂起,无法处理消息,因此子线程一直等在SendMessage处。

如果消息的处理不是必须在这个时候,可以改为PostMessage。该方法发送消息后直接返回,子线程可以继续往下执行,
主线程会在StopThread执行结束后处理子线程发出的消息。

Tags:

[串口][编程][线程]串口编程中关于线程的问题

09月 3rd, 2008 by admin
Posted in VC/MFC | No Comments »

    我这几天学着使用API函数编写串口程序,用来接收工控机的数据,遇到了几个问题,希望大家帮帮忙。
    我想显示具体的数据,同时能够显示图像,就是GDI图形,好比那些炒股软件一样,随着数据的变化,图形也会发生变化。这能不能用基本对话框实现?还是必须使用单文档或者多文档?需不需要使用线程?  串口编程中关于线程的问题
    我看到一些资料,一般有一个主线程和一个辅助线程,主线程用来处理图像数据以及数据发送给工控机等等;辅助线程在后台执行,用来监视串口,如果有数据送来了就接收。这是不是意味着WriteFile()要写在主线程里,ReadFile()函数要写在辅助线程里?可是我看到有些资料里并没有在辅助线程里使用ReadFile()函数,那麽数据还怎么被接收到啊?

可以看一看宋宝华老师的一个例子。
http://dev.yesky.com/401/2308901.shtml

谢谢2楼,不过那个连接里面没有用到线程。是个最基本的串口通讯代码,我现在希望使用线程来编写

可以使用对话框程序。就在对话框里开个区域,画图就可以了。
有界面的程序,一般都要用到多线程。

WriteFile()要写在主线程里,ReadFile()函数要写在辅助线程里
正好相反,由于串口可以开辟这缓存 <32K,所以ReadFile()可以定时读取,速度很快,不用多线程
WriteFile()发送少量数据面bps足够大可以不用多线程,否则就要用多线程,以免程序假死机

可以参靠一个CSerialPort类呀

串口读写有几种方式,其中有一种是不需要等待的,不会产生假死的问题的,但是控制起来比较麻烦的。
至于使用多线程,最主要就是因为一般工业用都是同时多串口操作的,而且还牵涉到同步、对时等等问题,就必须用多线程了。
关于显示部分,如果不复杂的话也可以用对话框来实现,但是复杂的图形处理用对话框就不太方便了。

串口操作,一种是用mscom控件,这种相对简单,但是容易假死;另一种通过文件读写的方式,创建串口—打开串口—读写串口—-关闭串口,采用多线程很不错,辅助线程监听串口,主线程用与显示和用户交互,基本上用对话框就能解决

TO 2楼,那个例程怎么下不下来啊,你若下下来了能否发我一份:yccwt@qq.com  谢谢!

http://www.vckbase.com/document/viewdoc/?id=1734
这个例子也可以。。一看就懂。。。

Tags: , , ,

[线程][CreateThread][创建]主线程用CreateThread()创建一个子线程。子线程还在运行时主线程结束运行。这时子线程会继续运行么主线程还存在么所在进程会如何

08月 31st, 2008 by admin
Posted in VC/MFC | No Comments »

主线程用CreateThread()创建一个子线程。子线程还在运行时,主线程结束运行。这时子线程会继续运行么?主线程还存在么?所在进程会如何?

如果不是主线程,只是一个普通的父线程,他结束时,他的子线程会结束么?

只有启动进程时的主线程才是老大,其它子子孙孙都是子线程,没有区别,所以这些线程中的任何一个退出都不会影响别的线程。

但是为了安全性考虑,最好在结束主线程时把该结束的子线程都结束了,防止内存泄露和不必要的麻烦。

Tags: , , ,

[封装][线程][socket]我用类封装了线程和socket但是出了点问题,不知道如何修改

08月 31st, 2008 by admin
Posted in VC/MFC | No Comments »

class mysocket
{

private:
SOCKET mysock;
HANDLE hThread;

public:

mysocket(SOCKET mysock)
{
this->mysock = mysock;
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
int nbytes = 0;

char buf[100];

while(true)
{ //等待接受参数
nbytes = recv(this->mysock,buf,100,0);

buf[nbytes] = '';
printf("接受消息:%s
",buf);
}

return 0;
}

//启动线程
void run_Thread()
{
DWORD dwThreadid1;

this->hThread = CreateThread(NULL,NULL,this->ThreadProc,NULL,0,&dwThreadid1);
WaitForSingleObject(this->hThread,100);
}

//关闭socket,线程
void close()
{
closesocket(this->mysock);

CloseHandle(this->hThread);
}

};

this->hThread = CreateThread(NULL,NULL,this->ThreadProc,NULL,0,&dwThreadid1)问题就出在这里下面是错误提示
cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)
是不是要用函数指针?我不会解决请帮我改一下谢谢

刚刚没说清楚,我不想用静态函数,可以用函数指针传递吗?请指点

你的线程函数写得不对,应该按如下形式写:
void mysocket::MyThread()
{
    int nbytes = 0;

    char buf[100];

    while(m_bRun) //这里将你的true最好是改成用一个变量控制,这样停止线程时只要将m_bRun设置为false这样线程会自己终止,一般不赞成直接杀线程。
    { //等待接受参数
        nbytes = recv(this->mysock,buf,100,0);

      buf[nbytes] = '';
      printf("接受消息:%s
",buf);
      sleep(50);//最好是sleep一下,要不你的CPU占用率太高了
    }
}
DWORD WINAPI ThreadProc(LPVOID pPara)
{
    mysocket* pSck = (mysocket*)pPara;
    pPara->MyThread();
    return NULL;
}

线程函数只能是静态成员函数或全局函数

谢谢

Tags: , , ,

[线程][运行][线程]关于线程运行和线程内核对象的关系

08月 31st, 2008 by admin
Posted in VC/MFC | No Comments »

每个线程都有其内核对象,内核对象中有对线程引用的计数。当用GetCurrentThread()等函数或取线程句柄时,计数就会增加;当用CloseHandle()释放线程句柄时,计数就减少。计数减为0时,内核对象就被释放。

那么这个内核对象的计数和线程的运行有什么关系?
若计数减为0时,线程还没运行完,系统会怎么处理?

引用 1 楼 jasonshark 的回复:
有两个计数,一个是CloseHandle可以减掉的,这个是HandleCount,另外还有一个总的PointerCount = HandleCount + ReferenceCount, ReferenceCount是内核里使用的,比如Scheduler要调度你的线程,就肯定得拿一个ReferenceCount, 这个是CloseHandle搞不掉的. 内核对象是否被释放看的是总的PointerCount,不是看HandleCount

学习了!

GetCurrentThread() 获取的线程句柄 是个伪句柄,并不会增加计数,用CloseHandle来释放这个伪句柄,也不会影响计数。

当内核对象的引用计数为0时,系统会释放内核对象。
线程的内核对象含有 大部分管理该线程的系统信息,如线程的退出码,线程的挂起计数等等。

当线程退出时,会对线程内核对象做如下事情:将内核对象的状态变为有信号,设置线程的退出码,引用计数减1。
内核对象不会被自动释放,除非所有指向该对象的外部指针都已经关闭,也就是说引用计数为0时,才释放。

不会出现“计数减为0时,线程还没运行”的情况。 线程在运行时,计数至少是1

回答的不错。学习了

那我对同一个句柄多次掉用closeHandle(),会有什么结果。HandleCount 会变为负的么?那PointerCount也有可能变成0了。

不会,CloseHandle以后句柄就失效了,也就没有从Handle到object的映射关系了,再CloseHandle会返回错误的. 这里说的都是实句柄, 伪句柄就更没关系了

Tags: ,

[双核][线程][同步]双核CPU的线程无法同步

08月 29th, 2008 by admin
Posted in VC/MFC | No Comments »

MFC程序
有一后台线程,会被多次调用,调用间隔不定,0.1s~0.8s左右,为避免线程未处理完毕又再次被调用导致多个线程同时访问共享资源
使用CCriticalSection类
CCriticalSection g_xxx;

UINT ProFun1(LPVOID lpParam)
{
  g_xxx.Lock()//进入临界区

  …..//do something,共享资源中包括一些全局变量

  g_xxx.Unock()//共享资源使用完毕,释放临界区

  return 0;
}
环境1:CPU双核  程序多次调用该线程,会导致死锁,后尝试CMutex,CEvent等同步类无果.
环境2:CPU单核  程序多次调用该线程,无死锁,长时间运行完全正常.
经多次检查程序不存在漏洞,2次对比唯一不同处就在于CPU的核数量. 跪求高人指教如何在双/多核心情况下进行线程同步!

可能是你的g_xx在你线程运行后才初始化
就像这样

HANDLE hThread = CreateThread(//….);
HANDLE hEvent = CreateEvent(//..);

没有源代码
只能这么猜测

等高人指教如何在双/多核心情况下进行线程同步

不懂,帮顶,不过记得核心编程第八章介绍过有关多核同步的问题。。

个人感觉跟几个cpu没啥关系

多跟踪吧

为什么会导致死锁呢?是因为其中一个线程在:
…..//do something,共享资源中包括一些全局变量
中,陷入了死循环?还是在这中,又申请了其他的互斥同步资源?

Tags: , , ,

[线程]多线程的问题

08月 28th, 2008 by admin
Posted in VC/MFC | No Comments »

process.h中的_beginthreadex与Windows.h中的CreateThread有什么区别?
它们适用于什么样的情况下?
如果要在双核或多核的情况下写多线程,应该怎么做?

CreateThread下层调用_beginthreadex实现多线程。
多处理器下面多线程程序多注意线程同步问题,因为这时是真正的多个线程同时运行。

_beginthreadex是C Run Time函数,相应地,它会对线程做一些CRT相关的初始化,而CreateThread是Windows的Api, 并不会知道CRT的存在.99%的多线程程序都不应该使用CreateThread来创建.

具体和更详细的请参考windows核心编程.

注意的应该看核心编程 里面讲的很清楚
注意线程的同步  和 不要随便  termaniteThread()

Tags: ,

[线程]多线程的问题

08月 28th, 2008 by admin
Posted in VC/MFC | No Comments »

process.h中的_beginthreadex与Windows.h中的CreateThread有什么区别?
它们适用于什么样的情况下?
如果要在双核或多核的情况下写多线程,应该怎么做?

CreateThread下层调用_beginthreadex实现多线程。
多处理器下面多线程程序多注意线程同步问题,因为这时是真正的多个线程同时运行。

_beginthreadex是C Run Time函数,相应地,它会对线程做一些CRT相关的初始化,而CreateThread是Windows的Api, 并不会知道CRT的存在.99%的多线程程序都不应该使用CreateThread来创建.

具体和更详细的请参考windows核心编程.

注意的应该看核心编程 里面讲的很清楚
注意线程的同步  和 不要随便  termaniteThread()

Tags: ,