⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edfscheduledlg.cpp

📁 进程的调度
💻 CPP
字号:
// EDFScheduleDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "EDFSchedule.h"
#include "EDFScheduleDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CEDFScheduleDlg 对话框




CEDFScheduleDlg::CEDFScheduleDlg(CWnd* pParent /*=NULL*/)
	: CExpandingDialog(CEDFScheduleDlg::IDD, pParent,IDC_DEFUALTBOX,IDC_EXPAND,
	_T("展开>>"),_T("简缩<<"))
	, m_bWorking(FALSE)
	, m_TaskName(_T(""))
	, m_Period(0)
	, m_CPUTime(0)
	, m_U(0)
	, m_Tid(-1)
	, m_TimeCounter(0)
	, m_TidNT(-1)
	, m_TimeCounterNT(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CEDFScheduleDlg::DoDataExchange(CDataExchange* pDX)
{
	CExpandingDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_NAME, m_TaskName);
	DDX_Text(pDX, IDC_PERIOD, m_Period);
	DDX_Text(pDX, IDC_CPUTIME, m_CPUTime);
	DDX_Control(pDX, IDC_CURTITLE, m_TCBTitle);
	DDX_Control(pDX, IDC_PROGRESS, m_TCBProgress);
}

BEGIN_MESSAGE_MAP(CEDFScheduleDlg, CExpandingDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_CREATE()
	ON_BN_CLICKED(IDC_RUN, &CEDFScheduleDlg::OnBnClickedRun)
	ON_BN_CLICKED(IDC_ADD, &CEDFScheduleDlg::OnBnClickedAdd)
	ON_BN_CLICKED(IDC_END, &CEDFScheduleDlg::OnBnClickedEnd)
	ON_WM_TIMER()
	ON_WM_DESTROY()
END_MESSAGE_MAP()


// CEDFScheduleDlg 消息处理程序

BOOL CEDFScheduleDlg::OnInitDialog()
{
	CExpandingDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标
	
	// TODO: 在此添加额外的初始化代码
	m_TCBProgress.SetBarColor(RGB(80,50,50));

	CreateBitmapCtrl();
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CEDFScheduleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CExpandingDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CEDFScheduleDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CExpandingDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CEDFScheduleDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CEDFScheduleDlg::OnOK()
{
	//CDialog::OnOK();
}

int CEDFScheduleDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!m_TSB.CreateEx(this,SBARS_SIZEGRIP))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);//这句很关键

	return 0;
}

void CEDFScheduleDlg::OnBnClickedAdd()
{
	UpdateData();
	if (Satisfy())
	{
		TCB *pTCB=new TCB;
		pTCB->TaskName=m_TaskName;
		pTCB->Period=m_Period;
		pTCB->CPUTime=m_CPUTime;
		pTCB->RemainTime=m_CPUTime;
		pTCB->nCount=0;
		pTCB->RemainTimeNT=m_CPUTime;
		pTCB->nCountNT=0;
		m_TCBPtrArray.Add(pTCB);
	}
	return;
}

BOOL CEDFScheduleDlg::Satisfy()
{
	if (m_Period<0||m_CPUTime<0||m_Period<m_CPUTime)
	{
		MessageBox(_T("CPU时间必须小于周期而且两者都不能小于零!"));
		return FALSE;
	}
	if (m_TaskName.IsEmpty())
	{
		MessageBox(_T("任务名称不能为空!"));
		return FALSE;
	}
	int Sum=m_TCBPtrArray.GetCount();
	TCB *pTCB=NULL;
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB*)m_TCBPtrArray.GetAt(i);
		if (m_TaskName==pTCB->TaskName)
		{
			MessageBox(_T("任务名称已存在!"));
			return FALSE;
		}
	}
	m_U+=m_CPUTime/m_Period;
	if (m_U>1)
	{
		MessageBox(_T("添加任务后CPU利用率大于零!"));
		m_U-=m_CPUTime/m_Period;
		return FALSE;
	}
	else
		return TRUE;
}

