操作系统:模拟售票功能

以下程序是模拟售票功能,使用临界区对象,其中SellPro_1,SellPro_2两个函数分别对应两个售票进程,一次售出一张票。

 1 //模拟售票程序
 2 #include <windows.h>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 DWORD WINAPI SellPro_1( LPVOID lpParameter);
 7 DWORD WINAPI SellPro_2( LPVOID lpParameter );
 8 
 9 int tickets=100;
10 CRITICAL_SECTION critical_sec; //定义关键区域
11 void main()
12 {
13 HANDLE hThread1;
14 HANDLE hThread2;
15 
16 InitializeCriticalSection(&critical_sec); //初始化关键区域
17 hThread1=CreateThread(NULL,0,SellPro_1,NULL,0,NULL);
18 hThread2=CreateThread(NULL,0,SellPro_2,NULL,0,NULL);    
19 CloseHandle(hThread1);
20 CloseHandle(hThread2);
21 Sleep(4000);
22 }
23 
24 DWORD WINAPI SellPro_1( LPVOID lpParameter )
25 { 
26 while(TRUE)
27 { 
28 Sleep(1);
29 EnterCriticalSection(&critical_sec); //进入关键代码区域 
30 if(tickets>0)
31 {
32 cout<<"thread1 sell ticket : "<<--tickets<<endl;
33 }
34 else
35 break;
36 LeaveCriticalSection(&critical_sec); //离开代码关键区域
37 } 
38 return 0;
39 }
40 
41 DWORD WINAPI SellPro_2( LPVOID lpParameter)
42 { 
43 while(TRUE)
44 { 
45 Sleep(1);
46 EnterCriticalSection(&critical_sec); //进入关键代码区域    
47 if(tickets>0)
48 {
49 cout<<"thread2 sell ticket : "<<--tickets<<endl;
50 
51 }
52 else
53 break;
54 LeaveCriticalSection(&critical_sec); //离开代码关键区域
55 } 
56 return 0;
57 }

 

DWORD WINAPI SellPro_1(LPVOID lpParameter);

DWORD:
1、代表 unsigned long,一般用于返回值不会有负数的情况。
2、typedef unsigned long DWORD;
关于DWORD使用中重要的一点。DWORD 现在表示 32bit 无符号整数,即使以后 Windows 升级到64位,DWORD 仍然是 32bit 无符号整数(也许以后的 long 不是32bit了,只需要重新定义一下 DWORD 就可以了)。对于那些直接和位数有关的整数,最好不用 int, long, short 之类的类型,因为这些类型的位数可能不确定(比如,在16位程序里,int 是16位的,在32位程序里,int 是32位的,谁知道在以后的64位程序里,int 是多少位,long 又是多少位)。用重新定义的类型就没有这方面的问题了,最多到时候修改一下定义就可以了,而不需要在程序里一行一行的查找
3、在实际情况中,DWORD会根据操作系统的不同,被定义成了不同的长度
4、C++中使用DWORD不用声明,但是要加头文件Windows.h。
(1)DWORD全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位。
(2)DWORD在Windows下经常用来保存地址(或者存放指针)。

DWORD WINAPI

 DWORD是数据类型,WINAPI是函数调用形式,最终就是_stdcall形式,即由被调用函数来清理栈中的参数,这种方式是不能实现可变参数的。
 WINAPI是个宏,一般会被代换为一个调用约定,通常为_stdcall,告诉编译器如何调用该函数。

_stdcall

 被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递的(__fastcall 的前面部分由ecx,edx传),
 函数调用在返回前要由被调用者清理堆栈。

LPVOID

 LPVOID是一个没有类型的指针,也就是说你可以将LPVOID类型的变量赋值给任意类型的指针,比如在参数传递时就可以把任意类型传递给一个LPVOID类型为参数的方法,然后在方法内再将这个“任意类型”从传递时的“LPVOID类型”转换回来。

CRITICAL_SECTION

 critical section是每个线程中访问临界资源的那段代码,不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问。


