#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <sys/time.h> #define WATCHDOG_TIMEOUT_MS 1000 // 看门狗超时时间(毫秒) #define HEARTBEAT_INTERVAL_MS 500 // 心跳信号发送间隔(毫秒) int t_for_test = 0; // 子进程的主程序逻辑 void child_process() { while (1) { // 模拟子进程的工作 printf("子进程运行中...\n"); usleep(HEARTBEAT_INTERVAL_MS * 1000); // 模拟工作间隔 t_for_test++; if(t_for_test > 10){ t_for_test = 0; exit(0); } } } // 父进程的看门狗逻辑 void parent_process(pid_t child_pid) { int status; while (1) { // 检查子进程是否存活 pid_t result = waitpid(child_pid, &status, WNOHANG); if (result == 0) { // 子进程仍在运行 printf("子进程正常运行\n"); } else if (result > 0) { // 子进程已退出 if (WIFEXITED(status)) { printf("子进程正常退出,退出码: %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("子进程被信号终止,信号: %d\n", WTERMSIG(status)); } // 重启子进程 printf("重启子进程...\n"); child_pid = fork(); if (child_pid == 0) { // 子进程 child_process(); exit(0); // 子进程退出 } else if (child_pid < 0) { perror("fork failed"); exit(EXIT_FAILURE); } } else { // waitpid 出错 perror("waitpid failed"); exit(EXIT_FAILURE); } // 父进程等待一段时间后再次检查 usleep(WATCHDOG_TIMEOUT_MS * 1000); } } int main(void) { // 创建子进程 pid_t child_pid = fork(); if (child_pid == 0) { // 子进程 child_process(); exit(0); // 子进程退出 } else if (child_pid < 0) { // fork 失败 perror("fork failed"); exit(EXIT_FAILURE); } // 父进程 parent_process(child_pid); return 0; } 如果这样写,子进程发生卡死或异常退出,父进程是否可以重启子进程

时间: 2025-07-10 20:47:51 浏览: 24
<think>好的,我现在需要回答用户关于在C语言中父进程如何检测子进程崩溃或卡死,并通过waitpid自动重启子进程的问题。首先,我得回顾一下进程管理和waitpid的相关知识。 用户提到子进程可能崩溃或卡死,父进程需要检测这两种情况并重启。根据引用[2]和[3],当子进程终止时,无论是正常还是异常,内核会保留其退出状态,父进程可以通过wait或waitpid获取这些信息。对于正常终止,可以用WIFEXITED和WEXITSTATUS,异常终止则用WIFSIGNALED和WTERMSIG来获取信号。 但问题在于,如果子进程卡死(比如陷入死循环或阻塞),它并没有终止,此时waitpid无法立即获取状态。这时候父进程如何检测呢?可能需要引入超时机制,或者使用非阻塞的方式定期检查子进程状态。另外,可能需要信号处理,比如SIGCHLD来通知父进程子进程状态变化。 另外,引用[1]提到父进程异常退出可能导致子进程成为孤儿,但这里的情况相反,是子进程出问题,父进程需要处理。重启子进程的可行性方面,父进程在检测到子进程终止后,可以再次fork并执行子进程,这应该是可行的。但如果是卡死,父进程需要主动终止子进程,比如发送SIGKILL,然后再重启。这可能涉及到进程组的控制,防止产生僵尸进程。 正确性方面,需要确保在waitpid之后正确回收资源,避免僵尸进程。同时,处理信号时要小心竞态条件,比如在信号处理函数中调用waitpid。此外,多次重启可能需要限制次数,防止无限重启导致系统资源耗尽。 代码实现的大致步骤应该是:父进程fork子进程,使用waitpid非阻塞轮询或结合信号处理。如果子进程退出,根据状态判断是否重启。如果子进程卡死,父进程需要设置超时,超时后发送终止信号,然后重启。 可能需要考虑的问题:如何判断子进程卡死?可以通过心跳机制、超时检测,或者监视子进程的活动。例如,父进程设置一个定时器,如果子进程在指定时间内没有响应,则认为其卡死,进而终止并重启。 此外,处理多个子进程的情况可能需要更复杂的结构,比如维护子进程的PID列表,但用户的问题可能只涉及单个子进程的情况。 总结步骤: 1. 父进程fork子进程,记录其PID。 2. 使用waitpid在非阻塞模式下轮询,或处理SIGCHLD信号。 3. 检测子进程退出状态,判断是否正常终止或异常终止。 4. 如果子进程退出,父进程重新启动它。 5. 对于卡死的子进程,父进程需主动检测(如超时),发送SIGKILL终止,再重启。 6. 处理可能的竞态条件和资源回收问题。 需要注意,waitpid只能检测已终止的子进程,无法直接检测卡死。因此,卡死的处理需要额外的机制,比如设置超时,如果子进程在指定时间内未完成某个任务,则认为其卡死。 现在需要将这些思路整理成结构化的回答,并确保符合用户的要求,如正确引用文献,使用适当的中文表达,以及生成相关问题。</think>在C语言中,父进程通过`waitpid`检测并自动重启子进程的可行性及正确性分析如下: ### 一、检测子进程终止的可行性 1. **正常/异常终止检测** 当子进程终止(正常退出或被信号终止)时,父进程可通过`waitpid`获取状态信息: - 使用`WIFEXITED(status)`判断是否正常退出,`WEXITSTATUS(status)`获取退出码[^3] - 使用`WIFSIGNALED(status)`判断是否被信号终止,`WTERMSIG(status)`获取信号编号 代码示例: ```c int status; pid_t pid = waitpid(child_pid, &status, WNOHANG); if (pid > 0) { if (WIFEXITED(status)) { printf("子进程正常退出,状态码:%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("子进程被信号终止,信号编号:%d\n", WTERMSIG(status)); } restart_child(); // 重启子进程 } ``` 2. **非阻塞检测** 通过`WNOHANG`标志实现非阻塞轮询,避免父进程挂起: ```c pid_t pid = waitpid(child_pid, &status, WNOHANG); ``` ### 二、处理子进程卡死的挑战 1. **卡死检测的局限性** `waitpid`无法直接检测未终止的子进程。需通过以下方法间接检测: - **超时机制**:记录子进程最后活跃时间,超时后判定为卡死 - **心跳检测**:子进程定期向父进程发送心跳信号 - **IPC监控**:通过管道或共享内存检测子进程响应 2. **强制终止卡死进程** 判定卡死后,父进程需主动终止子进程: ```c kill(child_pid, SIGKILL); // 发送不可屏蔽的终止信号 waitpid(child_pid, &status, 0); // 确保回收资源 ``` ### 三、自动重启的正确性保障 1. **避免僵尸进程** 必须调用`waitpid`彻底回收子进程资源,否则会导致僵尸进程积累[^2]。 2. **防止竞态条件** 在信号处理函数中使用异步信号安全函数,例如: ```c void sigchld_handler(int sig) { int saved_errno = errno; while (waitpid(-1, NULL, WNOHANG) > 0); errno = saved_errno; } ``` 3. **端口占用问题** 若子进程继承了网络端口,重启前需确保旧进程完全终止,避免出现引用[1]描述的端口冲突问题[^1]。 ### 四、完整实现框架 ```c #include <sys/wait.h> #include <unistd.h> void restart_child() { pid_t pid = fork(); if (pid == 0) { execl("./child_program", "child_program", NULL); _exit(EXIT_FAILURE); // exec失败时退出 } // 父进程记录新pid child_pid = pid; } int main() { signal(SIGCHLD, sigchld_handler); restart_child(); while (1) { // 心跳检测逻辑 if (检测到超时) { kill(child_pid, SIGKILL); waitpid(child_pid, NULL, 0); restart_child(); } sleep(1); } } ``` ### 五、注意事项 1. 重启次数应设置上限,避免无限重启导致系统过载 2. 建议记录子进程崩溃原因(通过`WTERMSIG`等),用于故障分析 3. 对网络服务类子进程,需处理优雅重启(如关闭文件描述符)
阅读全文

