时间片轮转的问题?

时间:2021-09-29 19:51:24
在多任务系统中(没有线程的概念),怎么在一个任务中,设计出类似于多线程的一个咚咚?是通过时间片轮转吧?应该怎么弄?

谢谢啦。。。。。

12 个解决方案

#1


没有线程的概念,总有任务的概念吧!差别不大吧?

#2


进程模拟线程,设定定时器。

不过这样耗费资源较大。

#3


现在的论题就是在一个任务之中,通过时间片轮转来模拟实现多线程的概念。。。

#4


没有线程的概念那么有进程么?
要是进程也没有了就不知道怎么模拟了……
多线程的关系就有同步(相应于进程)和竞争,单向的程序怎么能模拟那?

或者你说得是最简单的模拟,不需要实现任何线程功能,只需要时间片轮转的话,那么
你可以用sleep(500)这样的语法来实现时间片的效果。

#5


小弟的意思是这样的:

系统是多任务系统(具体是什么系统目前还不清楚).然后呢,这个系统呢,他只有进程,没有线程。而我要提供一个接口,调用者的进程里面调用我的函数。然后,我的这个函数里面又必须要有多个线程去工作才行。。。。因此,小弟就不知道该怎么办了???于是,想到了时间片轮转的办法。。。

曾经看到这样的帖子(程序如下),和我的想法有些相似哦,但是还是不能确定,我该怎么去做!?



#include "stdafx.h"

#include <stdio.h>
#include <time.h>
#include <memory.h>

typedef unsigned long (__stdcall *LPTHREAD_START_ROUTINE)(void * lpParameter);

struct
{
LPTHREAD_START_ROUTINE Routine;
void * lpParameter;
char RunState;
}ThreadList[10];

void _CreateThread(LPTHREAD_START_ROUTINE routine,void * lpParameter)
{
static char RunOnce='\1';

if(RunOnce=='\1')
{
RunOnce='\0';
memset(&(ThreadList[0]),0,sizeof(ThreadList));
}

int i;

for(i=0;i<10;i++)
{
if(ThreadList[i].Routine==NULL)
{
ThreadList[i].Routine=routine;
ThreadList[i].lpParameter=lpParameter;
return;
}
}
}

typedef struct
{
unsigned long Data[2];
}_CallStack;


struct
{
time_t ExecuteTime;
_CallStack ReturnAddress;
}ThreadAttemper[10];


static time_t NowTime=0;
_CallStack SystemIdle()//调度函数
{
static char RunOnce='\1';
if(RunOnce=='\1')
{
RunOnce='\0';
memset(&(ThreadAttemper[0]),0,sizeof(ThreadAttemper));
}

_CallStack ret_address;
int i;
while(1)
{
//看看谁到了时间了
NowTime=time(NULL);
for(i=0;i<10;i++)
{
if(ThreadAttemper[i].ReturnAddress.Data[0]>0 && ThreadAttemper[i].ExecuteTime<NowTime)
{
ret_address=ThreadAttemper[i].ReturnAddress;
memset(ThreadAttemper[i].ReturnAddress.Data,0,sizeof(_CallStack));
return ret_address;
}
}

//到了这里就调度未执行的现成子程序subroutine
for(i=0;i<10;i++)
{
if(ThreadList[i].RunState=='\0' && ThreadList[i].Routine!=NULL)
{
ThreadList[i].RunState='\1';
ThreadList[i].Routine(ThreadList[i].lpParameter);//阻塞执行的,如果有_ThreadSleep则重入本程序
}
}

//如果一个都没有,那么应该实际的等时间
}

return ret_address;//到了这里就是错误的
}
void _ThreadSleep(unsigned long t)
{
int i;
unsigned long stack_addr;
_CallStack addr,ret_addr;
//获得返回的地方
__asm
{
mov eax,ebp;
mov stack_addr,eax;
}
memcpy(ret_addr.Data,(void *)stack_addr,sizeof(ret_addr));

NowTime=time(NULL);

for(i=0;i<10;i++)
{
if(ThreadAttemper[i].ReturnAddress.Data[0]==0)
{
ThreadAttemper[i].ReturnAddress=ret_addr;
ThreadAttemper[i].ExecuteTime=NowTime+t;
break;
}
}

addr=SystemIdle();//调度后知道该谁来执行了。
if(addr.Data[0]==0)//调度错误返回到调用者
addr=ret_addr;

//重置返回的地方
memcpy((void *)stack_addr,addr.Data,sizeof(ret_addr));
}