void CEDFScheduleDlg::OnBnClickedRun()
{
	int Sum=m_TCBPtrArray.GetCount();
	if (Sum<1)
	{
		MessageBox(_T("当前队列中没有任务"));
		return;
	}
	m_bWorking=TRUE;
	EnableCtrls();
	if (!SetTimer(CLOCK_TIMER, 1000, NULL))
	{
		MessageBox(_T("创建时钟失败!"));
		PostMessage(WM_QUIT);
		return;
	}
	
	//SelectTask();
	
	//以上是时间驱动的调度过程,形象的显示了某一时刻哪个任务正在执行。
	//下面进行一个非时间驱动的调度,以便把整个调度流程图绘制出来。
	ScheduleNotTimeDrived();
	m_BitmapCtrl.ReSetBitmap(m_ShowFlowBitmap);
}

void CEDFScheduleDlg::OnBnClickedEnd()
{
	m_bWorking=FALSE;
	KillTimer(CLOCK_TIMER);
	m_TimeCounter=0;
	CString strTitle;
	strTitle=_T("00:00:00");
	m_TSB.m_strTime=strTitle;
	m_TSB.SetTime();
	strTitle=_T("未进行调度");
	m_TCBTitle.SetWindowTextW(strTitle);
	m_TCBProgress.SetPos(0);
	ResetTask();
	EnableCtrls();
}

void CEDFScheduleDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (!m_bWorking)//不是处于调度状态
		;
	else
	{
		CString strTime,strH,strM,strC;//时,分,秒。
		if (m_TimeCounter/3600<10)
			strH.Format(_T("0%d"),(m_TimeCounter/3600)%24);
		else
			strH.Format(_T("%d"),(m_TimeCounter/3600)%24);
		if ((m_TimeCounter/60)%60<10)//分钟数
			strM.Format(_T("0%d"),(m_TimeCounter/60)%60);
		else
			strM.Format(_T("%d"),(m_TimeCounter/60)%60);
		if (m_TimeCounter%60<10)
			strC.Format(_T("0%d"),m_TimeCounter%60);
		else
			strC.Format(_T("%d"),m_TimeCounter%60);
		strTime.Format(_T("%s:%s:%s"),strH,strM,strC);
		m_TSB.m_strTime=strTime;
		m_TSB.SetTime();
		int nPos=0;
		nPos=m_TCBProgress.GetPos();
		nPos++;
		m_TCBProgress.SetPos(nPos);

		TCB * pTCB=NULL;
		if (m_Tid==-1)//CPU空跑
			SelectTask();
		else
		{
			pTCB=(TCB *)m_TCBPtrArray.GetAt(m_Tid);
			pTCB->RemainTime--;
			if (pTCB->RemainTime<=0)
			{
				pTCB->nCount++;
				pTCB->RemainTime=pTCB->CPUTime;
			}
			m_Tid=-1;
			SelectTask();
		}
		m_TimeCounter++;
	}
	CDialog::OnTimer(nIDEvent);
}

void CEDFScheduleDlg::SelectTask()
{
	int Sum=m_TCBPtrArray.GetCount();
	TCB * pTCB=NULL;
	double ET=LONG_MAX;//最早截止时间
	double SET=LONG_MAX;//下一个最早开始的任务的开始时间。
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		if (SET>((pTCB->nCount)*pTCB->Period))
			SET=(pTCB->nCount)*pTCB->Period;
		if ((pTCB->nCount*pTCB->Period)<=m_TimeCounter)//此刻在该任务的周期内
		{
			if (ET>((pTCB->nCount+1)*pTCB->Period))
			{
				ET=(pTCB->nCount+1)*pTCB->Period;//最早截止时间
				m_Tid=i;//选择最早截止时间的任务
			}
		}
	}
	StartToRun();
	return;
}