相关推荐

// >>> common include #include <iostream> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> // >>> verilator #include <memory> #include <verilated.h> #include <verilated_vcd_c.h> #include "VA_top.h" #include "sdm_config.h" #include "Sdm_node_A.h" using HW =VA_top; uint64_t GlobalMainTime = 0; int main(int argc, char** argv, char**env) { const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext}; const std::unique_ptr<HW> hw {new HW{contextp.get(), "TOP"}}; Sdm_config * shuncfg_ptr = new Sdm_config (sub_node_A_node_name); shuncfg_ptr->arg_parse (argc, argv); Sdm_node_A shunobj (shuncfg_ptr, hw.get(), contextp.get()); Verilated::mkdir("node_node_A_logs"); contextp->debug(0); contextp->randReset(2); contextp->commandArgs(argc, argv); #if VM_TRACE == 1 VerilatedVcdC* tgp = NULL; const char* flag = Verilated::commandArgsPlusMatch("trace"); if (flag && 0 ==strcmp(flag, "+trace")) { Info("Enter Trace!"); contextp->traceEverOn(true); tfp = new VerilatedVcdC; hw->trace(tfp,99); shunobj.fulleval(); std::string filename = shuncfg_ptr->dumpfile(); tfp->open(filename.c_str()); }; #endif shunobj.setup(); bool retmp; int loop = 0; while(1) { //Info("loop %d", loop); shunobj.update(); if (shunobj.finish()) break; do { shunobj.eval(); shunobj.sync(); } while(!shunobj.converge()); #if VM_TRACE == 1 if (flag && 0 == strcmp(flag, "+trace")) { tfp->dump(contextp->time()); } #endif loop++; } hw->final(); return 0; #if VM_TRACE == 1 if (flag && 0 == strcmp(flag, "+trace")){ tfp->close(); } #endif #if VM_COVERAGE Verilated::mkdir("node_node_A_logs"); contextp->coverageep()->write("node_node_A_logs/coverage.dat"); #endif }

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H ----------------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } 以上两个是.h和.cpp代码 --------------------------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>628</height> </rect> <string>MainWindow</string> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="pb_connect"> <rect> <x>40</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>连接</string> </widget> <widget class="QPushButton" name="pb_led0"> <rect> <x>40</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>led0_on</string> </widget> <widget class="QPushButton" name="pb_led1"> <rect> <x>40</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>led1_on</string> </widget> <widget class="QPushButton" name="pb_led2"> <rect> <x>40</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>led2_on</string> </widget> <widget class="QPushButton" name="pb_feng"> <rect> <x>40</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>feng_on</string> </widget> <widget class="QPushButton" name="pb_buzzer"> <rect> <x>140</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>蜂鸣器_on</string> </widget> <widget class="QPushButton" name="pb_humiture"> <rect> <x>140</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>温湿度_on</string> </widget> <widget class="QPushButton" name="pb_photosensitive"> <rect> <x>140</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>光敏_on</string> </widget> <widget class="QPushButton" name="pb_infrared"> <rect> <x>140</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>人体红外_on</string> </widget> <widget class="QPushButton" name="pb_camera"> <rect> <x>140</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>摄像头_on</string> </widget> <widget class="QTextBrowser" name="textBrowser"> <rect> <x>350</x> <y>10</y> <width>421</width> <height>211</height> </rect> </widget> </widget> <widget class="QMenuBar" name="menubar"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>28</height> </rect> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> 以上是.ui代码 --------------------------------------------------------- 目前项目进度: 当前项目结构如下: DXM1txst: DXM1txst.pro Headers: fsmpBeeper.h fsmpElectric.h fsmpEvents.h fsmpFan.h fsmpLed.h fsmpLight.h fsmpProximity.h fsmpsevensegLed.h fsmpTempHum.h fsmpvibrator.h mainwindow.h Sources: main.cpp mainwindow.cpp Forms: mainwindow.ui qtcreator内:ui界面中已经有组件:pb_connect(连接按钮)、pb_led0(电灯1开关按钮)、pb_led1(电灯2开关按钮)、pb_led2(电灯3开关按钮)、pb_feng(风扇开关按钮)、pb_buzzer(蜂鸣器开关按钮)、pb_humiture(温湿度传感器开关按钮)、pb_photosensitive(光敏传感器开关按钮)、pb_infrared(人体红外传感器开关按钮)、pb_camera(摄像头开关按钮)、textBrowser(用于接收和发布的消息显示)。 华清远见元宇宙实验中心物联网仿真系统内:所需的所以硬件的3D场景设计完毕,M4网关单元的Mqtt配置为: 地址:mqtt.yyzlab.com.cn 端口:1883 与应用层、云端交互的Topic: 订阅:1752365375766/APP2AIOTSIM 发布:1752365375766/AIOTSIM2APP 与硬件交互的Topic: 订阅:1752365382482/Device2AIOTSIM 发布:1752365382482/AIOTSIM2Device 与华清远见元宇宙实验中心物联网仿真系统内硬件开关发布的控制码为:电灯0开:{"lamp":true,"id":0},电灯0关:{"lamp":false,"id":0},电灯1开:{"lamp":true,"id":1},电灯1关:{"lamp":false,"id":1},电灯2开:{"lamp":true,"id":2},电灯2关:{"lamp":false,"id":2},风扇开:{"fan":true,"id":0},风扇关:{"fan":false,"id":0},人体红外传感器开:{"infrared ":true,"id":0},人体红外传感器关:{"infrarrared ":false,"id":0},温湿度传感器:{"tem":38.8,"hum":65.7,"id":0},光敏传感器:{"light":43037.0,"id":0} Stm32mp157开发板:所有需要的硬件部署完毕,硬件的.h代码如下(硬件的.h代码已经放入qtcreator项目下的Headers文件夹下,且硬件的所有.h文件内代码都不能再进行修改): fsmpBeeper.h: #ifndef FSMPBEEPER_H #define FSMPBEEPER_H /*************************************************************************** * * 类名:fsmpBeeper * 功能说明:扩展板 蜂鸣器 * 公有函数: * fsmpBeeper() * bool setRate(uint32_t rate) 设置频率 * bool start(void) 启动蜂鸣器 * bool stop(void) 关闭蜂鸣器 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> /* FSMP开发板(linux)蜂鸣器操作类 v0 2023/1/9 by 张城 */ class fsmpBeeper:public QObject{ Q_OBJECT public: explicit fsmpBeeper(const char *device = "/dev/input/event0", QObject *parent = nullptr) :QObject(parent) { event.type = EV_SND; time.tv_sec = 1; time.tv_usec = 0; event.time = time; beeper_fd = ::open(device,O_RDWR); if(beeper_fd < 0) { perror("open_beeper"); return; } }; ~fsmpBeeper() { ::close(beeper_fd); } /* * Description: 设置频率值 * input: rate 频率 * output: null * return: 成功true/失败false */ bool setRate(uint32_t rate = 1000) { if(rate > 0) { event.code = SND_TONE; event.value = rate; return true; } return false; } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ bool start(void) { int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool stop(void) { struct input_event event; event.type = EV_SND; event.code = SND_BELL; event.value = 0000; time.tv_sec = 1; time.tv_usec = 0; event.time = time; int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } private: int beeper_fd; //设备文件描述符 struct input_event event; struct timeval time; }; #endif // FSMPBEEPER_H ------------------------------------------------------- fsmpElectric.h: #ifndef ELC_H #define ELC_H /*************************************************************************** * * 类名:fsmpElectric * 功能说明:扩展板 电气信息检测 * 公有函数: * fsmpElectric() * float voltagemV(void) 获取电压mv(旋钮控制) * float currentmA(void) 获取电流ma(板载设备真实电流) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpElectric:public QObject{ Q_OBJECT public: explicit fsmpElectric(QObject *parent = nullptr) :QObject(parent) { } ~fsmpElectric(){ } float voltagemV(void) { electric_fd1 = open("/sys/bus/iio/devices/iio:device3/in_voltage1_raw",O_RDONLY|O_NONBLOCK); if(electric_fd1 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd1,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd1); return (float)3300 * val / 65536; } float currentmA(void) { electric_fd0 = open("/sys/bus/iio/devices/iio:device3/in_voltage0_raw",O_RDONLY|O_NONBLOCK); if(electric_fd0 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd0,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd0); return ((((float)3300 * val) /65536)/(10 + 100*1000 + 1000)) * 1000 / 0.1; } private: int electric_fd0; //设备文件描述符 int electric_fd1; //设备文件描述符 }; #endif // ELC_H ------------------------------------------------------- fsmpEvents.h: #ifndef ENV_H #define ENV_H /*************************************************************************** * * 类名:fsmpEvents * 功能说明:扩展板 按钮、人体红外、光闸管、火焰 * 公有函数: * fsmpEvents() * 信号: * void lightTriggered(); 光闸管阻隔 * void flameDetected(); 火焰检测 * void peopleDetected(bool); 人体红外发现true/离开false * void keyPressed(int keynum); 按键按下 keynum: 1、2、3 * void keyRelessed(int keynum); 按键释放 keynum: 1、2、3 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QTimer> #include #include <sys/ioctl.h> #include <QDebug> #include <QProcess> #include <QThread> #include <stdio.h> #include <stdlib.h> class fsmpEvents:public QObject{ Q_OBJECT signals: /* edge trigle !!!*/ void lightTriggered();//光电开关 void flameDetected();//火焰检测 void peopleDetected(bool);//人体红外 void keyPressed(int keynum); void keyRelessed(int keynum); public: explicit fsmpEvents(QObject *parent = nullptr):QObject(parent) { this->gpio_F_open(); this->gpio_E_open(); fs_timer = new QTimer(this); connect(fs_timer,SIGNAL(timeout()),this,SLOT(time_out())); fs_timer->start(10); }; private: bool gpio_F_open(const char *device = "/dev/gpiochip5") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 9; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE|GPIOEVENT_REQUEST_RISING_EDGE; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_1_fd = event_req.fd; int flags = fcntl(key_1_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_1_fd,F_SETFL,flags); event_req.lineoffset = 8; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_3_fd = event_req.fd; flags = fcntl(key_3_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_3_fd,F_SETFL,flags); #if 0 event_req.lineoffset = 5; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } fire_fd = event_req.fd; flags = fcntl(fire_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(fire_fd,F_SETFL,flags); #endif // fire req.lineoffsets[0] = 5; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "fire"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } fire_fd = req.fd; // key2 req.lineoffsets[0] = 7; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } key_2_fd = req.fd; // people req.lineoffsets[0] = 12; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } people_fd = req.fd; return true; } bool gpio_E_open(const char *device = "/dev/gpiochip4") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 15; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } light_trigger_fd = event_req.fd; int flags = fcntl(light_trigger_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(light_trigger_fd,F_SETFL,flags); return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool close(void); public slots: void time_out() { static int key_1_flag = 0; static int key_2_flag = 0; static int key_3_flag = 0; static int light_trigger_flag = 0; static int people_flag = 0; static int flame_flag = 0; //捕获key_1按下 read(key_1_fd,&event_data,sizeof (event_data)); if(event_data.id == 2) { key_1_flag = 1; emit(this->keyPressed(1)); //qDebug()<<"key_1 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_1_flag==1) { key_1_flag = 0; emit keyRelessed(1); //qDebug()<<"key_1 relessed"; } event_data.id = 0; //捕获key_2按下 int ret = ioctl(key_2_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << "==========" << data.values[0]; if(data.values[0] ==0&&key_2_flag==0) { emit(this->keyPressed(2)); key_2_flag = 1; //qDebug()<<"key_2 pressed"; } else if(data.values[0] ==1&&key_2_flag==1) { key_2_flag = 0; emit keyRelessed(2); //qDebug()<<"key_2 relessed"; } //event_data.id = 0; //捕获key_3按下 read(key_3_fd,&event_data,sizeof (event_data)); //qDebug() << "key3 "<< event_data.id; if(event_data.id == 2 && key_3_flag==0) { key_3_flag = 1; emit(this->keyPressed(3)); //qDebug()<<"key_3 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_3_flag==1) { key_3_flag = 0; emit keyRelessed(3); //qDebug()<<"key_3 relessed"; } event_data.id = 0; //捕获光电开关 read(light_trigger_fd,&event_data,sizeof (event_data)); if(event_data.id == 1 && light_trigger_flag==0) { //qDebug()<<"light triggered"; light_trigger_flag = 1; emit(this->lightTriggered()); } else light_trigger_flag = 0; event_data.id = 0; //捕获people coming ret = ioctl(people_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } if(data.values[0] ==1&&people_flag==0) { emit(this->peopleDetected(true)); people_flag = 1; //qDebug()<<"people coming"; } else if(data.values[0] ==0&&people_flag==1) { people_flag = 0; emit(this->peopleDetected(false)); //qDebug()<<"people leave"; } #if 0 //捕获火焰检测 read(fire_fd,&event_data,sizeof (event_data)); qDebug() << "------------------"<<event_data.id; if(event_data.id == 2 && flame_flag == 0) { qDebug()<<"flamedetection on"; flame_flag = 1; emit(this->flameDetected(true)); event_data.id = 0; } else if(event_data.id == 0 && flame_flag == 1) { qDebug()<<"flamedetection off"; flame_flag = 0; emit(this->flameDetected(false)); event_data.id = 0; } #endif //捕获key_2按下 ret = ioctl(fire_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << data.values[0]; if(data.values[0] ==1&&flame_flag==0) { emit(this->flameDetected()); flame_flag = 1; //qDebug()<<"flame on"; } else flame_flag = 0; } private: struct gpiohandle_request req; struct gpiohandle_data data; struct gpiochip_info chip_info; struct gpioevent_request event_req; struct gpioevent_data event_data; struct gpiod_chip *gpiochip5; struct gpiod_line *gpioline5_7; int key_1_fd; //设备文件描述符 int key_2_fd; int key_3_fd; int light_trigger_fd; int people_fd; int fire_fd; QTimer * fs_timer; }; #endif //ENV_H ------------------------------------------------------- fsmpFan.h: #ifndef FAN_H #define FAN_H /*************************************************************************** * * 类名:fsmpFan * 功能说明:扩展板 风扇控制 * 公有函数: * fsmpFan() * void start(void) 开启风扇) * void stop(void) 关闭风扇 * void setSpeed(int speed) 设置风扇速度(0-255) * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpFan:public QObject{ Q_OBJECT public: explicit fsmpFan(QObject *parent = nullptr):QObject(parent) { const char *device = "/sys/class/hwmon/hwmon1/pwm1"; fan_fd = ::open(device,O_WRONLY|O_TRUNC); if(fan_fd < 0) { perror("open fan"); return; } fan_speed = 0; }; ~fsmpFan(){ ::close(fan_fd); } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ void stop(void) { write(fan_fd,"0",strlen("0")); } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ void start(void) { char speedstr[100] = {0}; sprintf(speedstr, "%d", fan_speed); write(fan_fd, speedstr, strlen(speedstr)); } /* * Description: 控制风扇转速 * intput: speed 转速 * output: null * return: null */ void setSpeed(int speed) { fan_speed = speed%255; } private: int fan_fd; //设备文件描述符 int fan_speed; }; #endif // FAN_H ------------------------------------------------------- fsmpLeds.h: #ifndef LED_H #define LED_H /*************************************************************************** * * 类名:fsmpLeds * 功能说明:扩展板 3颗灯泡 * 公有函数: * fsmpLeds() * bool on(lednum x) 开灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * bool off(lednum x) 关灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpLeds:public QObject{ Q_OBJECT public: enum lednum{ LED1, LED2, LED3 }; explicit fsmpLeds(QObject *parent = nullptr) :QObject(parent) { led_fd1 = ::open("/sys/class/leds/led1/brightness",O_WRONLY|O_TRUNC); if(led_fd1 < 0) { perror("open led1"); return ; } led_fd2 = ::open("/sys/class/leds/led2/brightness",O_WRONLY|O_TRUNC); if(led_fd2 < 0) { perror("open led2"); return ; } led_fd3 = ::open("/sys/class/leds/led3/brightness",O_WRONLY|O_TRUNC); if(led_fd3 < 0) { perror("open led3"); return ; } } ~fsmpLeds() { ::close(led_fd1); ::close(led_fd2); ::close(led_fd3); } /* * Description: 开启设备,默认/sys/class/leds/led1/brightness * input: lednum * output: null * return: 成功true/失败false */ bool on(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"1",1); if(ret < 0) { return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool off(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"0",1); if(ret < 0) { return false; } return true; } private: int led_fd1; //设备文件描述符 int led_fd2; //设备文件描述符 int led_fd3; //设备文件描述符 }; #endif // LED_H ------------------------------------------------------- fsmpLight.h: #ifndef LIGHT_H #define LIGHT_H /*************************************************************************** * * 类名:fsmpLight * 功能说明:扩展板 光照强度检测 * 公有函数: * fsmpLight() * double getValue(void) 获取光照强度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpLight:public QObject{ Q_OBJECT public: explicit fsmpLight(QObject *parent = nullptr) :QObject(parent) { light_fd = ::open("/sys/bus/iio/devices/iio:device1/in_illuminance_input",O_RDONLY|O_NONBLOCK); if(light_fd < 0) { perror("open"); return; } } ~fsmpLight() { ::close(light_fd); } /* * Description: 获取光照强度 * input: null * output: null * return: current light */ double getValue(void) { char buf[10] = {0}; int ret = read(light_fd,buf,10); if(ret < 0) { perror("read"); return false; } double num; sscanf(buf, "%lf", &num); lseek(light_fd, 0, SEEK_SET); return num; } private: int light_fd; //设备文件描述符 }; #endif // LIGHT_H ------------------------------------------------------- fsmpProximity.h: #ifndef FSMPPROXIMITY_H #define FSMPPROXIMITY_H /*************************************************************************** * * 类名:fsmpProximity * 功能说明:扩展板 红外接近传感器(和光照传感器一起) * 公有函数: * fsmpProximity() * double getValue(void) 获取接近情况(0-2048越接近数据越大) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpProximity:public QObject{ Q_OBJECT public: explicit fsmpProximity(QObject *parent = nullptr) :QObject(parent) { proximity_fd = ::open("/sys/bus/iio/devices/iio:device1/in_proximity_raw",O_RDONLY|O_NONBLOCK); if(proximity_fd < 0) { perror("open"); return; } } ~fsmpProximity() { ::close(proximity_fd); } /* * Description: 获取distence * input: null * output: null * return: current light */ int getValue(void) { char buf[10] = {0}; int ret = read(proximity_fd,buf,10); if(ret < 0) { perror("read"); return false; } int num; sscanf(buf, "%d", &num); lseek(proximity_fd, 0, SEEK_SET); return num; } private: int proximity_fd; //设备文件描述符 }; #endif // FSMPPROXIMITY_H ------------------------------------------------------- fsmpSevensegLed.h: #ifndef FSMPSEVENSEGLED_H #define FSMPSEVENSEGLED_H /*************************************************************************** * * 类名:fsmpSevensegLed * 功能说明:扩展板 七段数码管 * 公有函数: * fsmpSevensegLed() * void display(int value) 显示4位以内整数 * void display(const char *str) 显示4位字符,注:仅支持 a、b、c、d、e * * 信号: * 无 * * *************************************************************************/ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include #include #include <QThread> #include <stdlib.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) class fsmpSevensegLed:public QThread{ Q_OBJECT public: explicit fsmpSevensegLed(QObject *parent = nullptr) :QThread(parent) { memset(data, 0, sizeof(data)); device = "/dev/spidev0.0"; bits = 8; speed = 400000; delay = 0; } void display(int value) { data[3] = value%10; data[2] = value/10%10; data[1] = value/100%10; data[0] = value/1000%10; } //"abcde" void display(const char *str) { data[3] = (strlen(str)-1 >= 0)?(str[strlen(str)-1] - 'a')+10:0; data[2] = (strlen(str)-2 >= 0)?(str[strlen(str)-2] - 'a')+10:0; data[1] = (strlen(str)-3 >= 0)?(str[strlen(str)-3] - 'a')+10:0; data[0] = (strlen(str)-4 >= 0)?(str[strlen(str)-4] - 'a')+10:0; } private: void run() { int ret = 0; int fd; fd = open(device, O_RDWR); //打开设备文件 if (fd < 0) pabort("can't open device"); /* * spi mode //设置spi设备模式 */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); //写模式 if (ret == -1) pabort("can't set spi mode"); /* * bits per word //设置每个字含多少位 */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); //写每个字含多少位 if (ret == -1) pabort("can't set bits per word"); /* * max speed hz //设置速率 */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); //写速率 if (ret == -1) pabort("can't set max speed hz"); //打印模式,每字多少位和速率信息 printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); //transfer(fd); //传输测试 int i = 0; int pos = 0; unsigned char buf[2]; while(1) { pos = 1 << (i % 4); buf[0] = pos; buf[1] = num[data[i]]; if (write(fd, buf, 2) < 0) perror("write"); i++; if (i == 4) { i = 0; } usleep(3500); } } static void pabort(const char *s) { perror(s); abort(); } const char *device; uint8_t mode; uint8_t bits; uint32_t speed; uint16_t delay; int data[4]; unsigned char num[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; }; #endif // FSMPSEVENSEGLED_H ------------------------------------------------------- fsmpTempHum.h: #ifndef TEMPHUM_H #define TEMPHUM_H /*************************************************************************** * * 类名:fsmpTempHum * 功能说明:扩展板 温度湿度 * 公有函数: * fsmpTempHum() * double temperature(void) 提取温度 * double humidity(void) 提取湿度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpTempHum:public QObject{ Q_OBJECT public: explicit fsmpTempHum(QObject *parent = nullptr) :QObject(parent) { } double temperature(void) { int temp_raw = 0; int temp_offset = 0; float temp_scale = 0; open_device_int("iio:device0","in_temp_raw",&temp_raw); open_device_int("iio:device0","in_temp_offset",&temp_offset); open_device_float("iio:device0","in_temp_scale",&temp_scale); return (temp_raw + temp_offset) * temp_scale / 1000; } double humidity(void) { int hum_raw = 0; int hum_offset = 0; float hum_scale = 0; open_device_int("iio:device0","in_humidityrelative_raw",&hum_raw); open_device_int("iio:device0","in_humidityrelative_offset",&hum_offset); open_device_float("iio:device0","in_humidityrelative_scale",&hum_scale); return (hum_raw + hum_offset) * hum_scale / 1000; } private: bool open_device_int(const char *device, const char *filename, int *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%d",val); ::close(fd); return true; } bool open_device_float(const char *device, const char *filename, float *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%f",val); ::close(fd); return true; } private: int temp_hum_fd;; //设备文件描述符 }; #endif // TEMPHUM_H ------------------------------------------------------- fsmpVibrator.h: #ifndef VIBRATOR_H #define VIBRATOR_H /*************************************************************************** * * 类名:fsmpVibrator * 功能说明:扩展板 振动马达 * 公有函数: * fsmpVibrator() * bool setParameter(int strong_magnitude, int timems) 设置振动强度(0-0xffff)及时长(ms) * bool start(void) 启动马达 * bool stop(void) 停止马达 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <sys/ioctl.h> #include <QDebug> class fsmpVibrator:public QObject{ Q_OBJECT public: explicit fsmpVibrator(QObject *parent = nullptr) :QObject(parent) { vibrator_fd = ::open("/dev/input/event1", O_RDWR|O_NONBLOCK); if(vibrator_fd < 0) { perror("open vibrator"); } } ~fsmpVibrator() { ::close(vibrator_fd); } /* * Description:设置 * input:频率 * output:null * return:成功true/失败false */ bool setParameter(int strong_magnitude = 0xFFFF, int timems = 5000) { //qDebug()<<strong_magnitude<<timems; effect.type = FF_RUMBLE, effect.id = -1, effect.u.rumble.strong_magnitude = strong_magnitude; effect.u.rumble.weak_magnitude = 0; effect.replay.length = timems; effect.replay.delay = 0; if (ioctl(vibrator_fd, EVIOCSFF, &effect) < 0) { printf("Error creating new effect: %s\n", strerror(errno)); return false; } return true; } bool start(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 1 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator on"); return false; } //qDebug()<<"start"; return true; } bool stop(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 0 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator off"); return false; } //qDebug()<<"stop"; return true; } private: int vibrator_fd;//设备文件描述符 struct ff_effect effect; }; #endif // VIBRATOR_H ------------------------------------------------------- 项目目的: 在Linux下通过qtcreator编写后通过st-mp1构建部署到远程Linux主机后,在Stm32mp157开发板上能够控制本身的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。并且通过Desktop Qt5.12.12 GCC64bit构建部署到Deploy Configuration时,能够控制Stm32mp157开发板上的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。 设计要求: 1. 通过点击pb_connect(连接按钮)按钮可以连接到云端mqtt,连接成功则弹出小窗提示连接成功并自动绑定订阅与发布功能、连接失败则弹出小窗提示连接失败,弹出的小窗有一个确定键,点击确定关闭小窗。 2. 点击按钮pb_led0打开Stm32mp157开发板上的LD1灯且同步打开华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(初始化为led0_on)变更为led0_off。再次点击按钮pb_led0时关闭Stm32mp157开发板上的LD1灯且同步关闭华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(此时为led0_off)变更为led0_on。按钮pb_led1和pb_led2也是相同理论。 3. 点击按钮pb_feng打开Stm32mp157开发板上的风扇且同步打开华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(初始化为feng_on)变更为feng_off。再次点击按钮pb_feng时关闭Stm32mp157开发板上的风扇且同步关闭华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(此时为feng_off)变更为feng_on。 4. 点击按钮pb_buzzer打开Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(初始化为:蜂鸣器_on)变更为蜂鸣器_off。再次点击按钮pb_buzzer时关闭Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(此时为:蜂鸣器_off)变更为蜂鸣器_on。 5. 点击按钮pb_humiture时,打开Stm32mp157开发板上的温湿度传感器并将数据显示在textBrowser组件上。此时按钮pb_humiture上的文本(初始化为:温湿度_on)变更为温湿度_off。再次点击按钮pb_humiture时关闭Stm32mp157开发板上的温湿度传感器,此时按钮pb_humiture上的文本(此时为:温湿度_off)变更为温湿度_on。(需添加功能:打开Stm32mp157开发板上的温湿度传感器后,当温度超过30度时蜂鸣器会立即开启,低于30度或者直接点击按钮pb_buzzer都可关闭蜂鸣器) 6. 点击按钮pb_photosensitive时,打开Stm32mp157开发板上的光敏传感器并将数据显示在textBrowser组件上。此时按钮pb_photosensitive上的文本(初始化为:光敏_on)变更为光敏_off。再次点击按钮pb_photosensitive时关闭Stm32mp157开发板上的光敏传感器,此时按钮pb_photosensitive上的文本(此时为:光敏_off)变更为光敏_on。 7. 点击按钮pb_infrared时,打开Stm32mp157开发板上的人体红外传感器并将数据显示在textBrowser组件上。此时按钮pb_infrared上的文本(初始化为:人体红外_on)变更为人体红外_off。再次点击按钮pb_infrared时关闭Stm32mp157开发板上的人体红外传感器,此时按钮pb_infrared上的文本(此时为:人体红外_off)变更为人体红外_on。 8. 点击按钮pb_camera时打开Stm32mp157开发板上的摄像头并将采集到的图像在屏幕界面的右侧显示出来(目前项目中没有设计用于显示摄像头采集图像显示的组件,需要添加)。此时按钮pb_camera上的文本(初始化为:摄像头_on)变更为摄像头off。再次点击按钮pb_camera时关闭Stm32mp157开发板上的摄像头,此时按钮pb_camera上的文本(此时为:摄像头_off)摄像头_on,并关闭摄像头采集的图像显示界面。 结合以上代码及要求,进行完整详细的项目开发,如有需要可以添加项目结构内缺失的文件(项目结构内缺失硬件的.cpp文件),硬件.h文件不可进行修改。整合后将项目的所有文件发我,让我复制粘贴就能直接使用