//---------------------------------------------------------------------
unsigned long __stdcall thread1(void * lpParameter)
{
for(int i=0;i<1000;i++)
{
_ThreadSleep(10);
printf("Thread %d第%d ...    \t%010d\n",(int)lpParameter,i,NowTime);
}
return 0;
}



unsigned long __stdcall thread2(void * lpParameter)
{
for(int i=0;i<1000;i++)
{
_ThreadSleep(15);
printf("Thread %d第%d ...    \t%010d\n",(int)lpParameter,i,NowTime);
}
return 0;
}



int main(int argc, char* argv[])
{
printf("Hello World!\n");

_CreateThread(thread1,(void *)1);
_CreateThread(thread2,(void *)2);

while(1)
SystemIdle();
return 0;
}



#6


高人指点阿...

#7


?

#8


是不是嵌入式os哦。
其实任务、进程、线程等,之间的界限不要话的太绝对了。
很多嵌入式os的任务其实就是通常概念的线程了,因为这种os其实没有所谓的保护模式,所有任务共用一个地址空间,因此资源都是共享的,这就很像线程的概念了。

具体怎么作,时间片轮转肯定是一个办法,但是也可以实现优先级抢占的模式,要灵活使用os提供的诸如信号量、事件等通信机制,并和os的任务调度结合。
你的os都不确定,现在其它就还说不清楚。

#9


同意楼上的说法,看看VxWorks的内核代码应该对你很有帮助.

#10


我是ST的os,我对于这个平台不熟悉。还是请高手指教?
另外,vxworks的内核代码哪里有啊?谢谢了。。。

#11


如果又vxworks得内核代码,俺也要一份,谢谢!

#12


mark!

#1


没有线程的概念,总有任务的概念吧!差别不大吧?

#2


进程模拟线程,设定定时器。

不过这样耗费资源较大。

#3


现在的论题就是在一个任务之中,通过时间片轮转来模拟实现多线程的概念。。。

#4


没有线程的概念那么有进程么?
要是进程也没有了就不知道怎么模拟了……
多线程的关系就有同步(相应于进程)和竞争,单向的程序怎么能模拟那?

或者你说得是最简单的模拟,不需要实现任何线程功能,只需要时间片轮转的话,那么
你可以用sleep(500)这样的语法来实现时间片的效果。

#5


小弟的意思是这样的:

系统是多任务系统(具体是什么系统目前还不清楚).然后呢,这个系统呢,他只有进程,没有线程。而我要提供一个接口,调用者的进程里面调用我的函数。然后,我的这个函数里面又必须要有多个线程去工作才行。。。。因此,小弟就不知道该怎么办了???于是,想到了时间片轮转的办法。。。

曾经看到这样的帖子(程序如下),和我的想法有些相似哦,但是还是不能确定,我该怎么去做!?



#include "stdafx.h"

#include <stdio.h>
#include <time.h>
#include <memory.h>

typedef unsigned long (__stdcall *LPTHREAD_START_ROUTINE)(void * lpParameter);

struct
{
LPTHREAD_START_ROUTINE Routine;
void * lpParameter;
char RunState;
}ThreadList[10];

void _CreateThread(LPTHREAD_START_ROUTINE routine,void * lpParameter)
{
static char RunOnce='\1';

if(RunOnce=='\1')
{
RunOnce='\0';
memset(&(ThreadList[0]),0,sizeof(ThreadList));
}

int i;

for(i=0;i<10;i++)
{
if(ThreadList[i].Routine==NULL)
{
ThreadList[i].Routine=routine;
ThreadList[i].lpParameter=lpParameter;
return;
}
}
}