HANDLE
Windows操作系统中的一个概念

 

 HANDLE:句柄,是Windows用来表示对象的(不是C++的对象),HWND是其中一种,HWND是HANDLE,但HANDLE不只是HWND,HANDLE是一个通用句柄表示,HWND是一个专用表示窗口的句柄。更具体的可查找MSDN。包含在winnt.h头文件中。

 HANDLE(句柄)是Windows操作系统中的一个概念。在Windows程序中,有各种各样的资源(窗口、图标、光标等),系统在创建这些资源时会为它们分配内存,并返回标示这些资源的标示号,即句柄。句柄指的是一个核心对象在某一个进程中的唯一索引,而不是指针。由于地址空间的限制,句柄所标识的内容对进程是不可见的,只能由操作系统通过进程句柄列表来进行维护。句柄列表:每个进程都要创建一个句柄列表,这些句柄指向各种系统资源,比如信号量,线程,和文件等,进程中的所有线程都可以访问这些资源。


InitializeCriticalSection
(API的功能)
功能——初始化临界区对象
格式:

 VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 

参数说明:
lpCriticalSection——指向临界区对象的指针。

CreateThread
(API的功能)
功能——创建一个在调用进程的地址空间中执行的线程
格式:

HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParamiter,
DWORD dwCreationFlags,
Lpdword lpThread );

 

参数说明:
lpThreadAttributes——指向一个LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。
dwStackSize——定义原始堆栈大小。
lpStartAddress——指向使用LPTHRAED_START_ROUTINE类型定义的函数。
lpParamiter——定义一个给进程传递参数的指针。
dwCreationFlags——定义控制线程创建的附加标志。
lpThread——保存线程标志符(32位)

CloseHandle

 CloseHandle包括文件、文件映射、进程、线程、安全和同步对象等。涉及文件处理时,这个函数通常与vb的close命令相似。应尽可能的使用close,因为它支持vb的差错控制。
参数
hObject :代表一个已打开对象handle。
返回值
TRUE:执行成功;
FALSE:执行失败,可以调用GetLastError()获知失败原因。
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。
返回值
Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
hObject Long,欲关闭的一个对象的句柄
注解
除非对内核对象的所有引用都已关闭,否则该对象不会实际删除

Sleep

 SLEEP是一种函数,作用是延时,程序暂停若干时间,在执行时要抛出一个中断异常,必须对其进行捕获并处理才可以使用这个函数。
时间,就是他的参数,单位是毫秒。

EnterCriticalSection
(API的功能)
功能——等待指定临界区对象的所有权
格式

VOID enterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

 

参数说明
lpCriticalSection——指向临界区对象的指针。

LeaveCriticalSection
(API的功能)
功能——释放指定临界区对象的所有权
格式

VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

参数说明
lpCriticalSection——指向临界区对象的指针。

 

转载于:https://www.cnblogs.com/waiting-/p/10701761.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通过优先级调度算法的模拟,加深进程概念和进程调度过程的理解。设计原理及方案:1)在Linux下用C语言编程模拟优先级程调度算法。为了清楚地观察每个进程的调度过程,程序将每个时间片内的进程情况显示出来。2)进程控制块是进程存在的唯一标志,因此,在模拟算法中每一个进程用一个进程控制块PCB来代表,PCB用一结构体表示。3)进程在运行过程中其状态将在就绪、执行、完成几种状态之间转换,同时进程可能处于不同的队列中,如就绪队列。在优先级调度算法中,选择单向队列,入队既是将进程控制块插入队尾,出队既是按优先级重新排列的队,删除队头元素。4)为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的优先级认为输入,运行所需时间随机产生。5)优先权调度算法采用动态优先权,进程每运行一个时间片,优先数减1;进程在就绪队列等待一个时间单位,优先数加1。6)对于遇到优先权一致的情况,采用FCFS策略解决。7)由于是模拟进程调度,所以,对被选中的进程并不实际启动运行,而是修改进程控制块的相关信息来模拟进程的一次运行。 分别用两种调度算法对伍个进程进行调度。每个进程可有三种状态;执行状态(R)、就绪状态(W,包括等待状态)和完成状态(F,并假定初始状态为就绪状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值