首页 > 编程语言 >系统编程练习题----利用条件量和互斥锁,实现两个线程之间的同步与互斥

系统编程练习题----利用条件量和互斥锁,实现两个线程之间的同步与互斥

时间:2024-05-31 20:54:32浏览次数:15  
标签:练习题 ts ---- 互斥 触摸屏 线程 include event

目录

题目

image

解析

​ 该题主要依靠条件量和互斥锁来实现线程之间的同步与互斥,分析主线程、线程A和线程B的任务如下:

主线程:

  1. 打开LCD屏和触摸屏的硬件文件,并分别存储两个文件的文件描述符,方便后面进行条件判断。
  2. 开启线程A和线程B。
  3. 定义并初始化条件量和互斥量,方便后续线程内进行上锁和挂起步骤

线程A:

  1. 读取触摸屏坐标,并对读取到的坐标值进行判断。
  2. 坐标条件判断满足后,利用pthread_cond_signal()函数接口对线程B中挂起的条件量进行唤醒操作。

线程B:

  1. 当flag条件不满足时,进入挂起状态,等待线程A的唤醒,再次对flag条件进行判断。
  2. 当flag条件满足且自身处于唤醒状态时,输出相应的字符串到终端。

代码

/********************************************************************************
*
*	file name:	demo.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>
#include <errno.h>
#include <string.h>
#include <stdlib.h>


/****************************全局变量*********************************************/
volatile int flag;          //临界资源,用于条件判断是否满足输出字符串
int *lcd_mp;                //指向LCD屏映射空间地址的指针变量
int ts_fd;                  //触摸屏文件
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; //定义一个互斥量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;        //定义一个条件量

// #define DEBUG  //调试代码用,开启后可看到触摸坐标

/********************************************************************************
*
*	name	 :	thread_A_task
*	function :  线程A的任务函数,实现对触摸屏坐标的判断以及条件唤醒线程B
*	param :  
*				none
*				
*	retval	 :  none
*	author	 :  [email protected] 
*	date	 :  2024/05/31
* 	note	 :  由于线程B处于挂起状态,所以一定要在线程A中设定条件对线程B进行唤醒,防止
*               死锁情况出现
*   version  :
* 	
* *****************************************************************************/
void *thread_A_task(void *arg)
{   
    //定义触摸屏参数变量
    struct input_event ts_event;
    //定义一个变量,用于判断坐标是否读取完整
    int cnt = 0;
    //定义两个变量,分别存触摸屏横坐标与纵坐标
    int x = -1, y = -1;

    //循环判断触摸屏坐标是否满足“处于左上角”条件
    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;

            #ifdef DEBUG
            //调试代码用
            printf("x = %d  y = %d\n",x,y);
            #endif

            //上锁
            pthread_mutex_lock(&fastmutex);
            //条件判断
            if(x >= 0 && x <= 200 && y >= 0 && y <= 200 )
            {
                //清空获取坐标
                x = -1;
                y = -1;

                //将标志量置为一
                flag = 1;
                // 条件满足时唤醒线程B
                pthread_cond_signal(&cond);
            }
            // 解锁
            pthread_mutex_unlock(&fastmutex);

        }

    }
}

/********************************************************************************
*
*	name	 :	thread_B_task
*	function :  线程B的任务函数,在flag小于0时挂起,等待线程A的唤醒;在唤醒状态下且条件
*               满足时,在终端输出一串字符串
*	param :  
*				none
*				
*	retval	 :  none
*	author	 :  [email protected] 
*	date	 :  2024/05/31
* 	note	 :  由于线程B处于挂起状态,所以一定要在线程A中设定条件对线程B进行唤醒,防止
*               死锁情况出现
*   version  :
* 	
* *****************************************************************************/
void *thread_B_task(void *arg)
{
    //循环判断输出字符串条件是否满足
    while(1)
    {
        //上锁
        pthread_mutex_lock(&fastmutex);

        while(!flag)
        {
            pthread_cond_wait(&cond, &fastmutex);
        }
        printf("Touch coordinates in the upper left corner~\n");
        flag = 0;

        // 解锁
        pthread_mutex_unlock(&fastmutex);
    }

}


