要实现进程A和进程B之间的双向通信,并通过命名管道(FIFO)实现定时消息发送和CRC校验,可以使用以下步骤和代码示例。
进程A(发送消息并接收CRC校验结果)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#define FIFO_PATH_A "/tmp/myfifoA"
#define FIFO_PATH_B "/tmp/myfifoB"
uint32_t crc32(const void *data, size_t length) {
// CRC-32 implementation (simplified for demonstration)
// You can use a more optimized version or library.
static const uint32_t table[256] = { /* Precomputed CRC table */ };
uint32_t crc = 0xFFFFFFFF;
const uint8_t *byte = data;
while (length--) {
crc = table[(crc ^ *byte++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFF;
}
int main() {
int fdA, fdB;
const char *message = "Hello from Program A";
char buffer[100];
uint32_t crc;
// Create FIFOs if they do not exist
if (mkfifo(FIFO_PATH_A, 0666) == -1 && errno != EEXIST) {
perror("mkfifo A");
exit(EXIT_FAILURE);
}
if (mkfifo(FIFO_PATH_B, 0666) == -1 && errno != EEXIST) {
perror("mkfifo B");
exit(EXIT_FAILURE);
}
// Open FIFOs
fdA = open(FIFO_PATH_A, O_WRONLY);
if (fdA == -1) {
perror("open A");
exit(EXIT_FAILURE);
}
fdB = open(FIFO_PATH_B, O_RDONLY);
if (fdB == -1) {
perror("open B");
exit(EXIT_FAILURE);
}
while (1) {
// Send message
write(fdA, message, strlen(message) + 1);
// Compute CRC of the message
crc = crc32(message, strlen(message));
printf("Sent message: %s\n", message);
// Wait for CRC check result
read(fdB, buffer, sizeof(buffer));
printf("Received CRC: %s\n", buffer);
// Sleep for n seconds
sleep(5); // Change 5 to the desired interval
}
// Clean up
close(fdA);
close(fdB);
unlink(FIFO_PATH_A);
unlink(FIFO_PATH_B);
return 0;
}
进程B(接收消息并发送CRC校验结果)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#define FIFO_PATH_A "/tmp/myfifoA"
#define FIFO_PATH_B "/tmp/myfifoB"
uint32_t crc32(const void *data, size_t length) {
// CRC-32 implementation (simplified for demonstration)
// You can use a more optimized version or library.
static const uint32_t table[256] = { /* Precomputed CRC table */ };
uint32_t crc = 0xFFFFFFFF;
const uint8_t *byte = data;
while (length--) {
crc = table[(crc ^ *byte++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFF;
}
int main() {
int fdA, fdB;
char buffer[100];
uint32_t crc;
char crc_result[100];
// Create FIFOs if they do not exist
if (mkfifo(FIFO_PATH_A, 0666) == -1 && errno != EEXIST) {
perror("mkfifo A");
exit(EXIT_FAILURE);
}
if (mkfifo(FIFO_PATH_B, 0666) == -1 && errno != EEXIST) {
perror("mkfifo B");
exit(EXIT_FAILURE);
}
// Open FIFOs
fdA = open(FIFO_PATH_A, O_RDONLY);
if (fdA == -1) {
perror("open A");
exit(EXIT_FAILURE);
}
fdB = open(FIFO_PATH_B, O_WRONLY);
if (fdB == -1) {
perror("open B");
exit(EXIT_FAILURE);
}
while (1) {
// Read message
read(fdA, buffer, sizeof(buffer));
printf("Received message: %s\n", buffer);
// Compute CRC of the message
crc = crc32(buffer, strlen(buffer));
sprintf(crc_result, "%u", crc);
// Send CRC result
write(fdB, crc_result, strlen(crc_result) + 1);
}
// Clean up
close(fdA);
close(fdB);
unlink(FIFO_PATH_A);
unlink(FIFO_PATH_B);
return 0;
}
使用步骤
- 编译两个程序:
gcc -o progA progA.c
和gcc -o progB progB.c
。 - 运行进程B(接收和处理消息):
./progB
。 - 运行进程A(发送消息):
./progA
。
这将实现进程A每隔n
秒发送消息,并从进程B接收CRC校验结果。
#makefile文件
创建一个通用的 Makefile
以支持 proc_A
和 proc_B
两个源文件,并尽可能减少修改的工作量,可以按照以下步骤进行:
示例 Makefile
# 定义变量
CC = gcc
CFLAGS = -Wall -g
TARGETS = proc_A proc_B
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
# 默认目标
all: $(TARGETS)
# 目标规则
proc_A: proc_A.o
$(CC) -o $@ $^ $(CFLAGS)
proc_B: proc_B.o
$(CC) -o $@ $^ $(CFLAGS)
# 生成 .o 文件
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理
clean:
rm -f $(TARGETS) $(OBJECTS)
# 伪目标
.PHONY: all clean
说明
CC
:指定使用的编译器,这里是gcc
。CFLAGS
:编译选项,-Wall
启用所有警告,-g
生成调试信息。TARGETS
:最终要生成的可执行文件,这里是proc_A
和proc_B
。SOURCES
:当前目录下所有的.c
源文件。OBJECTS
:所有的.o
对象文件,这些文件由.c
文件生成。
目标规则
proc_A
和proc_B
目标规则中,$@
代表目标文件名(例如proc_A
),$^
代表所有依赖的文件(例如proc_A.o
)。
生成 .o 文件
%.o: %.c
规则表示每个.c
文件如何生成对应的.o
文件。
清理
clean
目标用于删除生成的可执行文件和对象文件。
伪目标
.PHONY
声明了all
和clean
为伪目标,这样即使有同名文件也不会影响make
的行为。
使用方法
- 编译所有目标:运行
make
。这会生成proc_A
和proc_B
可执行文件。 - 清理生成的文件:运行
make clean
。
扩展和修改
如果以后需要更改源文件名或添加新源文件,只需将新的源文件放在当前目录中,Makefile
会自动检测并处理它们,无需修改 Makefile
本身。