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

📄 设计报告.txt

📁 主要功能: 1、 包括顾客信息、货品信息、定单信息的管理。 2、 按月统计销售业绩。 3、 报表设计。 4、 系统维护。
💻 TXT
📖 第 1 页 / 共 4 页
字号:
任务一  实现批处理
一、基本信息
实践题目:实现批处理
二、实践内容简要描述
实践目标:
(1)了解Windows2000操作系统的基本结构
(2)学会在Win32环境下,通过函数 BOOL CreateProcess(LPCTSTR lpApplicationName,LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,  DWORD dwCreationFlags, LPVOID lpEnvironment,  LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)创建进程。
(3)学会用CreateFile ReadFile读文件,用FormatMessage处理出错信息。
实践内容:
从batch文件中正确读入应用程序命令行及其参数,并依次为其创建相应进程。
三、实践报告主要内容
设计思路:
(1)先打开文件 :使用CreateFile打开一个文件,获得HANDLE hFile
(2)然后读取文件 :用ReadFile通过已经获得HANDLE hFile的读取文件,并赋给inBuffer
(3)格式或处理读取信息并创建进程 :将inBuffer 中的信息格式化提取并用CreateProcess创建进程
主要代码结构:
/* 1.create the file and get the handle*/
 HANDLE hFile=CreateFile("batch",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
 
/* 2.judge if the file is open and get the error imformation */
 if(hFile==INVALID_HANDLE_VALUE)
 {
  LPVOID lpMsgBuf;
  FormatMessage( 
     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_IGNORE_INSERTS,
  NULL,
     GetLastError(),
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  (LPTSTR) &lpMsgBuf,
  0,
  NULL 
  );
  fprintf(stdout,(char*)(lpMsgBuf));
  ExitProcess(1);
 }
/* 3.read file and detect the error infomation */
 BOOL bResult;
 char inBuffer[1000];     // pointer to buffer that receives data
 DWORD nBytesToRead=900;   // number of bytes to read
 DWORD nBytesRead;
 LPDWORD lpnBytesRead=&nBytesRead;  // pointer to number of bytes read
 bResult =ReadFile(
  hFile,    // handle of file to read
  inBuffer,   // pointer to buffer that receives data
  nBytesToRead,  // number of bytes to read
  lpnBytesRead,  // pointer to number of bytes read
  NULL    // pointer to structure for data
);

/* 4.get the command from the buffer */
 count=0;
 pos=0;
 for (i=0;i<(int)nBytesRead;i++)
 {
  if(inBuffer[i]!=10 && inBuffer[i]!=13)
  {
   cmdLine[count][pos]=inBuffer[i];
   pos++;
   continue;
  }
  if(inBuffer[i]==10)
  {
   cmdLine[count][pos]=0;
   pos=0;
   count++;
  }
 }
/* 5.copy the command from command line parameters */
 for ( i = 0; i < count ; i++) {
  if(!CreateProcess( 
       lpApplicationName, /* File name of executable */
       cmdLine[i],   /* Command line */
       processSA,   /* Process inherited security */
       threadSA,   /* Thread inherited security */
       shareRights,  /* Right propagation */
       creationMask,  /* Various creation flags */
       environment,  /* Environment variabkesr */
       curDir,    /* Child's current directory */
       &startInfo,
       &processInfo
       )
    ) {
    fprintf(stderr,"CreatProcess failed on error %d\n",GetLastError());
    ExitProcess(1);
   };
  fprintf(stdout,"The Child Process's PID: %d.\n", processInfo.dwProcessId);
  fprintf(stdout,"The Parent Process finish.\n");
  Sleep(500);
  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);
 };
四、实践结果
基本数据:
 
源程序代码行数 完成实践投入的总时间 编程调试时间 源程序文件    
116 2.5小时 0.5小时 ex1.cpp  
测试数据设计:
“batch”文件内容如下:
  c:\windows\notepad.exe  
   c:\windows\system32\calc.exe    
  c:\windows\system32\mspaint.exe 
