第三階段應用層——1.7 數碼相冊—電子書(5)—多線程支持多輸入

數碼相冊——電子書多線程支持多輸入

  • 硬件平臺:韋東山嵌入式Linxu開發板(S3C2440.v3)
  • 軟件平臺:運行於VMware Workstation 12 Player下UbuntuLTS16.04_x64 系統
  • 參考資料:《嵌入式Linux應用開發手冊》、《嵌入式Linux應用開發手冊第2版》、【多線程編寫】
  • 開發環境:Linux 3.4.2內核、arm-linux-gcc 4.3.2工具鏈


一、前言

【1.7 數碼相冊—電子書(3)—輪詢方式支持多輸入】【1.7 數碼相冊—電子書(4)—select支持多輸入】中,我們採用了輪詢方式支持多輸入,並且採用select函數進了輪詢方式的CPU佔用率過高的問題。
在這篇博客中,採用多線程的方式,來改進了輪詢方式的CPU佔用率過高的問題,同時修改touchscreen.c支持滑動翻頁,分爲如下三個線程

  1. 主線程:負責初始化各種設備創建子線程,並協調它們進行顯示電子書的效果等待子線程的輸入信息,處於休眠
  2. stdin輸入子線程:負責響應stdin輸入設備的輸入事件的子線程,當發生輸入事件時,主線程處於休眠狀態執行此線程的任務,執行完畢後則重新喚醒主線程
  3. touchscreen輸入子線程:負責響應touchscreen輸入設備的輸入事件的子線程,當發生輸入事件時,主線程處於休眠狀態執行此線程的任務,執行完畢後則重新喚醒主線程

並且兩個子線程同一時間能只能執行一個

二、修改代碼

1、修改管理者input_manager.c文件

1.1 創建線程

此函數是main.c中被調用初始化所有輸入設備的時候創建對應子線程

/* 初始化所有支持的Input設備 */
int AllInputDeviceInit()
{
	int error;
	PT_InputOpr ptTmp;

	error = -1;
	ptTmp = s_ptInputOprHead;
	
	while (ptTmp) {
		if (ptTmp->DeviceInit() == 0) {
			/* 創建子線程 */
			error = pthread_create(&ptTmp->threadId, NULL, InputEventThreadFunction, ptTmp->GetInputEvent);
			if (error != 0) {				
				printf("pthread_creat error ,error code : %d\n", error);
				return error;
			}	
		}
		ptTmp = ptTmp->ptNext;
	}

	return 0;
}

1.2 輸入事件線程函數

此函數在發生對應子線程的時候被執行。

/* 輸入事件線程函數 */
static void *InputEventThreadFunction(void *pvoid)
{
	T_InputEvent tmpInputEvent;
	
	/* 定義函數指針 */
	int (*GetInputEvent)(PT_InputEvent ptInputEvent);
	GetInputEvent = (int (*)(PT_InputEvent))pvoid;

	while(1) {
		/* 調用函數獲得輸入事件 */
		if (GetInputEvent(&tmpInputEvent) == 0) {
			/* 喚醒主線程,把tmpInputEvent的值賦給一個全局變量 */
			/* 訪問臨界資源前,先獲得互斥量 */
			pthread_mutex_lock(&s_tMutex);		//加鎖
			s_tInputEvent = tmpInputEvent;
		
			/* 喚醒主線程 */
			pthread_cond_signal(&s_tCondvar);	//發送信號給處於阻塞等待狀態的主線程

			/* 釋放互斥量 */
			pthread_mutex_unlock(&s_tMutex);	//解鎖
		}
	}
	
	return NULL;
}

1.3 獲取輸入事件的函數

此函數在發生對應子線程的時候被執行,通過1.2中的函數的GetInputEvent(&tmpInputEvent),被調用。

/* 獲取輸入事件 */
int GetInputEvent(PT_InputEvent ptInputEvent)
{
	/* 休眠 */
	/* 進入臨界資源前,獲得互斥量 */
	pthread_mutex_lock(&s_tMutex);	

	/* pthread_cond_wait會先解除之前的pthread_mutex_lock鎖定的s_tMutex,
     * 然後阻塞在等待隊列裏休眠,直到再次被喚醒
     * (大多數情況下是等待的條件成立而被喚醒,喚醒後,該進程會先鎖定pthread_mutex_lock(&s_tMutex)
     */
	pthread_cond_wait(&s_tCondvar, &s_tMutex);

	/* 被喚醒之後(執行完子線程對應的InputEventThreadFunction()函數)返回數據 */
	*ptInputEvent = s_tInputEvent;

	/* 釋放互斥量 */
	pthread_mutex_unlock(&s_tMutex);	//解鎖
	
	return 0;
}

2、修改touchscreen.c設備文件,支持滑動翻頁

通過調用tslib庫:

  1. 獲取觸摸屏滑動按下的第一個點startPressured和鬆開最後一個點endReleased
  2. 計算二者的x座標的差值delta = endReleased.x - startPressured.x標準爲滑動距離爲觸摸屏x分辨率的1/5
  3. delta > s_Xres / 3滑動,往右滑,則翻到上一頁
  4. delta < (0 - s_Xres / 3),往左滑,則翻到下一頁
/**
 * @Description: 採用查詢的方式獲讀取touchscreen數據
 * @param ptInputEvent - 表示input設備的結構體.
 * @return 有數據:0 無數據:-1
 */
static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent)
{
	int ret;
	int delta;
	int startflag;
	int endflag;
	struct ts_sample samp;
	struct ts_sample startPressured;
	struct ts_sample endReleased;

	endflag = startflag = 0;
	while(1) {
		/* 如果無數據則休眠 */
		ret = ts_read(s_pTSDev, &samp, 1);
		if (ret == 1) {
			/* 第一次按下 */
			if ((samp.pressure > 0) && (startflag == 0)) {
				/* 記錄數據 */
				startPressured = samp;
				startflag = 1;
			}

			/* 最後鬆開 */
			if (samp.pressure <= 0) {
				endReleased = samp;
				endflag = 1;
			}
			
			/* 鬆開處理數據 */
			if (!startflag && endflag == 1)
				return -1;	//異常情況
			else if((startflag == 1) && (endflag == 1)) {
				delta = endReleased.x - startPressured.x;	//計算差值
				ptInputEvent->time = endReleased.tv;
				ptInputEvent->type = INPUT_TYPE_TOUCHSCREEN;

				if (delta > s_Xres / 3)
					ptInputEvent->val = INPUT_VALUE_UP;		//上翻
				else if(delta < (0 - s_Xres / 3))
					ptInputEvent->val = INPUT_VALUE_DOWN;	//下翻
				else
					ptInputEvent->val = INPUT_VALUE_UNKONW;	//未知
				return 0;
			}		
		} else 
			return -1;
	}
	
	return 0;
}

三、編譯與燒寫

1、編譯

執行make,得到可執行文件show_file

2、運行

由於使用到觸摸屏,需要調用tslib庫來進行校準

  1. 執行./show_file -l,顯示出當前支持的設備
    在這裏插入圖片描述
  2. 執行./shoe_file -s 16 -h HZK16 -f ./MSYH.TTF hz.txt
    執行ps -T,可以看到此時的三個線程:
    在這裏插入圖片描述
    沒有任何外部輸入的時候,CPU佔用率爲0,處於休眠
    輸入時才喚醒程序同時也支持滑動(在這裏展示不了)。
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章