#include <stdio.h> #include <stdlib.h> #include <string.h> #include #include <sys/time.h> #include <unistd.h> #include #include <signal.h> #include #include <algorithm> #include <iostream> #include <map> #include <string> #include <queue> #include <vector> #include <sstream> #define LOG_BRASERO_NUM 15 using namespace std; static char *g_cpBrasero[] = { (char *) "ID", (char *) "刻录时间", (char *) "刻录机型号", (char *) "光盘属性", (char *) "刻录状态", (char *) "计算机帐户", (char *) "文件名称", (char *) "文件大小", (char *) "文件类型", (char *) "测试1", (char *) "测试2", (char *) "测试3", (char *) "测试4", (char *) "测试5", (char *) "测试6", }; typedef struct _tagBraseroLog { char cpValue[1024]; } BRASEROLOG; int uosaarch_line_parse(char *pBuffer) { int index, len,lastLen; int ret = 0; char *begin = NULL; char *end = NULL; char *lastEnd = NULL; //debug printf("进入了扫描"); BRASEROLOG BraseroLog[LOG_BRASERO_NUM]; memset(&BraseroLog, 0, LOG_BRASERO_NUM * sizeof(BRASEROLOG)); for (index = 0; index < LOG_BRASERO_NUM; index++) { begin = strstr(pBuffer, g_cpBrasero[index]); if(NULL == begin) continue; begin=strstr(begin,"="); end = strstr(pBuffer, g_cpBrasero[index + 1]); //end--; if (begin != NULL) { len = strlen("="); unsigned long strSize = end - begin - len ; printf("BraseroLOg[%d]=%s\n",index,BraseroLog[index].cpValue); //strncpy(BraseroLog[index].cpValue, begin + len, std::min(strSize, sizeof(BraseroLog[index].cpValue) - 1)); // printf("PrintLog[%d] = %s\n",index,BraseroLog[index].cpValue); } return 0; } return 1; } int main(){ char a[500] = "ID=1689309873, 刻录时间=2023-07-14 12:44:34, 刻录机型号=TSSTcorp-CDDVDW-SE-218CB-R95M6YMDA00008, 光盘属性=DVD+R, 刻录状态=成功, 计算机帐户=hba, 文件名称=/home/hba/Desktop/刻录测试文件.txt, 文件大小=66 B, 文件类型=文档"; uosaarch_line_parse(a); return 0; }