int main(int argc,const char *argv[])
{
    /****条件准备****/
    // 打开LCD
    int lcd_fd = open("/dev/fb0", O_RDWR);
    if(lcd_fd == -1)
    {
        fprintf(stderr, "open error, errno : %d, %s\n", errno, strerror(errno));
        exit(1);
    }

    // 对LCD进行内存映射  mmap
    lcd_mp = (int *)mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if(lcd_mp == MAP_FAILED)
    {
        fprintf(stderr, "mmap error, errno : %d, %s\n", errno, strerror(errno));
        exit(2);
    }

    // 打开触摸屏
    ts_fd = open("/dev/input/event0", O_RDWR);
    if(ts_fd == -1)
    {
        fprintf(stderr, "open error, errno : %d, %s\n", errno, strerror(errno));
        exit(3);
    }

    //初始化一个互斥锁
    pthread_mutex_init(&fastmutex, NULL);

    //初始化一个条件量
    pthread_cond_init(&cond, NULL);

    //创建两个线程:线程A和线程B
    pthread_t thread_A;
	pthread_t thread_B;
    pthread_create(&thread_A, NULL, thread_A_task, NULL);
    pthread_create(&thread_B, NULL, thread_B_task, NULL);

    //将线程A设定为分离模式
    pthread_detach(thread_A);
    pthread_detach(thread_B);

    //关闭主线程
    pthread_exit(NULL);
}

结果展示

image

标签:练习题,ts,----,互斥,触摸屏,线程,include,event
From: https://www.cnblogs.com/fly-home/p/18225263

相关文章

  • Codeforces Round 949 (Div. 2)
    榜单#提交者=*ABCDEF1(2055)gutongxing20261388-1488900A#include<bits/stdc++.h>usingnamespacestd;intT,n,m;signedmain(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); printf(&quo......
  • BUUCTF-Misc(81-90)
    从娃娃抓起第一句话是中文电码中文电码查询-中文电码转换-中文电码对照表(bmcx.com)第二句话是五笔编码汉字五笔编码批量查询:86版五笔编码、98版五笔编码、18030版五笔编码;五笔编码反查汉字-千千秀字(qqxiuzi.cn)人工智能也要从娃娃抓起flag{3b4b5dccd2c008fe7e......
  • 用Python脚本迁移MongoDB数据到金仓-kingbase数据库
    1、首先需要明确MongoDB与kingbase的对应关系,collection相当于table,filed相当于字段,根据这个对应关系创建表;此次迁移的MongoDB里的数据字段是:_id(自动生成的objectid),image(转成二进制存储的文档)所以在金仓里创建表createtableadmin(idvarchar,imagebytea);2、安装Python环境......
  • vue之vuex使用
    如图所示,它是一个程序里面的状态管理模式,它是集中式存储所有组件的状态的小仓库,并且保持我们存储的状态以一种可以预测的方式发生变化。对于可以预测,现在我不多做说明,相信在看完这篇文章之后,你就会有自己的理解。第一步,了解Vuex......
  • RC-u3 骰子游戏
    睿抗2023本科第三题//包含C++标准库,用于各种通用功能,如输入输出和排序#include<bits/stdc++.h>usingnamespacestd;//全局变量声明intn,k[6],level1,level2,t[6],f[32],r[32];//函数get_level:根据五个骰子的点数,返回当前获胜等级intget_level(ints[]){//首......
  • 管理 Windows Server 2022 中 DNS 服务器相关的 CMD 批处理命令的示例
    一些与管理WindowsServer2022中DNS服务器相关的CMD批处理命令的示例:创建新的DNS区域:CopyCodednscmd/ZoneAddexample.com/Primary删除DNS区域:CopyCodednscmd/ZoneDeleteexample.com/f添加区域转发:CopyCodednscmd/ZoneResetForwardersexample......
  • 防抖函数 debounce 和节流函数 throttle
    明天考蓝桥web,复习下debounce和throttledebounce防抖函数应用场景:即时响应式的输入框、按钮等(毕竟没人知道用户究竟会怎么用)前置知识:闭包:与很多主流编程语言不同,JavaScript在变量作用域上具有一些特殊表现。(摘自mdn)闭包是由函数以及声明该函数的词法环境组合而成的。该环......
  • 使用条件量和互斥锁实现线程的同步以及临界资源的互斥访问
    /********************************************************************** name :* function:主线程需要创建2个子线程之后主线程终止,此时进程中有2个子线程A和B,此时进程中有一个临界资源fag,子线程A获取触摸屏坐标并判断坐标值是否在LCD屏的左上角,如果坐标范围满足......
  • 进程控制(互斥锁)
    进程控制(互斥锁)目录进程控制(互斥锁)头文件全局变量234验证头文件/********************************************************************** name :* function:主线程需要创建2个子线程之后主线程终止,此时进程中有2个子线程A和B,此时进程中有一个临界资源fag,子线程......
  • 系统编程
    系统编程目录系统编程1.管道通信1.1匿名管道(pipe)1.2命名管道(fifo)2.消息队列3.共享内存4.信号量1.管道通信1.1匿名管道(pipe)//创建子线程pid_tfork(void);/****************************************返回值 成功(父进程)>0/(子进程)0 失败 -1(父进程,不创建子......