• 【操作系统核心编程】大四的编程作业留底


     邹老师布置了五个Task,不过自己时间不够,尽量做吧。感觉着实很有用,所以打算先记录下来。

    1. 进程打开进程 

    2.  多线程

    3.  线程互斥

    4.  多线程操作数组

    5.  多线程模型

    笔者按:

    使用windows对象解决临界区问题:
    方式有:
    windows执行体对象:
    • 互斥对象:mutex 实现一个资源同一时刻只能被一个线程使用
    • 事件对象:event 限制并发访问的线程数
    • 信号量对象:semaphore
    windows子系统对象:
    • 临界区 critical section,同一进程内对于临界区的访问是互斥的

    『临界区windows子系统对象,不是内核对象,只能用于同步单个进程中的线程,要注意跟信号量相区别。』

    /*
        task 2
        应用Peterson算法解决临界区问题  协作线程——兄弟问题
        
        利用Peterson算法,实现线程间的互斥。
            boolean flag[2];//初值false
            int turn;
            do{
               flag[i]:=true;
               turn=j;
               while(flag[j] and turn=j);
                   临界区;
               flag[i]=false;
                   剩余区;
              }while(1);
    */
    
    #include <windows.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <fstream>  //for Dev C++  VC use #include <fstream.h>
    #include <stdio.h>
    
    #define INTE_PER_SEC  1000
    #define MAX_THREAD_NUM  64
    
    struct ThreadInfo
    {
    	int	serial;
    	double	delay;
    };
    
    volatile  int accnt1 = 0; /*  in the memory */
    volatile  int accnt2 = 0;
    volatile  bool flag[2] = {0,0};
    volatile int turn;
    void account( char* file);
    void acc(void* p);
    
    ////////////////////////////////////////////////////////
    // main fuction
    ////////////////////////////////////////////////////////
    
    int main( int agrc, char* argv[] )
    {
    	char ch;
    
    	while ( TRUE )
    	{
    		// Cleare screen
    		system( "cls" );
    
    		// display prompt info
    		printf("*********************************************
    ");
    		printf("       1.Start test
    ");
    		printf("       2.Exit to Windows
    ");
    		printf("*********************************************
    ");
    		printf("Input your choice(1or2): ");
    
    		// if the number inputed is error, retry!
    		do{
    			ch = (char)_getch();
    		}while( ch != '1' && ch != '2');
    
    		system ( "cls" );
    		if ( ch == '1')
    			account( (char*)"sm6.dat");
    		else if ( ch == '2')
    			return 0;
    		printf("
    Press any key to finish this Program. 
    Thank you test this Proggram!
    ");
    		_getch();
    	} //end while
    } //end main
    
    void account( char* file)
    {
    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];
    
    std::ifstream  inFile;  //for Dev C++   VC use ifstream  inFile;
    inFile.open(file,std::ifstream::in);		//open file
    printf( "Now, We begin to read thread Information to thread_info array 
    
    " );
    
    while ( inFile )
    {
    	// read every thread info
    	inFile>>thread_info[n_thread].serial;
    	inFile>>thread_info[n_thread++].delay;
    	inFile.get();
    } //end while
    
    // Create all thread
    for( int i = 0; i < (int)(n_thread); i++)
    {
    	// Create a thread
        	h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc), &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.
    ");
    }// end account
    
    void acc(void* p)
    {
    	DWORD m_delay;
    	int m_serial;
    	int rand_num, accnt,counter = 0;;
    
    //get info froam para
    
    	m_serial = ((ThreadInfo*) (p)) -> serial;
    	m_delay  = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
    	srand( (unsigned)((ThreadInfo*)(p)) -> delay );
    	do {
    		printf("I am thread  %d , I am doing  %05dth step
    ",m_serial,counter);
    		rand_num = rand();
    		/* printf("rand_num =  %05d 
    ",rand_num); */
    		//Sleep(m_delay);
            int i=m_serial;
            flag[i-1] = true;
            int j = (m_serial==2?1:2);
            turn = j;
            while(flag[m_serial-1] and turn==j)
                j=j;
    //begin critical_section
    		accnt1 = accnt1 - rand_num;
    		Sleep(m_delay);
    		accnt2 = accnt2 + rand_num;
    		accnt = accnt1 + accnt2;
    //critical_section  end
            flag[i] = false;
    		counter++;
    	} while ( (accnt == 0) && (counter<10));
    	printf("Now accnt1+accnt2 =  %05d
    ",accnt);
    } //end acc
    

      

    /*
        task 3
    */
    #include <windows.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <fstream>  //for Dev C++  VC use #include <fstream.h>
    #include <stdio.h>
    
    #define INTE_PER_SEC  1000
    #define MAX_THREAD_NUM  64
    
    struct ThreadInfo
    {
    	int	serial;
    	double	delay;
    };
    
    volatile  int accnt1 = 0; /*  in the memory */
    volatile  int accnt2 = 0;
    
    CRITICAL_SECTION  BRO_Add;
    
    void account( char* file);
    void acc(void* p);
    
    ////////////////////////////////////////////////////////
    // main fuction
    ////////////////////////////////////////////////////////
    
    int main( int agrc, char* argv[] )
    {
    	char ch;
    
    	while ( TRUE )
    	{
    		// Cleare screen
    		system( "cls" );
    
    		// display prompt info
    		printf("*********************************************
    ");
    		printf("       1.Start test
    ");
    		printf("       2.Exit to Windows
    ");
    		printf("*********************************************
    ");
    		printf("Input your choice(1or2): ");
    
    		// if the number inputed is error, retry!
    		do{
    			ch = (char)_getch();
    		}while( ch != '1' && ch != '2');
    
    		system ( "cls" );
    		if ( ch == '1')
    			account( (char*)"sm6.dat");
    		else if ( ch == '2')
    			return 0;
    		printf("
    Press any key to finish this Program. 
    Thank you test this Proggram!
    ");
    		_getch();
    	} //end while
    } //end main
    
    void account( char* file)
    {
    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];
    
    std::ifstream  inFile;  //for Dev C++   VC use ifstream  inFile;
    inFile.open(file,std::ifstream::in);		//open file
    printf( "Now, We begin to read thread Information to thread_info array 
    
    " );
    
    while ( inFile )
    {
    	// read every thread info
    	inFile>>thread_info[n_thread].serial;
    	inFile>>thread_info[n_thread++].delay;
    	inFile.get();
    } //end while
    InitializeCriticalSection(&BRO_Add);
    // Create all thread
    for( int i = 0; i < (int)(n_thread); i++)
    {
    	// Create a thread
        	h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc), &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.
    ");
    }// end account
    
    void acc(void* p)
    {
    	DWORD m_delay;
    	int m_serial;
    	int rand_num, accnt,counter = 0;;
    
    //get info froam para
    
    	m_serial = ((ThreadInfo*) (p)) -> serial;
    	m_delay  = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
    	srand( (unsigned)((ThreadInfo*)(p)) -> delay );
    	do {
    		printf("I am thread  %d , I am doing  %05dth step
    ",m_serial,counter);
    		rand_num = rand();
            EnterCriticalSection(&BRO_Add);
    //begin critical_section
    		accnt1 = accnt1 - rand_num;
    		Sleep(m_delay);
    		accnt2 = accnt2 + rand_num;
    		accnt = accnt1 + accnt2;
    //critical_section  end
            LeaveCriticalSection( &BRO_Add );
    		counter++;
    	} while ( (accnt == 0) && (counter<10));
    	printf("Now accnt1+accnt2 =  %05d
    ",accnt);
    } 
    

      

    /*
        task 4
        windows 核心编程:有限缓冲区问题
        测试数据:4.dat
        生产者消费者算法:
            生产者:计算一定范围内素数并将其放入 prime 队列(数组实现的)
            消费者:将素数取出并打印出来。
        临界区和事件对象解决线程独占资源问题。
        Reference:
            CreateEvent function: https://msdn.microsoft.com/en-us/library/ms682396(VS.85).aspx
            WaitForSingleObject function: https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx
    */
    
    #include <windows.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <fstream>
    #include <stdio.h>
    
    #define MAX_THREAD_NUM  64
    using namespace std;
    struct ThreadInfo
    {
    	int	serial;
    	char entity;
    	int from;
    	int to;
    };
    
    int prime[9];
    int count = 0;
    
    volatile int putArea=0;
    
    HANDLE h_full;  
    HANDLE h_empty; 
    CRITICAL_SECTION  criticalSection;
    
    void control( char* file);
    void consumerThread(void* p);
    void producerThread(void* p);
    
    ////////////////////////////////////////////////////////
    // main fuction
    ////////////////////////////////////////////////////////
    
    int main( int agrc, char* argv[] )
    {
    	char ch;
    
    	for(int i = 0;i < 9; i++)
    	{
    		prime[i] = 0;
    	}
    
    	while ( TRUE )
    	{
    		// Cleare screen
    		system( "cls" );
    
    		// display prompt info
    		printf("*********************************************
    ");
    		printf("       1.Start test
    ");
    		printf("       2.Exit to Windows
    ");
    		printf("*********************************************
    ");
    		printf("Input your choice(1or2): ");
    		
    		// if the number inputed is error, retry!
    		do{
    			ch = (char)_getch(); 
    		}while( ch != '1' && ch != '2');
    
    		system ( "cls" );
    		if ( ch == '1')
    			control("4.dat");
    		else if ( ch == '2')
    			return 0;
    		printf("
    Press any key to finish this Program. 
    Thank you test this Proggram!
    ");
    		_getch();
    	} //end while
    } //end main
    
    void  control( char* file)
    {
    DWORD n_thread = 0;
    DWORD thread_ID;
    DWORD wait_for_all;
    
    InitializeCriticalSection(&criticalSection); 
    
    // Tread Object Array
    
    HANDLE h_Thread[MAX_THREAD_NUM];
    ThreadInfo  thread_info[MAX_THREAD_NUM];
    
    h_full = CreateEvent(NULL,TRUE,TRUE,"full_event");
    h_empty = CreateEvent(NULL,TRUE,TRUE,"empty_event");
    
    ifstream  inFile;
    inFile.open(file);		//open file
    printf( "Now, We begin to read thread Information to thread_info array 
    
    " );
    
    while ( inFile )
    {
    	// read every thread info
    	inFile>>thread_info[n_thread].serial;
    	inFile>>thread_info[n_thread].entity;
    	inFile>>thread_info[n_thread].from;
    	inFile>>thread_info[n_thread++].to;
    	inFile.get();
    } //end while
    
    // Create all thread
    for( int i = 0; i < (int)(n_thread); i++)
    {	
    	if(thread_info[i].entity == 'D')// Create a reader thread
    	{
    		h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(consumerThread), &thread_info[i], 0, &thread_ID);
    	}
    	else
    	{
    		h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(producerThread), &thread_info[i], 0, &thread_ID);
    	}
        	
    } //end for
    	
    // waiting all thread will been finished
    
    wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE, -1);
    printf("All threads have finished Operating.
    ");
    }// end account
    
    void consumerThread(void* p) 
    {
    	
    	int m_count;
    	int m_serial;
    
    	int i = 0;
    	int readcount=0;
    
    	m_serial = ((ThreadInfo*) (p)) -> serial;
    	m_count  = ((ThreadInfo*)(p)) -> from;
    
    	do {
    		WaitForSingleObject(h_full,-1); 		
    		EnterCriticalSection(&criticalSection);
    		while(!prime[i])
    		{
    			i=(i+1)%9;
    		}
    		printf("Consumer thread %d reads %d from postion %d.
    ",m_serial,prime[i],i);
    		prime[i] = 0;
    		count--;
    		readcount++;
    		LeaveCriticalSection(&criticalSection);  
    		SetEvent(h_empty); 
    		Sleep(1000);
    	} while ( readcount<(int)m_count); 
    	return;
    } 
    
    void producerThread(void* p)
    {
    	int m_from;
    	int m_to;
    	int m_serial;
    
    	m_serial = ((ThreadInfo*) (p)) -> serial;
    	m_from  = ((ThreadInfo*)(p)) -> from;
    	m_to  = ((ThreadInfo*)(p)) -> to;
    	int i = 0;
    
    	for(int j = (int)m_from;j < (int)m_to;j++)
    	{
    		
    		if(j==1) continue;
    		int k;
    		for(k = 2;k <= j/2;k++)
    		{
    			if(j % k == 0) break;
    		}
    		if(k < j/2 +1) continue;
    		
    		if(count == 9) break;
    		WaitForSingleObject(h_empty,-1);  
    		EnterCriticalSection(&criticalSection);;  
    		prime[putArea%9] = j;
    		printf("Producer thread %d writes %d to the %d postion.
    ",m_serial,j,putArea%9);
    		putArea++;
    		count++;
    		LeaveCriticalSection(&criticalSection); 
    		SetEvent(h_full); 
    		Sleep(1000);
    	}
    	return;
    } 
    

      

    原文链接:http://www.cnblogs.com/learn-to-rock/p/5894682.html

  • 相关阅读:
    ByteBuffer用法总结
    内部类访问外部同名属性或者方法
    floodlight 学习(一)
    ubuntu 更改文件所有者
    python cmd 模块
    matlab 矩阵
    python操作MySQL数据库
    Win 7 下制作 mac 系统启动U盘
    Window 常用命令
    大数据扫盲
  • 原文地址:https://www.cnblogs.com/learn-to-rock/p/5894682.html
Copyright © 2020-2023  润新知