/* A program to put stress on a POSIX system (stress).:let @+ = join(argv(), "\n") * * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 * Amos Waterland <[email protected]> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ctype.h> #include <errno.h> #include #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <time.h> #include <unistd.h> #include <sys/wait.h> /* By default, print all messages of severity info and above. */ static int global_debug = 2; /* Name of this program */ static char *global_progname = PACKAGE; /* Implemention of runtime-selectable severity message printing. */ #define dbg if (global_debug >= 3) \ fprintf (stdout, "%s: dbug: [%lli] ", \ global_progname, (long long)getpid()), fprintf #define out if (global_debug >= 2) \ fprintf (stdout, "%s: info: [%lli] ", \ global_progname, (long long)getpid()), fprintf #define wrn if (global_debug >= 1) \ fprintf (stderr, "%s: WARN: [%lli] (%d) ", \ global_progname, (long long)getpid(), __LINE__), fprintf #define err if (global_debug >= 0) \ fprintf (stderr, "%s: FAIL: [%lli] (%d) ", \ global_progname, (long long)getpid(), __LINE__), fprintf /* Implementation of check for option argument correctness. */ #define assert_arg(A) \ if (++i == argc || ((arg = argv[i])[0] == '-' && \ !isdigit ((int)arg[1]) )) \ { \ err (stderr, "missing argument to option '%s'\n", A); \ exit (1); \ }

