进程控制(互斥锁)
头文件
/********************************************************************
*
* name :
* function :主线程需要创建2个子线程之后主线程终止,此时进程中有2个子线程A和 B,此时进程中有一个临界资源 fag,
子线程A获取触摸屏坐标并判断坐标值是否在LCD屏的左上角,如果坐标范围满足左上角,则利用条件量和互斥锁来唤醒子线程B,
子线程B的任务是判断fag 是否大于 0,如果子线程B的条件满足,则让子线程B在终端输出一个字符串即可。
要求进程中使用条件量和互斥锁实现线程的同步以及临界资源的互斥访问
* argument :
* @n :需要计算的值n
*
* retval :
* author : 17647576169@163.com
* date : 2024年5月31日
* note :
* 变量
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
* 初始化
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
启动唤醒
int pthread_cond_signal(pthread_cond_t *cond);
唤醒所有
int pthread_cond_broadcast(pthread_cond_t *cond);
等待
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
等待一段时间
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
销毁
int pthread_cond_destroy(pthread_cond_t *cond);
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem_t *sem_open(const char *name, int oflag,
mode_t mode, unsigned int value);
* *****************************************************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <sys/ipc.h>
#include <linux/input.h>
#include <sys/mman.h>
全局变量
volatile int fag = 0, cnt, x, y, a; // 临界资源 fag,cnt,x,y
int *lcd_mp; // lcd映射
int lcd_fd, ts_fd; // lcd和触摸屏
struct input_event ts_event; // 触摸信息存放
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 条件量
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
sem_t *sem;
char buf[10] = {1};
2
/********************************************************************
*
* name :funcA
* function :获取触摸屏坐标并判断坐标值是否在LCD屏的左上角,如果坐标范围满足左上角,则利用条件量和互斥锁来唤醒子线程B
* argument :
* @n :需要计算的值n
*
* retval :pthread_cond_broadcast pthread_cond_destroy
pthread_cond_init pthread_cond_signal
pthread_cond_timedwait pthread_cond_wait
* author : 17647576169@163.com
* date : 2024年5月31日
* note :
*
* *****************************************************************/
void *
funcA(void *arc)
{
pthread_mutex_lock(&mut);
for (;;)
{ // read函数默认会阻塞的,也就是没有读取数据,则卡这句话
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 && x > 0 && x < 100 && y > 0 && y < 100)
{
fag = 3;
}
printf("唤醒\n");
// 唤醒B
pthread_cond_signal(&cond);
// 还锁
pthread_mutex_unlock(&mut);
}
}
}
3
/********************************************************************
*
* name :funcB
* function :
* argument :判断fag 是否大于 0,如果子线程B的条件满足,则让子线程B在终端输出一个字符串
* @n :需要计算的值n
*
* retval :
* author : 17647576169@163.com
* date : 2024年5月31日
* note :
*
* *****************************************************************/
void *funcB(void *arc)
{
for (;;)
{
pthread_mutex_lock(&mut);
if (fag == 3)
{
pthread_cond_wait(&cond, &mut);
printf("哦哦哦哦哦哦哦哦哦\n");
fag = 0;
}
// sleep(3);
pthread_mutex_unlock(&mut);
}
}
4
int main(int argc,
char const *argv[])
{
buf[0] = 'a';
// 1.打开LCD open
lcd_fd = open("/dev/fb0", O_RDWR);
// 2.对LCD进行内存映射 mmap
lcd_mp = (int *)mmap(NULL,
800 * 480 * 4,
PROT_READ | PROT_WRITE, MAP_SHARED,
lcd_fd, 0);
ts_fd = open("/dev/input/event0", O_RDWR);
// 创建两个线程
pthread_t Afunc;
pthread_t Bfunc;
pthread_create(&Afunc, NULL, funcA, NULL);
pthread_create(&Bfunc, NULL, funcB, NULL);
// 初始化
pthread_cond_init(&cond, NULL);
// 结束主进程
pthread_exit(NULL);
return 0;
}
验证
点击后
[root@GEC6818 /ljw]#./a
唤醒
唤醒
哦哦哦哦哦哦哦哦哦
唤醒
唤醒
哦哦哦哦哦哦哦哦哦
唤醒
唤醒
哦哦哦哦哦哦哦哦哦
唤醒
唤醒
唤醒
唤醒
唤醒