typedef struct
{
unsigned long Data[2];
}_CallStack;


struct
{
time_t ExecuteTime;
_CallStack ReturnAddress;
}ThreadAttemper[10];


static time_t NowTime=0;
_CallStack SystemIdle()//调度函数
{
static char RunOnce='\1';
if(RunOnce=='\1')
{
RunOnce='\0';
memset(&(ThreadAttemper[0]),0,sizeof(ThreadAttemper));
}

_CallStack ret_address;
int i;
while(1)
{
//看看谁到了时间了
NowTime=time(NULL);
for(i=0;i<10;i++)
{
if(ThreadAttemper[i].ReturnAddress.Data[0]>0 && ThreadAttemper[i].ExecuteTime<NowTime)
{
ret_address=ThreadAttemper[i].ReturnAddress;
memset(ThreadAttemper[i].ReturnAddress.Data,0,sizeof(_CallStack));
return ret_address;
}
}

//到了这里就调度未执行的现成子程序subroutine
for(i=0;i<10;i++)
{
if(ThreadList[i].RunState=='\0' && ThreadList[i].Routine!=NULL)
{
ThreadList[i].RunState='\1';
ThreadList[i].Routine(ThreadList[i].lpParameter);//阻塞执行的,如果有_ThreadSleep则重入本程序
}
}

//如果一个都没有,那么应该实际的等时间
}

return ret_address;//到了这里就是错误的
}
void _ThreadSleep(unsigned long t)
{
int i;
unsigned long stack_addr;
_CallStack addr,ret_addr;
//获得返回的地方
__asm
{
mov eax,ebp;
mov stack_addr,eax;
}
memcpy(ret_addr.Data,(void *)stack_addr,sizeof(ret_addr));

NowTime=time(NULL);

for(i=0;i<10;i++)
{
if(ThreadAttemper[i].ReturnAddress.Data[0]==0)
{
ThreadAttemper[i].ReturnAddress=ret_addr;
ThreadAttemper[i].ExecuteTime=NowTime+t;
break;
}
}

addr=SystemIdle();//调度后知道该谁来执行了。
if(addr.Data[0]==0)//调度错误返回到调用者
addr=ret_addr;

//重置返回的地方
memcpy((void *)stack_addr,addr.Data,sizeof(ret_addr));
}



//---------------------------------------------------------------------
unsigned long __stdcall thread1(void * lpParameter)
{
for(int i=0;i<1000;i++)
{
_ThreadSleep(10);
printf("Thread %d第%d ...    \t%010d\n",(int)lpParameter,i,NowTime);
}
return 0;
}



unsigned long __stdcall thread2(void * lpParameter)
{
for(int i=0;i<1000;i++)
{
_ThreadSleep(15);
printf("Thread %d第%d ...    \t%010d\n",(int)lpParameter,i,NowTime);
}
return 0;
}



int main(int argc, char* argv[])
{
printf("Hello World!\n");

_CreateThread(thread1,(void *)1);
_CreateThread(thread2,(void *)2);

while(1)
SystemIdle();
return 0;
}



#6


高人指点阿...

#7


?

#8


是不是嵌入式os哦。
其实任务、进程、线程等,之间的界限不要话的太绝对了。
很多嵌入式os的任务其实就是通常概念的线程了,因为这种os其实没有所谓的保护模式,所有任务共用一个地址空间,因此资源都是共享的,这就很像线程的概念了。

具体怎么作,时间片轮转肯定是一个办法,但是也可以实现优先级抢占的模式,要灵活使用os提供的诸如信号量、事件等通信机制,并和os的任务调度结合。
你的os都不确定,现在其它就还说不清楚。

#9


同意楼上的说法,看看VxWorks的内核代码应该对你很有帮助.

#10


我是ST的os,我对于这个平台不熟悉。还是请高手指教?
另外,vxworks的内核代码哪里有啊?谢谢了。。。

#11


如果又vxworks得内核代码,俺也要一份,谢谢!

#12


mark!