测试结果分析:
程序能够依次打开notepad,calc和mspaint,并显示
The Child Process's PID: 1712.
The Parent Process finish.
The Child Process's PID: 3276.
The Parent Process finish.
The Child Process's PID: 3876.
The Parent Process finish.
五、实践体会
第1个任务比较简单,我参考样例程序并查阅有关资料,在这个实验上没有遇到比较棘手的问题,通过任务1,我了解了创建进程的方法,对创建进程CreateProcess()函数中的各个参数有了一个初步的认识。

任务二  软件方法解决临界区问题
一、基本信息
实践题目:软件方法解决临界区问题-兄弟问题
二、实践内容简要描述
实践目标:
用软件方法(Peterson算法或Dekker算法等)解决临界区问题-兄弟问题。
实践内容:
设置竞争条件:
定义两个全局变量:accnt1和accnt2,初值都为零;
创建两个线程acc1和acc2;
(1)获得一个随机数
(2)从accnt1减去这个随机数;
(3)将这个随机数加到accnt2中;
(4)正确的话,accnt1+accnt2=0。
设置条件使其不正确。
用软件方法实现协作线程,以解决以上临界区问题,即兄弟问题。
三、实践报告主要内容
设计思路:
选择算法:
Dekker算法——该算法主要用于解决两个线程的临界区问题,是典型的软件方法解决临界区问题的算法。
设计思路:
线程Pi结构如下:
do{
 flag[i]=true;
 while(flag[j]){
  if(turn==j) {
   flag[i] = false;
   while(turn==j);
   flag[i]=true;
  }
 }
  critical section
turn=j;
flag[i]=false;
remainder section
}while(1);
每个在进入临界区前用entry section实行判断等待,离开临界区后发出信号通知别的线程可以进入临界区,这样可以防止两个线程同时访问临界区。
在程序中i表示自身线程序号,再用两个线程序号之和减去i即可表示另外那个线程的序号。
主要数据结构:
struct ThreadInfo
{
 int serial;
 double delay;
};//存放线程的ID及其执行延时(模拟兄弟在外创业的时间)
/*volatile*/  int accnt1 = 0;  //借款帐户中金额
/*volatile*/  int accnt2 = 0;  //还款帐户中金额
/*volatile*/  int accnt;  //借款帐户与还款帐户金额总和,应保持为0
/* variables for Dekker's arithmetic */
BOOL flag[2]={false,false};// flag[i] = true表示线程Pi 准备进入临界区
int turn;   // turn = i表示线程Pi允许在临界区执行
int i = m_serial;  // 自身线程序号
int j = 1 - m_serial;   // 另外那个线程序号
主要代码结构:
do{
entry section
critical section
exit section
remainder section
}while(1);
主要代码分析:
1.entry section用于在进入临界区时的等待
  /* entry section begin */
  flag[m_serial]=true;
  turn=1-m_serial;
  while (flag[1-m_serial] && turn==1-m_serial);
  /* entry section end   */
2.exit section用于离开临界区后的发送信号的工作,通知另外的线程可以进入临界区
  /* exit section begin */
  flag[m_serial]=false;
  /* exit section end   */
四、实践结果
基本数据:
 
源程序代码行数 完成实践投入的总时间 资料查阅时间 编程调试时间 源程序文件    
196 0.5小时 0.3小时 0.2小时 ex2.cpp  

测试数据设计:
“ex2.dat”文件内容如下:
 0  1
