实时系统中的线程安全数据传输架构(C语言)

问题描述 投票:0回答:1

短: 我有一个负责与设备通信的模型。该模型有两个线程:一个用于通信(读取和写入),另一个用于记录结果。使用互斥体确保线程安全不是问题。

现在,我有了使用此模型从设备获取/发送值的主程序。假设我有一个缓冲区。主程序本身是多线程的,这意味着我需要保护多个线程之间以及与设备模型通信时的缓冲区。

对所有事情使用一个全局互斥体违反了模型原则,并且会让一切变得更加复杂。

如何在通信模型和主程序之间建立线程安全的接口?

长: 请允许我用一个简单的例子来说明这个问题。

我的设备模型结构如下:

设备.h

#ifndef DEVICE_H
#define DEVICE_H

struct d_in {
    int x;
    int y;
    int z;
};

struct d_out {
    int x;
    int y;
    int z;
};

struct device {
    struct d_in input;
    struct d_out output;
    pthread_mutex_t mutex;
    sem_t sem_data;
};

void *communication_thread(void *arg);
void *logging_thread(void *arg);

void _init_device();
void _read_input(struct d_in *input);
void _write_output(const struct d_out *output);

//////////////////////////////////////
void transfer_data(struct *dev)    // that what I want as interface

#endif /* DEVICE_H */

设备.c

#include "device.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "special_card_for_reading_from_device_.h"

static struct device dev;

void init_device() {
    dev.input.x = 0;
    dev.input.y = 0;
    dev.input.z = 0;
    dev.output.x = 0;
    dev.output.y = 0;
    dev.output.z = 0;
    pthread_mutex_init(&dev.mutex, NULL);
    sem_init(&sem_data,NULL, NULL);
}

void read_input() {
    pthread_mutex_lock(&dev.mutex);
    read_fucntion(&dev.input);
    pthread_mutex_unlock(&dev.mutex);
}

void write_output() {
    pthread_mutex_lock(&dev.mutex);
    write_fucntion(&dev.output);
    pthread_mutex_unlock(&dev.mutex);
}

void *communication_thread(void *arg) {
    while (1) {
        read_input();
        write_output();
        sem_post(&sem_data);
        sleep(1); // Simulating communication delay
    }
    return NULL;
}

void *logging_thread(void *arg) {
    FILE *fp = fopen("log.txt", "w");
    if (fp == NULL) {
        perror("Error opening log file");
        exit(EXIT_FAILURE);
    }

    while (1) {
        sem_wait(&sem_data);
        pthread_mutex_lock(&dev.mutex);
        fprintf(fp, "Input: %d %d %d\n", dev.input.x, dev.input.y, dev.input.z);
        fprintf(fp, "Output: %d %d %d\n\n", dev.output.x, dev.output.y, dev.output.z);
        pthread_mutex_unlock(&dev.mutex);
        sleep(2); // Logging interval
    }

    fclose(fp);
    return NULL;
}

然后我就有了带有线程的主程序

transfer

void *transfer(void *arg) {
    while (1) {
        // how to protect this section
        transfer(&buffer_dev_data);
        //////////////////////////
        sleep(1);
    }
    return NULL;
}
void *another_thread(void *arg) {
    while (1) {
        // how to protect this section
        operations_on_bufffer(buffer_dev_data);
        //////////////////////////
        sleep(1);
    }
    return NULL;
}

使用两个互斥锁来保护同一行是否会导致死锁等问题?如果我在传输函数内部使用一个互斥锁,并在其外部使用另一个互斥锁,它最终看起来会是一样的:

mutex_lock(&mut_B);
mutex_look(&mut_A);
// critical section
mutex_unlock((&mut_A);
mutex_unlock(&mut_B);

有问题吗?

注意事项: 该程序是为具有实时内核的实时系统(RT-Linux)而设计的。它要复杂得多,并且还包括线程的优先级。然而,目前这只是附加信息。

c multithreading thread-safety posix software-design
1个回答
0
投票

我不同意你的说法“对所有事情都使用一个全局互斥体违反了模型原则”。

您的 struct device 中有一组易失性数据,名为

input
output
,只能由
one
线程访问。为了避免并发访问,您需要 one 保护器 - one 互斥体。 考虑使用

PTHREAD_MUTEX_RECURSIVE

属性来允许递归锁。

还可以考虑使用 MRSW 锁(多个读取器/单个写入器),它允许从多个线程进行只读访问而不会阻塞。

© www.soinside.com 2019 - 2024. All rights reserved.