大家在看

recommend-type

echarts-doc-5-nginx.zip

适合国企等内网开发,有配置项、示例及示例的代码等核心内容,带nginx环境,解压后运行nginx.exe即可访问localhost:81/zh/option.html和localhost:82/zh/index.html查看
recommend-type

matlab飞行轨迹代码-msa-toolkit:这是在MATLAB中开发的用于模拟火箭6自由度动力学的代码

matlab飞行模拟代码msa-工具包 MSA 工具包是存储任务分析团队实施的代码的存储库。 它由几个文件夹组成,将在下面的段落中简要介绍。 模拟器 这是在MATLAB中开发的用于模拟6自由度火箭动力学的代码。 该模拟器可预测 3D 轨迹、远地点、作用在火箭上的力以及各种其他空气动力学数据。 数据 包含当前飞行数据、火箭几何形状和模拟参数的文件夹。 通用功能 在该文件夹中,存储了工具包代码中使用的常用函数。 autoMatricesProtub 此代码允许使用 Missile DATCOM 自动计算火箭空气动力学系数,适用于不同的气闸配置。 空气动力学优化 此代码实现了火箭的空气动力学优化。 优化变量是鳍弦和高度、鳍形状、卵形长度和卵形形状。 代码使用遗传算法达到目的。 远地点分析 当结构质量已知且具有一定程度的不确定性时,此代码使用不同的电机执行主要的远地点分析,以选择最好的电机。 敏感性分析 该代码实现了对火箭上升阶段的敏感性分析。 有两种类型的分析可用:确定性和随机性。 在确定性分析中,可以改变空气动力学系数的标称值和火箭的结构质量。 变化的相对幅度由用户设置,并且对于分析中考虑
recommend-type

