gpt4 book ai didi

c - C中线程间的全局变量同步

转载 作者:行者123 更新时间:2023-11-30 15:10:27 25 4
gpt4 key购买 nike

我正在开发一个由Arduino控制的机器人。它将通过 TCP 从我的 PC 上的程序接收命令,并通过串行通信转发到 Arduino。一旦Arduino执行命令,其上安装的传感器就会将环境状态返回给PC。然后程序将运行一些算法来决定下一步采取什么行动。我能够从 Android 应用程序接收定向命令来手动移动机器人。我使用 Raspberry Pi 作为消息传递/控制设备。

PC 上的程序、Android 应用程序和 Arduino 草图已完成并经过测试。但在Rpi上运行的程序中多个线程之间的通信问题仍然存在。

到目前为止,我有以下内容(TCP、串行、蓝牙套接字代码被省略,因为它们超出了这个问题的范围):

int canForwardToPC, recvFromPC, recvFromAndroid, recvFromAr, canSendCommand, isWaitingForInstruc, isWaitingForPos;

//all the int are initialized to be 0

void *ar_send(){
int status;

do{
if(canSendCommand){
status = write(ser, output, BUFFER_SIZE);
if(status != -1) {

printf("Sent to Arduino: %s\n", output);

memset(&output[0], 0, sizeof(output));

isWaitingForGridStr = 1;
canSendCommand = 0;

usleep(1000000);

}else{
ar_isConnected = 0;
printf("Error Writing\n");
}
}
}while(1);

}

void *tcp_send(){

int status;

do{
if (canForwardToPC && tcp_isConnected){
status = write(newsockfd, output, strlen(output));
printf("Sent to PC: %s\n", output);
memset(&output[0], 0, sizeof(output));
if (status > 0) {

isWaitingForInstruc = 1;
}

else{
tcp_isConnected = 0;
usleep(10000000);
}
canForwardToPC = 0;
}
} while (1);

}

void *bt_recv(){

int bytes_read;

do{
bytes_read = read(client, bt_buffer, sizeof(bt_buffer));
if(bytes_read > 0) {

printf("Received \"%s\" from Android\n", bt_buffer);
recvFromAndroid = 1;

}
else{

bt_isConnected = 0;

}
}while(1);

}

void *ar_recv(){

do{
if(isWaitingForGridStr){

n = read(ser, ar_buffer, BUFFER_SIZE);

if(n <= 0) continue;

ar_buffer[BUFFER_SIZE] = '\0';

printf("Received %s from Arduino.\n", ar_buffer);

isWaitingForGridStr = 0;

recvFromAr = 1;

}
}while(1);

}

void *tcp_recv(){

do{
if (tcp_isConnected && isWaitingForInstruc){


n = read(newsockfd, tcp_buffer, BUFFER_SIZE);


isWaitingForInstruc = 0;

printf("Received %s from PC.\n", tcp_buffer);
if (n > 0){
recvFromPC = 1;

}else{
tcp_isConnected = 0;
usleep(10000000);
}
}
} while (1);

}

void *controller(){
do{
if(recvFromAndroid){

recvFromAndroid = 0;



char temp[1];
temp[0] = bt_buffer[0];

canForwardToPC = 1;

strncpy(output, temp, sizeof(temp));
memset(&bt_buffer[0], 0, sizeof(bt_buffer));


}

else if(recvFromAr){

recvFromAr = 0;


canForwardToPC = 1;

isWaitingForInstruc = 1;]

strncpy(output, ar_buffer, sizeof(ar_buffer));
memset(&ar_buffer[0], 0, sizeof(ar_buffer));

}

else if(recvFromPC){

recvFromPC = 0;

canSendCommand = 1;

strncpy(output, tcp_buffer, sizeof(tcp_buffer));
memset(&tcp_buffer[0], 0, sizeof(tcp_buffer));

}

}while(1);

}

每个方法都是一个线程,将在主函数中创建并加入。

据我所知,输出受到所有整数的良好保护,并且接收和发送线程组织正确。该代码看起来是合法的。

但是我有以下部分输出,但未按计划进行:

Sent to PC: W1
Received W1 from PC.
Sent to Arduino: W1
Received 0:0:0:2:0:3 from Arduino.
Sent to PC: 0:0:0:2:0:3
Received W1W1W1W1W1D180W1A180W1 from PC.
Sent to Arduino: W1W1W1W1W1D180W1A180W1
Received -1:0:-1:2:0:3 from Arduino.
Received W1D180W1A180W1W1W1W1A180 from PC.
Sent to PC: -1:0:-1:2:0:3
Received W1 from PC.
Sent to Arduino: W1
Received -1:-1:-1:-1:0:3 from Arduino.
Received W1D180W1D180W1W1W1A180W1 from PC.
Sent to PC: -1:-1:-1:-1:0:3
Received W1 from PC.
Sent to Arduino: W1
Received -1:-1:-1:-1:0:3 from Arduino.
Received D180W1W1W1W1W1W1D180W1 from PC.
Sent to PC: D180W1W1W1W1W1W1D180W1
Received A180 from PC.
Sent to Arduino: A180
Received -1:-1:-1:1:0:3 from Arduino.
Sent to PC: -1:-1:-1:1:0:3
Received W1W1W1D180W1W1W1W1 from PC.
Received W1 from PC.

我想要发送到 PC 的唯一内容是位置字符串,其格式为 x:x:x:x:x:x。但有一个实例,D180W1W1W1W1W1W1D180W1被发送到PC。

预期输出应重复如下:发送至电脑从电脑接收发送到Arduino从 Arduino 接收

我怀疑发生了一些全局变量不一致,导致了意外的输出。

我找到了几篇关于信号量和互斥量的文章,但这些只是针对 2 个线程的解决方案。我这里运行着 6 个线程,但我不知道如何实现信号量。

如何解决数据不一致问题?

任何帮助将不胜感激。

最佳答案

根据你告诉我的情况:您应该为每个传入和传出 channel 实​​现不同的消息队列。每个通信线程仅负责将传入消息放入队列中,或从队列中取出消息并将其发送到其通信端口。每个队列都有自己的锁(互斥锁或其他)。主 Controller (1 个线程)将有权访问所有队列,并将处理在它们之间移动消息。每个队列的互斥体将由 Controller 或其通信线程锁定。

流程示例:

  1. 通过线程处理从 PC 读取的消息来接收消息。
  2. 获取锁后将其放入来自 PC 的传入消息队列中,然后释放锁。
  3. Controller 唤醒(通过我推荐的定期调度,或通过某种事件机制)并尝试获取来自 PC 的传入消息队列的锁定。
  4. 它获取锁并读取那里的第一条消息。它发现它有一条消息发送给arduino。
  5. 它接收消息,释放来自 PC 的传入锁定。
  6. 获取到 arduino 锁的传出,并将消息放入到 arduino 队列中。
  7. 发送到arduino线程唤醒,获取其队列锁,获取那里的所有消息并发送到arduino。
  8. 发送到arduino线程释放锁并进入休眠状态。

所有传出线程都可以定期处理或根据来自 Controller 的事件进行处理。希望这会有所帮助。

关于c - C中线程间的全局变量同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36146339/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com