Я пытаюсь выяснить, как сделать фоновый процесс в C, я ничего не нашел в Интернете. Я думаю, что причина, по которой я не нашел много, состоит в том, что я, возможно, не задаю правильный вопрос.
Я работаю над школьным проектом с использованием сборки ARM и C с Raspberry Pi с использованием операционной системы Raspbian и компилятор G CC.
Для своего проекта я решил сделать простую систему сигнализации. Идея проста, у меня есть 3 ИК-датчика, которые обнаруживают движение и запускают зуммер при обнаружении движения.
Вместо использования аппаратного обеспечения для клавиатуры, я выбрал GUI, где вы можете поставить / снять систему с охраны, а также сменить пароль и включить / выключить определенные датчики. Например, если вы хотите отключить датчики движения 1 и 2, на GUI будут кнопки для этого.
Проблема, с которой я столкнулся, заключается в том, что используемая библиотека GUI , (GTK3 и Glade) управляется событиями, поэтому если кнопка не нажата, она ничего не сделает. Это было бы хорошо, если бы я хотел включить зуммер только при обнаружении движения, потому что я мог бы сделать свой собственный l oop, чтобы следить за движением, но я действительно хочу повторно воспроизвести какой-то тип паттерна (пример: 3 коротких звука) непрерывно, пока не будет снята сигнализация). В то же время я все еще хочу иметь доступ к кнопкам GUI, чтобы можно было отключить будильник. Это заставляет меня думать, что мне нужно прерывание или фоновый процесс.
Я уверен, что есть много способов решить эту проблему, но я действительно хотел создать своего рода фоновую подпрограмму, которая могла бы выполняться параллельно основной Задача, когда пользователь вооружает систему. Я спросил своего профессора о том, как многопоточность в ARM, но он сказал, что мы не расскажем об этом в классе. Я читал, что стандартная библиотека C не поддерживает многопоточность, но я уверен, что есть способ сделать это. Если бы кто-то мог просто указать мне правильное направление, я был бы благодарен.
Вот код GUI, который я написал, наряду с другим модулем, который я закончил, чтобы получить рабочий прототип, прежде чем я начну подключать датчики , Ничто из этого не содержит ассемблерного кода, потому что я еще не дошел до этого, я хотел, чтобы он работал на более высоком уровне, а затем разбивал некоторые детали до сборки. Если вам нужны все файлы, я с удовольствием предоставлю их, но я думаю, что этого будет достаточно, чтобы вы все поняли, что я пытаюсь сделать.
Код GUI:
/*****************************************************
* Title: User Interface
* Author:
* Date: 2/15/20
* Class: CISP 2410
*
* Description:
* ! This header file contains all of the function
* ! Declarations and definitions for the GUI
* ! Everything involving the GUI will be in
* --> this header
*
*****************************************************/
#include <gtk/gtk.h> // For gtk stuff
#include <stdlib.h> // Standard Library
#include "GUI_Ctrl.h" // Prototypes
#include "Alarm.h" // Alarm Functions
/* Private Functions */
static void UpdateLcdDisplay(char keyPadValue);
static void ClearLcdDisplay(void);
static void UpdateDisplay(void);
/***********************************/
// Global Variables
GtkWidget *g_Lbl_Lcd;
GtkWidget *g_Lbl_SysStat;
GtkWidget *g_Lbl_LogStat;
char inputBuffer[6] = {0x0};
int charCounter = 0;
const int INPUT_LIMIT = 6;
/*****************************************************
* ! Initializes all of the GUI elements
* ! Adds CSS attributes to GUI elements
* ! Also handles the formatting of text
*****************************************************/
void GUI_INIT(int argc, char* argv[])
{
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *g_Lbl_Lbl1;
GtkWidget *g_Lbl_Lbl2;
// Get pointer to css file
GtkCssProvider *cssProvider = gtk_css_provider_new ();
gtk_css_provider_load_from_path(cssProvider,"UI/style.css",NULL);
gtk_init(&argc, &argv);
// get pointer to xml dat file
builder = gtk_builder_new_from_file("UI/HelloWorld.glade");
// Get pointer to main window
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
// Get pointer to labels
g_Lbl_Lcd = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_Lcd"));
g_Lbl_SysStat = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_SysStat"));
g_Lbl_LogStat = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_LogStat"));
g_Lbl_Lbl1 = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl1"));
g_Lbl_Lbl2 = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl2"));
// Align Text Right
gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lcd), 1);
// Align Text Left
gtk_label_set_xalign (GTK_LABEL(g_Lbl_SysStat), 0);
gtk_label_set_xalign (GTK_LABEL(g_Lbl_LogStat), 0);
gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lbl1), 0);
gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lbl2), 0);
// Add CSS
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_USER);
// Finish setup and start GUI
g_object_unref(builder);
gtk_widget_show(window);
UpdateDisplay();
gtk_main();
return;
}
// called when window is closed
void on_window_main_destroy()
{
gtk_main_quit();
}
/*------------------END SECTION------------------*/
static void UpdateDisplay(void)
{
ClearLcdDisplay();
gtk_label_set_text(GTK_LABEL(g_Lbl_SysStat), GetSysStat());
gtk_label_set_text(GTK_LABEL(g_Lbl_LogStat), GetLogStat());
return;
}
static void UpdateLcdDisplay(char keyPadValue)
{
if (charCounter >= INPUT_LIMIT)
ClearLcdDisplay();
else
{
inputBuffer[charCounter] = keyPadValue;
charCounter++;
}
gtk_label_set_text(GTK_LABEL(g_Lbl_Lcd), inputBuffer);
return;
}
static void ClearLcdDisplay(void)
{
memset(inputBuffer, 0, 6);
charCounter = 0;
gtk_label_set_text(GTK_LABEL(g_Lbl_Lcd), inputBuffer);
return;
}
/*------------------ EVENT HANDLERS ------------------*/
void on_btn0_clicked(void) {UpdateLcdDisplay('0');}
void on_btn1_clicked(void) {UpdateLcdDisplay('1');}
void on_btn2_clicked(void) {UpdateLcdDisplay('2');}
void on_btn3_clicked(void) {UpdateLcdDisplay('3');}
void on_btn4_clicked(void) {UpdateLcdDisplay('4');}
void on_btn5_clicked(void) {UpdateLcdDisplay('5');}
void on_btn6_clicked(void) {UpdateLcdDisplay('6');}
void on_btn7_clicked(void) {UpdateLcdDisplay('7');}
void on_btn8_clicked(void) {UpdateLcdDisplay('8');}
void on_btn9_clicked(void) {UpdateLcdDisplay('9');}
void on_btnClear_clicked(void) {ClearLcdDisplay();}
void on_btnEnter_clicked(void) {UpdateDisplay();}
void on_btnLogin_clicked(void)
{
LoginLogout(inputBuffer);
UpdateDisplay();
return;
}
void on_btnArm_clicked(void)
{
ArmDisarm();
UpdateDisplay();
return;
}
Вот код для будильника. Обратите внимание, это всего лишь прототип, я буду использовать библиотеку wiringPi, как только разберусь с этим прерыванием.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Alarm.h"
// Private Function Prototypes
static int PasswordIsCorrect(char* pswAttempt);
// Global Variables
static int armed = 0;
static int loggedIn = 0;
static int PasswordIsCorrect(char* pswAttempt)
{
const char PASSWORD[] = "123";
if (!strcmp(pswAttempt, PASSWORD))
return 1;
else
return 0;
}
/*
* Returns a string,
* Used to update label
*/
char* GetSysStat(void)
{
if(armed)
return "Armed";
else
return "Disarmed";
}
/*
* Returns a string,
* Used to update label
*/
char* GetLogStat(void)
{
if(loggedIn)
return "Logged In";
else
return "Logged Out";
}
void ArmDisarm(void)
{
if (loggedIn && armed)
armed = 0;
else if(loggedIn && !armed)
armed = 1;
return;
}
void LoginLogout(char* pswAttempt)
{
if(PasswordIsCorrect(pswAttempt))
loggedIn = 1;
else
loggedIn = 0;
return;
}
Спасибо всем за потраченное время!