5g核心网和关键技术和功能介绍-nokia.rar

5g核心网和关键技术和功能介绍-nokia.rar
recommend-type

wlanapi.dll缺少 wzcsapi.dll缺少 修复工具

最近系统老是提示wlanapi.dll缺少 wzcsapi.dll缺少 ,一激动写了个工具,专门修复这个问题。
recommend-type

易语言WinSock模块应用

易语言WinSock模块应用源码,WinSock模块应用,启动,停止,监听,发送,接收,断开连接,取服务器端口,取服务器IP,取客户IP,取客户端口,异步选择,检查连接状态,连接,断开,关闭,创建,发送数据,接收数据,取本机名,取本机IP组,窗口1消息处理,客户进入,客户离开,数据到达

最新推荐

recommend-type

三菱图形操作终端连接手册(非三菱产品1).pdf

三菱图形操作终端连接手册(非三菱产品1).pdf
recommend-type

【基于RESTful设计的高性能API接口实战开发:用户管理与权限控制系统全流程详解】

内容概要:本文档介绍了基于RESTful设计的高性能API接口的实战开发案例,涵盖从设计、开发、权限控制、性能优化到测试与文档自动化等环节。项目以用户管理与权限控制系统为例,采用Node.js + Express.js作为后端框架,MongoDB为数据库,Mongoose管理数据模型,严格遵循RESTful风格的接口设计,定义了标准HTTP动作对应的操作。安全性方面,实现了JWT认证机制和基于角色的访问控制(RBAC),确保接口安全。性能优化措施包括Redis缓存热点数据、接口请求频率限制、Winston和Morgan日志系统。开发调试借助Postman和Swagger UI,支持自动生成接口文档,提高前后端协作效率。部署方案利用Docker、Nginx、GitHub Actions等技术实现自动化部署,ELK用于日志收集与分析。; 适合人群:有一定编程基础,尤其是对API开发感兴趣的开发者和系统架构师。; 使用场景及目标:①学习RESTful风格的API设计原则;②掌握API的安全机制,如JWT认证和RBAC;③了解性能优化方法,如缓存和限流;④熟悉API开发的完整流程,包括测试、文档管理和部署。; 阅读建议:本案例详细描述了API开发的各个环节,建议读者按照文档顺序逐步学习,重点理解各部分的技术细节和实现原理,同时结合实际项目进行实践。
recommend-type