void CEDFScheduleDlg::StartToRun()
{
	TCB * pTCB=NULL;
	CString strTitle;
	if (m_Tid==-1)//CPU空跑
	{
		m_TCBProgress.SetRange(0,1);
		m_TCBProgress.SetPos(0);
		strTitle=_T("CPU空跑");
	}
	else
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(m_Tid);
		m_TCBProgress.SetRange(0,pTCB->CPUTime);
		m_TCBProgress.SetPos(pTCB->CPUTime-pTCB->RemainTime+1);
		strTitle.Format(_T("任务%s正在执行第%d秒"),pTCB->TaskName,int((pTCB->CPUTime) - (pTCB->RemainTime)+1));
	}
	m_TCBTitle.SetWindowTextW(strTitle);
}

void CEDFScheduleDlg::EnableCtrls()
{
	CButton *pBA=(CButton *)GetDlgItem(IDC_ADD);
	CButton *pBR=(CButton *)GetDlgItem(IDC_RUN);
	if (m_bWorking)
	{
		pBA->EnableWindow(FALSE);
		pBR->EnableWindow(FALSE);
	}
	else
	{
		pBA->EnableWindow(TRUE);
		pBR->EnableWindow(TRUE);
	}
	return;
}

void CEDFScheduleDlg::ResetTask()
{
	m_Tid=-1;
	m_TimeCounter=0;
	int Sum=m_TCBPtrArray.GetCount();
	TCB * pTCB=NULL;
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		pTCB->nCount=0;
		pTCB->RemainTime=pTCB->CPUTime;
	}
}

void CEDFScheduleDlg::OnDestroy()
{
	int Sum=m_TCBPtrArray.GetCount();
	TCB * pTCB=NULL;
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		delete pTCB;
	}
	m_TCBPtrArray.RemoveAll();
	CDialog::OnDestroy();
}

BOOL CEDFScheduleDlg::OnDialogExpanding(BOOL bExpanded)
{
	return TRUE;
}

void CEDFScheduleDlg::OnDialogExpanded(BOOL bExpanded)
{
	CRect rect1,rect2;
	GetClientRect(&rect1);
	m_TSB.GetWindowRect(&rect2);
	rect1.top=rect1.bottom-rect2.Height();
	m_TSB.MoveWindow(rect1);
}

BOOL CEDFScheduleDlg::CreateBitmapCtrl()
{
	CRect rect;
	CWnd* pCtrl=NULL;
	pCtrl=GetDlgItem(IDC_BITMAPBOX);
	if (pCtrl==NULL)
		return FALSE;
	pCtrl->GetWindowRect(&rect);
	ScreenToClient(&rect);//记得要把屏幕坐标转换为客户区坐标。
	m_BitmapCtrl.Create(RECT(rect),this,2000);
	return TRUE;
}

void CEDFScheduleDlg::ScheduleNotTimeDrived()
{
	
	double MaxPeriod=GetMaxPeriod();
	double MaxCounter=3*MaxPeriod;
	//下面做计数驱动,最大计数为所有任务的最大周期的三倍。
	TCB * pTCB=NULL;
	m_TimeCounterNT=0;
	DrawFitBitmap(MaxCounter);
	while (m_TimeCounterNT<=MaxCounter)
	{
		if (m_TidNT==-1)//CPU空跑
			SelectTaskNT();
		else
		{
			pTCB=(TCB *)m_TCBPtrArray.GetAt(m_TidNT);
			pTCB->RemainTimeNT--;
			if (pTCB->RemainTimeNT<=0)
			{
				pTCB->nCountNT++;
				pTCB->RemainTimeNT=pTCB->CPUTime;
			}
			m_TidNT=-1;
			SelectTaskNT();
		}
		DrawThePeriod();
		m_TimeCounterNT++;
	}
	m_dcMem.SelectObject(m_pOldBitmap);
	ResetTaskNT();
}

