【平头哥Sipeed LicheeRV 86 Panel测评】 6-socket实现不同进程通信
[复制链接]
架构的选择
前几天移植了python3.8到开发板上,python的优点是明显的,比如不用交叉编译、语法简单、有很多封装好的库。但是python上用的GUI还需要重新移植,因此放弃了。决定使用已经移植好的lvgl实现GUI。因此整体的架构是用C语言写的lvgl的进程作为显示进程,而后台进程则由python实现。后台进程的工作包括:与远程终端通信获取数据、传输控制指令等。
进程间通信方式的选择
如果使用这种方式的话,就需要实现lvgl进程与python后台进程的通信。虽然进程间通信有很多种方式,但是消息队列、共享内存貌似实现不了,因为没法共同操作同一个消息队列或共享内存。通过在网上搜索发现有三种方式可以实现通信:
- 通过共享的文件
- 通过管道,将其中1个进程的标准输入输出改写到管道
- 通过socket
感觉还是socket比较通用和方便,因此最终选择socket实现进程间的通信。所以总体的思路如下图所示。
socket进程间通信
C语言版本的socket通信如下,实现了socket客户端的方式。
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#define SOCKET_CLIENT_PATH "/tmp/client.socket"
int client_sockfd;
struct sockaddr_un lv_socket_client_addr;
void lv_socket_init_client()
{
client_sockfd = socket(AF_UNIX,SOCK_STREAM,0);
lv_socket_client_addr.sun_family = AF_UNIX;
strcpy(lv_socket_client_addr.sun_path,SOCKET_CLIENT_PATH);
}
int lv_socket_client_send_recv(char* send_str,char* recv_str)
{
int len = sizeof(lv_socket_client_addr);
int result;
int i=0;
char ch;
result = connect(client_sockfd,(struct sockaddr*)&lv_socket_client_addr,len);
if(result == -1){
return -1;
}
if(send_str != NULL){
write(client_sockfd,send_str,strlen(send_str));
}
if(recv_str != NULL){
while(read(client_sockfd,&ch,1) > 0){
*(recv_str+i) = ch;
i++;
}
}
close(client_sockfd);
return 0;
}
python版本的socket通信如下,实现了socket服务器端的方式。
import socket
import os
skt = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
conn = '/tmp/client.socket'
if os.path.exists(conn):
os.unlink(conn)
skt.bind(conn)
skt.listen(5)
while True:
connect,addr = skt.accept()
with connect123:
data = connect123.recv(1024) #recv some data
connect123.send(bytes('temperature:'+temperature,encoding="utf8")) #send data
connect123.close()
两个进程共同使用的 /tmp/client.socket 文件描述符实现的数据通信。
|