0  1
测试结果分析:
运行结果图如下所示:
Now, We begin to read thread Information to thread_info array
I am thread  0 , I am doing  00000th step
Now the random number is 20571 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00000th step
Now the random number is 17781 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00001th step
Now the random number is 22438 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00001th step
Now the random number is 17547 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00002th step
Now the random number is 27554 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00002th step
Now the random number is 25718 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00003th step
Now the random number is 18778 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00003th step
Now the random number is 8063 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00004th step
Now the random number is 30162 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00004th step
Now the random number is 29448 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00005th step
Now the random number is 7046 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00005th step
Now the random number is 8096 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00006th step
Now the random number is 16582 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00006th step
Now the random number is 8806 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00007th step
Now the random number is 1534 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00007th step
Now the random number is 31418 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00008th step
Now the random number is 21293 ; and accnt1+accnt2 =  00000
I am thread  1 , I am doing  00008th step
Now the random number is 9811 ; and accnt1+accnt2 =  00000
I am thread  0 , I am doing  00009th step
Now the random number is 22034 ; and accnt1+accnt2 =  00000
At last of thread 0 accnt1+accnt2 =  00000
I am thread  1 , I am doing  00009th step
Now the random number is 20276 ; and accnt1+accnt2 =  00000
At last of thread 1 accnt1+accnt2 =  00000
All threads have finished Operating.
Press any key to finish this Program.
五、实践体会
 解决线程同步问题的关键是避免两个以上线程同时访问临界区数据,在实验中,由于entry section 和exit section所放位置不对导致了很多的错误,将entry section放在读取帐户数据后会出现读取数据出错导致帐户总额不对,因为可能读取到的是脏数据,将读取帐户数据和对其进行修改的代码放在entry section和exit section之间,即可确保同时只能有一个线程对其访问和操作,从而正确解决了问题。
 
六、参考文献
1、MSDN
2、《操作系统概念(第六版 影印版)》,Abraham Silberschatz、Peter Baer Galvin、Greg Gagne,
高等教育出版社

附:源程序代码
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream.h>
#include <stdio.h>
#include <time.h>
#define INTE_PER_SEC  500
#define MAX_THREAD_NUM  64
#define RIGHT_VERSION TRUE
#define WRONG_VERSION FALSE
struct ThreadInfo
{
 int serial;
 double  delay;
};

/*volatile*/  int accnt1 = 0; 
/*volatile*/  int accnt2 = 0;
/*volatile*/  int accnt;

BOOL flag[2]={false,false};
int turn;

void account( char* file,BOOL version);
void acc_right(void* p);
void acc_wrong(void* p);

////////////////////////////////////////////////////////
// main function
////////////////////////////////////////////////////////

int main( int agrc, char* argv[] )
{
 char ch;

 while ( TRUE )
 {
  // Clear screen
  system( "cls" );

  // display prompt info
  printf("*********************************************\n");
  printf("       1.Start the right version(with the PETERSON algorithm)\n");
  printf("       2.Start the wrong version(without any algorithm of synchronization)\n");
  printf("       3.Exit to Windows\n");
  printf("*********************************************\n");
  printf("Input your choice(1,2or3): ");

  // if the number inputed is error, retry!
  do
  {
   ch = (char)_getch(); 
  }while ( ch != '1' && ch != '2'&& ch != '3');

  system ( "cls" );
  if ( ch == '1')
   account("ex2.dat",RIGHT_VERSION);
  else if (ch =='2')
   account("ex2.dat",WRONG_VERSION);
  else if ( ch == '3')
   return 0;
  printf("\nPress any key to finish this Program. \n");
  _getch();
 } //end while
} //end main

void account( char* file,BOOL version)
{
 DWORD n_thread = 0;
 DWORD thread_ID;
 DWORD wait_for_all;

// Tread Object Array

 HANDLE h_Thread[MAX_THREAD_NUM];
 ThreadInfo  thread_info[MAX_THREAD_NUM];

 ifstream  inFile;
 inFile.open(file);  //open file
 printf( "Now, We begin to read thread Information to thread_info array \n\n" );

 while ( inFile )
 {
  // read every thread info
  inFile>>thread_info[n_thread].serial;
  inFile>>thread_info[n_thread++].delay;
  inFile.get();
 } //end while

// initialize the data
 
 srand((unsigned)time(NULL));
 accnt1=0;
 accnt2=0;

// Create all thread

 if (version==RIGHT_VERSION)
 {

  for ( int i = 0; i < (int)(n_thread); i++)
  {
   // Create a thread
   h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc_right), &thread_info[i], 0, &thread_ID);
  } //end for

 } else
 {
  for ( int i = 0; i < (int)(n_thread); i++)
  {
   // Create a thread
   h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc_wrong), &thread_info[i], 0, &thread_ID);
  } //end for
 }
// Create thread

// waiting all thread will been finished

 wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE, -1);
 printf("All threads have finished Operating.\n");
}// end account

⌨️ 快捷键说明

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