Canvas实现两张图片合成操作

资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 Canvas实现两张图片合成操作
recommend-type

【电子设计竞赛】2025电赛D题全解:声音定位系统设计与实现详解

内容概要:本文详细解析了2025年全国大学生电子设计大赛D题——声音定位系统,从赛题要求、系统架构、硬件选型、算法选择到软件代码实现进行了全面阐述。赛题要求设计一个声音定位系统,包括声响模块、声音接收模块和信息处理模块。声响模块负责产生500Hz的声音信号,声音接收模块通过麦克风和放大电路接收声音信号,信息处理模块则根据声音传播的时间差计算声响模块的位置坐标,并显示出来。发挥部分还包括提高定位精度、连续跟踪显示坐标值和显示移动轨迹。文中还介绍了开发环境搭建、关键代码实现以及常见问题的解决方法。 适合人群:具备一定电子设计基础的大学生、电子设计爱好者和参赛选手。 使用场景及目标:①帮助参赛者理解赛题要求,掌握声音定位系统的设计和实现方法;②提升参赛者的电子设计能力和编程水平,为比赛做好准备;③通过实际项目锻炼创新思维和实践能力,积累宝贵的经验。 其他说明:本文不仅涵盖了硬件选型、电路设计、算法选择等技术细节,还提供了详细的代码实现和优化建议,有助于读者全面掌握声音定位系统的开发过程。此外,文章还强调了电子设计竞赛的重要性,鼓励读者积极参与,探索电子设计的无限可能。
recommend-type

2022版微信自定义密码锁定程序保护隐私

标题《微信锁定程序2022,自定义密码锁》和描述“微信锁定程序2022,自定义密码锁,打开微信需要填写自己设定的密码,才可以查看微信信息和回复信息操作”提及了一个应用程序,该程序为微信用户提供了额外的安全层。以下是对该程序相关的知识点的详细说明: 1. 微信应用程序安全需求 微信作为一种广泛使用的即时通讯工具,其通讯内容涉及大量私人信息,因此用户对其隐私和安全性的需求日益增长。在这样的背景下,出现了第三方应用程序或工具,旨在增强微信的安全性和隐私性,例如我们讨论的“微信锁定程序2022”。 2. “自定义密码锁”功能 “自定义密码锁”是一项特定功能,允许用户通过设定个人密码来增强微信应用程序的安全性。这项功能要求用户在打开微信或尝试查看、回复微信信息时,必须先输入他们设置的密码。这样,即便手机丢失或被盗,未经授权的用户也无法轻易访问微信中的个人信息。 3. 实现自定义密码锁的技术手段 为了实现这种类型的锁定功能,开发人员可能会使用多种技术手段,包括但不限于: - 加密技术:对微信的数据进行加密,确保即使数据被截获,也无法在没有密钥的情况下读取。 - 应用程序层锁定:在软件层面添加一层权限管理,只允许通过验证的用户使用应用程序。 - 操作系统集成:与手机操作系统的安全功能进行集成,利用手机的生物识别技术或复杂的密码保护微信。 - 远程锁定与擦除:提供远程锁定或擦除微信数据的功能,以应对手机丢失或被盗的情况。 4. 微信锁定程序2022的潜在优势 - 增强隐私保护:防止他人未经授权访问微信账户中的对话和媒体文件。 - 防止数据泄露:在手机丢失或被盗的情况下,减少敏感信息泄露的风险。 - 保护未成年人:父母可以为孩子设定密码,控制孩子的微信使用。 - 为商业用途提供安全保障:在商务场合,微信锁定程序可以防止商业机密的泄露。 5. 使用微信锁定程序2022时需注意事项 - 正确的密码管理:用户需要记住设置的密码,并确保密码足够复杂,不易被破解。 - 避免频繁锁定:过于频繁地锁定和解锁可能会降低使用微信的便捷性。 - 兼容性和更新:确保微信锁定程序与当前使用的微信版本兼容,并定期更新以应对安全漏洞。 - 第三方应用风险:使用第三方应用程序可能带来安全风险,用户应从可信来源下载程序并了解其隐私政策。 6. 结语 微信锁定程序2022是一个创新的应用,它提供了附加的安全性措施来保护用户的微信账户。尽管在实施中可能会面临一定的挑战,但它为那些对隐私和安全有更高要求的用户提供了可行的解决方案。在应用此类程序时,用户应谨慎行事,确保其对应用程序的安全性和兼容性有所了解,并采取适当措施保护自己的安全密码。
recommend-type

【自动化脚本提速】:掌握序列生成的5种高效技巧

# 摘要 本文系统地阐述了自动化脚本提速的方法,重点介绍了序列生成的基础理论及其在脚本中的应用。通过探讨不同序列生成方法和高效技巧,本文旨在提高编程效率,优化自动化流程。同时,文中还涉及了高级技术,如嵌套循环、列表推导式和并行处理,这些技术不仅增加了序列生成的复杂性,同时也显著提升了效率。最后,本文通过综合案例分析,展示了一系列序列生成技巧的实际应用,并提出了优化建议和未来研究方向。 #
recommend-type

卷积神经网络中的分层!

<think>我们正在处理一个关于卷积神经网络(CNN)层级结构的问题。用户希望了解CNN的层级结构及其功能。根据提供的引用内容,我们可以整理出以下信息: 1. 引用[1]和[2]指出,一个完整的卷积神经网络通常包括以下层级: - 数据输入层(Input layer) - 卷积计算层(CONV layer) - ReLU激励层(ReLU layer) - 池化层(Pooling layer) - 全连接层(FC layer) - (可能还有)Batch Normalization层 2. 引用[2]详细说明了各层的作用: - 数据输入层:对原始图像
recommend-type

MXNet预训练模型介绍:arcface_r100_v1与retinaface-R50

根据提供的文件信息,我们可以从中提取出关于MXNet深度学习框架、人脸识别技术以及具体预训练模型的知识点。下面将详细说明这些内容。 ### MXNet 深度学习框架 MXNet是一个开源的深度学习框架,由Apache软件基金会支持,它在设计上旨在支持高效、灵活地进行大规模的深度学习。MXNet支持多种编程语言,并且可以部署在不同的设备上,从个人电脑到云服务器集群。它提供高效的多GPU和分布式计算支持,并且具备自动微分机制,允许开发者以声明性的方式表达神经网络模型的定义,并高效地进行训练和推理。 MXNet的一些关键特性包括: 1. **多语言API支持**:MXNet支持Python、Scala、Julia、C++等语言,方便不同背景的开发者使用。 2. **灵活的计算图**:MXNet拥有动态计算图(imperative programming)和静态计算图(symbolic programming)两种编程模型,可以满足不同类型的深度学习任务。 3. **高效的性能**:MXNet优化了底层计算,支持GPU加速,并且在多GPU环境下也进行了性能优化。 4. **自动并行计算**:MXNet可以自动将计算任务分配到CPU和GPU,无需开发者手动介入。 5. **扩展性**:MXNet社区活跃,提供了大量的预训练模型和辅助工具,方便研究人员和开发者在现有工作基础上进行扩展和创新。 ### 人脸识别技术 人脸识别技术是一种基于人的脸部特征信息进行身份识别的生物识别技术,广泛应用于安防、监控、支付验证等领域。该技术通常分为人脸检测(Face Detection)、特征提取(Feature Extraction)和特征匹配(Feature Matching)三个步骤。 1. **人脸检测**:定位出图像中人脸的位置,通常通过深度学习模型实现,如R-CNN、YOLO或SSD等。 2. **特征提取**:从检测到的人脸区域中提取关键的特征信息,这是识别和比较不同人脸的关键步骤。 3. **特征匹配**:将提取的特征与数据库中已有的人脸特征进行比较,得出最相似的人脸特征,从而完成身份验证。 ### 预训练模型 预训练模型是在大量数据上预先训练好的深度学习模型,可以通过迁移学习的方式应用到新的任务上。预训练模型的优点在于可以缩短训练时间,并且在标注数据较少的新任务上也能获得较好的性能。 #### arcface_r100_v1 arcface_r100_v1是一个使用ArcFace损失函数训练的人脸识别模型,基于ResNet-100架构。ArcFace是一种流行的深度学习人脸识别方法,它在损失函数层面上增强类间的区分度。在ArcFace中,通过引入角度余弦的特征分离度,改善了传统的Softmax损失函数,让学习到的人脸特征更加具有鉴别力。 ArcFace的模型文件包括: - model-0000.params: 这是模型权重参数文件。 - model-symbol.json: 这是包含网络结构定义的JSON文件。 #### retinaface-R50 retinaface-R50是基于ResNet-50架构的人脸检测模型,使用RetinaFace框架训练而成。RetinaFace是为了解决传统人脸检测模型在面对小尺寸、遮挡、模糊等复杂情况时识别准确度不高的问题而设计的。它采用一种基于多尺度的金字塔网络结构,能有效处理不同尺度的人脸,并且在特征提取时采用了一种高效的特征融合策略。 Retinaface-R50的模型文件包括: - R50-0000.params: 这是模型权重参数文件。 - R50-symbol.json: 这是包含网络结构定义的JSON文件。 ### 总结 从给定的文件信息中,我们可以看出这些预训练模型是基于MXNet深度学习框架开发的,具有专门针对人脸识别任务的优化。ArcFace模型通过增强特征的区分度,而Retinaface模型通过多尺度处理和高效的特征融合,都展示了在人脸检测和识别方面的先进技术。开发者可以利用这些预训练模型,结合MXNet提供的高级API,快速构建并部署自己的人脸识别解决方案。
recommend-type

【文本处理黑科技】:Shell脚本中序列和数组的高级应用

# 摘要 本文系统地介绍了Shell脚本中序列与数组的基础知识、操作技巧以及在实际应用中的优化方法。第一章和第二章分别对序列和数组的基础知识进行了阐述,重点讲解了序列的生成、操作、文本处理和数组的基本操作与高级特性。第三章探讨了数组在数据处理和内存管理中的性能优势。第四章结合实际案例,展示了序列与数组在日志文件分析、报告生成和配置文件管理
recommend-type

数据库用来干啥的

<think>首先,用户的问题是:“我想了解数据库的用途 请问数据库的主要用途是什么”。这翻译成英文是:“I want to understand the purpose of databases. What are the main uses of databases?” 从系统级指令中,我需要: - 所有行内数学表达式使用 $...$ 格式。 - 独立公式使用 $$...$$ 格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 - 结构清晰,帮助用户逐步解决问题。 - 回答真实可