void CEDFScheduleDlg::SelectTaskNT()
{
	int Sum=m_TCBPtrArray.GetCount();
	TCB * pTCB=NULL;
	double ET=LONG_MAX;//最早截止时间。
	double SET=LONG_MAX;//下一个最早开始的任务的开始时间。
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		if (SET>((pTCB->nCountNT)*pTCB->Period))
			SET=(pTCB->nCountNT)*pTCB->Period;
		if ((pTCB->nCountNT*pTCB->Period)<=m_TimeCounterNT)//此刻在该任务的周期内
		{
			if (ET>((pTCB->nCountNT+1)*pTCB->Period))
			{
				ET=(pTCB->nCountNT+1)*pTCB->Period;//最早截止时间
				m_TidNT=i;//选择最早截止时间的任务
			}
		}
	}
}

void CEDFScheduleDlg::ResetTaskNT()
{
	m_TidNT=-1;
	m_TimeCounterNT=0;
	int Sum=m_TCBPtrArray.GetCount();
	TCB * pTCB=NULL;
	for(int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		pTCB->nCountNT=0;
	}
}

double CEDFScheduleDlg::GetMaxPeriod()
{
	int Sum=m_TCBPtrArray.GetCount();
	double MaxPeriod=-1;
	TCB * pTCB=NULL;
	for(int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		if (MaxPeriod<pTCB->Period)
			MaxPeriod=pTCB->Period;
	}
	return MaxPeriod;
}

void CEDFScheduleDlg::DrawFitBitmap(double MaxCounter)
{
	if (HBITMAP(m_ShowFlowBitmap)!=NULL)
		m_ShowFlowBitmap.DeleteObject();
	CClientDC dc(this);
	int Sum=m_TCBPtrArray.GetCount();
	double nWidth=MaxCounter*BLOCKWIDTH+LEFTOFFSET+RIGHTOFFSET;
	long nHeight=LINEHEIGHT*Sum+BOTTOMOFFSET;
	m_ShowFlowBitmap.CreateCompatibleBitmap(&dc,nWidth,nHeight);
	if (m_dcMem.m_hDC!=NULL)
		m_dcMem.DeleteDC();
	m_dcMem.CreateCompatibleDC(&dc);
	CBrush brush(RGB(255,255,255));
	m_pOldBitmap=m_dcMem.SelectObject(&m_ShowFlowBitmap);
	m_dcMem.FillRect(CRect(0,0,nWidth,nHeight),&brush);
	CPoint point(0,0);
	TCB * pTCB=NULL;
	for (int i=0;i<Sum;i++)
	{
		pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
		m_dcMem.TextOut(3,(i+1)*LINEHEIGHT-BLOCKHEIGHT,pTCB->TaskName);
		m_dcMem.MoveTo(LEFTOFFSET,(i+1)*LINEHEIGHT);
		m_dcMem.LineTo(nWidth,(i+1)*LINEHEIGHT);
		for(int j=0;j<=MaxCounter;j++)
		{
			point=CPoint(LEFTOFFSET+j*BLOCKWIDTH,(i+1)*LINEHEIGHT+3);
			CString strTime;
			strTime.Format(_T("%d"),j);
			m_dcMem.TextOut(point.x,point.y,strTime);
		}
	}
}

void CEDFScheduleDlg::DrawThePeriod()
{
	if (m_TidNT==-1)
		return;
	if (HBITMAP(m_ShowFlowBitmap)==NULL)
		return;

	CBrush brush(RGB(60,120,60));
	CRect rect;
	rect.left=LEFTOFFSET+m_TimeCounterNT*BLOCKWIDTH;
	rect.top=(m_TidNT+1)*LINEHEIGHT-BLOCKHEIGHT;
	rect.right=LEFTOFFSET+(m_TimeCounterNT+1)*BLOCKWIDTH;
	rect.bottom=(m_TidNT+1)*LINEHEIGHT;
	m_dcMem.FillRect(&rect,&brush);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -