系統編程 POSIX信號量 題目 設計一個程式,主線程需要創建2個子線程之後主線程終止,此時進程中有2個子線程A和B,此時進程中有一個臨界資源flag,子線程A獲取觸摸屏坐標並判斷坐標值是否在LCD屏的左上角,如果坐標範圍滿足左上角,則利用條件量和互斥鎖來喚醒子線程B,子線程B的任務是判斷flag ...
系統編程
POSIX信號量
題目
設計一個程式,主線程需要創建2個子線程之後主線程終止,此時進程中有2個子線程A和B,此時進程中有一個臨界資源flag,子線程A獲取觸摸屏坐標並判斷坐標值是否在LCD屏的左上角,如果坐標範圍滿足左上角,則利用條件量和互斥鎖來喚醒子線程B,子線程B的任務是判斷flag 是否大於0,如果子線程B的條件滿足,則讓子線程B在終端輸出一個字元串即可。要求進程中使用條件量和互斥鎖實現線程的同步以及臨界資源的互斥訪問。
代碼
/***********************************************************************************
*
* file name: pthread_cond.c
* author : [email protected]
* date : 2024/05/31
* function : 該案例是在進程中使用條件量和互斥鎖實現線程的同步以及臨界資源的互斥訪問
* note :
* 由於使用了線程函數介面,所以編譯時需要加上-pthread
* version :
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* **********************************************************************************/
/************************************頭文件*****************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/input.h>
#include <pthread.h>
#include <unistd.h>
/***********************************************************************************/
/************************************全局變數***************************************/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int lcd_fd; //lcd屏文件
int ts_fd; //觸摸屏文件
int *lcd_mp; //指向LCD屏映射空間地址的指針變數
// 臨界資源flag,應該使用volatile修飾,防止編譯器優化
volatile int x,y;
volatile int flag = 0;
/**********************************************************************************/
/***********************************************************************************
*
* name : thread_A_func
* function : 線程A的任務函數,獲取觸摸屏坐標並判斷坐標值是否在LCD屏的左上角,
* 如果坐標範圍滿足左上角,則利用條件量和互斥鎖來喚醒子線程B
* param :
* none
*
* retval : none
* author : [email protected]
* date : 2024/05/31
* note : 由於線程B處於掛起狀態,所以需要線上程A中設定條件喚醒線程B進,防止
* 死鎖情況出現
* version :
*
* *********************************************************************************/
void *thread_A_func(void *arg)
{
//2.讀取輸入設備的信息
struct input_event ts_event;
int cnt = 0;
while(1)
{
read(ts_fd,&ts_event,sizeof(ts_event));
//3.分析讀取的設備信息 (type + code + value)
if (ts_event.type == EV_ABS) //說明是觸摸屏
{
if (ts_event.code == ABS_X) //說明是X軸
{
cnt++;
x = ts_event.value * 800 / 1024;
}
if (ts_event.code == ABS_Y) //說明是Y軸
{
cnt++;
y = ts_event.value * 480 / 600;
}
if(cnt >= 2)
{
cnt = 0;
printf("x = %d, y = %d\n",x,y);
// 用互斥鎖上鎖
pthread_mutex_lock(&mutex);
//判斷坐標值是否在LCD屏左上角
if (x >= 0 && x <= 200 && y >= 0 && y <= 200)
{
flag = 1;
//用條件來喚醒子線程B
pthread_cond_signal(&cond);
}
// 用互斥鎖解鎖
pthread_mutex_unlock(&mutex);
}
}
}
}
/***********************************************************************************
*
* name : thread_B_func
* function : 線程B的任務函數,判斷fag 是否大於 0,如果子線程B的條件滿足,
* 則讓子線程B在終端輸出字元串
* param :
* none
*
* retval : none
* author : [email protected]
* date : 2024/05/31
* note : 由於經過線程A的信號通知,flag 變為1,所以線程B的條件滿足,執行線程B的
* 任務函數後,需對flag的值進行修改,防止死鎖情況出現
* version :
*
* *********************************************************************************/
void *thread_B_func(void *arg)
{
while (1)
{
// 用互斥鎖上鎖
pthread_mutex_lock(&mutex);
// 判斷flag是否大於0
if (flag <= 0)
{
pthread_cond_wait(&cond, &mutex);
}
printf("The coordinates are in the upper left corner\n");
flag = 0;
// 用互斥鎖解鎖
pthread_mutex_unlock(&mutex);
}
}
int main()
{
//打開LCD屏
lcd_fd = open("/dev/fb0",O_RDWR);
//打開觸摸屏
ts_fd = open("/dev/input/event0",O_RDWR);
//2.對LCD進行記憶體映射 mmap
lcd_mp = (int *)mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
// 初始化讀寫鎖
// pthread_rwlock_init(&rwlock, NULL);
// 初始化互斥鎖
pthread_mutex_init(&mutex, NULL);
// 初始化條件變數
pthread_cond_init(&cond, NULL);
// 創建子線程B
pthread_t thread_B;
pthread_create(&thread_B, NULL, thread_B_func, NULL);
// 創建子線程C
pthread_t thread_A;
pthread_create(&thread_A, NULL, thread_A_func, NULL);
// 把子線程AB設置為分離態
pthread_detach(thread_B);
pthread_detach(thread_A);
// 主線程終止
pthread_exit(NULL);
return 0;
}