1、烧录:
首先git上下载项目到本地会下载所有项目,包括所有分支内容,烧录的话得在对应开发板子的分支下烧录,因为各分支的代码是不同的,得在本地切换到相应板子的分支烧录,切换后本地文件也会做相应改变
切换到本地分支后进入环境后执行makefile指令即可编译代码,其中模块的makefile指令大部分如下
#使用make all 命令会首先构建.so文件和rtcd文件,再进入test文件夹,执行make all
all: libzs.so rtcd $(MAKE) -C test all
include ./../Arch.make # 本Makefile包含上上个文件夹下的Arch.make CC := $(CROSS_COMPILE)gcc
INCFLAGS := -I include
OBJS := rtcTest.o
LIBS := -lzss_rtc -L../all: rtcTest # 输入 make all 指令后会构建rtcTest文件rtcTest: $(OBJS) # 指定依赖$(CC)$(SYSROOT) -o $@$(OBJS) $(LIBS) #生成目标文件%.o: %.c$(CC)$(INCFLAGS) $(SYSROOT) -g -c$< -o $@.PHONY: cleanclean: # make cleanrm -f *.orm -f rtcTest
include ./Arch.make # 包含头文件CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
CFLAGS := -Wall -pthread -ggdb $(SYSROOT) -I../drivers/
LFLAGS := -lrt
PROGRAMS := ./rtcdall: libzss_rtc.so $(PROGRAMS) # 目标$(MAKE) -C test $@lib: libzss_rtc.sortcd: rtc_util.o rtcd.o$(CC)$(CFLAGS) $(LFLAGS) rtc_util.o rtcd.o -o$@rtcd.o: rtc_pub.h rtc_priv.h rtcd.clibzss_rtc.so: rtc_lib.o rtc_socket.o rtc_util.o$(CC)$(SYSROOT) -fpic -shared -o $@ rtc_lib.o rtc_socket.o rtc_util.ortc_util.o: rtc_pub.h rtc_priv.h rtc_util.crtc_socket.o: rtc_pub.h rtc_priv.h rtc_socket.cclean:rm -f $(PROGRAMS)rm -f libzss_rtc.sorm -f *.o # 清除$(MAKE) -C test $@ # 在test下执行make clean
在编译环境中make all指令即可编译,用TFTP协议将bin文件烧录到板子上即可
tftp -gr 文件名 ip地址 # 传输命令
2、运行:
将动态库放到/usr/local/lib文件目录下,方便程序使用时找到
./rtcd -df # 前台运行
./rtcd & # 后台运行
ps | grep rtcd # 查看进程
3、部分相关代码:
int rtc_get_socket(void) {int socket_handle;int len;struct sockaddr_un remote;int conn_count = 0;// 创建socketif ((socket_handle = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {return -1; // 创建socket失败}// 设置socket地址结构memset(&remote, 0, sizeof(remote));remote.sun_family = AF_UNIX;strcpy(remote.sun_path, RTC_SOCKET);len = offsetof(struct sockaddr_un, sun_path) + strlen(remote.sun_path);// 尝试连接while (connect(socket_handle, (struct sockaddr *)&remote, len) == -1) {if (++conn_count >= SOCKET_CONN_TRY) {close(socket_handle); // 尝试连接次数达到上限,关闭socketreturn -1; // 返回错误}return socket_handle;}
本函数主要做本机内部连接,获取套接字后就尝试开始连接,尝试连接次数为100次
static int daemon_init(void) {pid_t pid;if ((pid = fork()) < 0)return -1;else if (pid != 0)exit(0);setsid();chdir("/");umask(0);return 0;
}
// 创建守护进程,子进程返回0父进程大于0
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
这里的参数含义如下:
sockfd:这是服务器用来监听连接请求的套接字文件描述符。
addr:这是一个指向 sockaddr 结构的指针,该结构会被 accept 填充以包含客户端的地址信息。如果不需要这些信息,可以传递 NULL。
addrlen:这是一个指向 socklen_t 类型的指针,它应该被初始化为 addr 指向的缓冲区的大小。在调用 accept 之后,addrlen 会被设置为实际存储在 addr 中的地址结构的长度。
accept 函数成功时返回一个新的文件描述符,用于后续的读写操作;失败时返回 -1,并设置 errno 来指示错误原因。
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>int main() {int listen_fd, conn_fd;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len = sizeof(client_addr);// 创建套接字,绑定地址,监听等操作...// 接受连接conn_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len);if (conn_fd == -1) {perror("accept");return 1;}// 使用 conn_fd 与客户端进行通信...// 关闭连接close(conn_fd);return 0;
}
4、本质流程:
服务器会创建一个或几个线程,每个线程做一个服务器,接收其他客户端的连接和传输的数据
服务器实现代码:
static int create_socket(const char *sockname, int nconn) {int socket_handle; // 套接字描述符int len; // 用于存储地址结构的长度struct sockaddr_un local; // Unix域套接字地址结构// 创建套接字if ((socket_handle = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {// 如果创建套接字失败,记录日志并返回-1// syslog(LOG_LOCAL4|LOG_DEBUG,"Socket failed in create_socket");return -1;}// 初始化地址结构local.sun_family = AF_UNIX; // 地址族为AF_UNIXstrcpy(local.sun_path, sockname); // 复制套接字文件名到地址结构中unlink(local.sun_path); // 如果套接字文件已存在,则删除它// 计算地址结构的大小len = strlen(local.sun_path) + sizeof(local.sun_family);// 绑定套接字到地址结构if (bind(socket_handle, (struct sockaddr*)&local, len) == -1) {// 如果绑定失败,记录日志,关闭套接字并返回-1// syslog(LOG_LOCAL4|LOG_DEBUG,"Bind failed in create_socket");close(socket_handle);return -1;}// 设置套接字监听队列的长度if (listen(socket_handle, nconn) == -1) {// 如果监听设置失败,记录日志,关闭套接字并返回-1// syslog(LOG_LOCAL4|LOG_DEBUG,"Listen failed in create_socket");close(socket_handle);return -1;}// 如果一切顺利,返回套接字描述符return socket_handle;
}
创建了一个套接字,指定Unix 域套接字,这种协议服务器与客户端绑定到同一个地址上即可进行通信,用bind进行绑定,地址没必要真实存在,可以人为定义,最后用listen将本套接字转化成服务器,并设置监听数量
用户输入命令,客户端会创建套接字,与服务端连接一次发送数据后断开,并回收套接字
int rtc_set_debug_mask(unsigned int mask){int socket_handle;uint8 str[100] = {0};if((socket_handle = rtc_get_socket()) == -1){return -1;}str[0] = CMD_SET_DEBUG_MASK;str[1] = 6;*(unsigned int*)(str+2) = mask;if(send(socket_handle, str, 6, MSG_NOSIGNAL) == -1){//syslog(LOG_LOCAL4|LOG_DEBUG, "%s(): Failed to send packet to rtcd\n", __func__);close(socket_handle);return -2;}close(socket_handle);return 0;
}
int rtc_get_socket(void) {int socket_handle;int len;struct sockaddr_un remote;int conn_count = 0;// 创建socketif ((socket_handle = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {return -1; // 创建socket失败}// 设置socket地址结构memset(&remote, 0, sizeof(remote));remote.sun_family = AF_UNIX;strcpy(remote.sun_path, RTC_SOCKET);len = offsetof(struct sockaddr_un, sun_path) + strlen(remote.sun_path);// 尝试连接while (connect(socket_handle, (struct sockaddr *)&remote, len) == -1) {if (++conn_count >= SOCKET_CONN_TRY) {close(socket_handle); // 尝试连接次数达到上限,关闭socketreturn -1; // 返回错误}return socket_handle;}
创建套接字连接到 RTC_SOCKET指定的服务器,用send发送命令,并关闭
5.补充:
git stash save
将当前节点的更改保存,工作区栈区都变为空
git stash pop
恢复到上个节点的更改