管道通信
了解了,如果你在Linux环境下开发,使用管道进行进程间通信(IPC)是一个良好的选择。以下是适用于Linux的代码示例:
程序A(发送端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define BUFFER_SIZE 65536 // 最大数据大小
// 简单的校验和算法
unsigned int checksum(const char *data, size_t len) {
unsigned int sum = 0;
for (size_t i = 0; i < len; i++) {
sum += (unsigned char)data[i];
}
return sum;
}
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程:接收端程序B
close(pipefd[1]); // 关闭写端
char buffer[BUFFER_SIZE];
ssize_t n;
while ((n = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
unsigned int received_checksum = *(unsigned int *)buffer;
unsigned int data_size = *(unsigned int *)(buffer + sizeof(unsigned int));
unsigned int calc_checksum = checksum(buffer + sizeof(unsigned int) * 2, data_size);
printf("B: Received %zu bytes of data\n", data_size);
if (received_checksum == calc_checksum) {
printf("B: Checksum correct\n");
write(pipefd[1], "OK", 2);
} else {
printf("B: Checksum incorrect\n");
write(pipefd[1], "ERROR", 5);
}
}
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else { // 父进程:发送端程序A
close(pipefd[0]); // 关闭读端
srand(time(NULL));
for (int i = 0; i < 10; i++) {
size_t data_size = rand() % (BUFFER_SIZE - sizeof(unsigned int) * 2) + 1;
char data[BUFFER_SIZE];
for (size_t j = 0; j < data_size; j++) {
data[j] = rand() % 256;
}
unsigned int data_checksum = checksum(data, data_size);
write(pipefd[1], &data_checksum, sizeof(data_checksum));
write(pipefd[1], &data_size, sizeof(data_size));
write(pipefd[1], data, data_size);
char response[5];
read(pipefd[1], response, sizeof(response));
if (strncmp(response, "OK", 2) == 0) {
printf("A: B received %zu bytes of data, checksum correct\n", data_size);
} else {
printf("A: B received %zu bytes of data, checksum incorrect\n", data_size);
}
sleep(1);
}
close(pipefd[1]);
wait(NULL); // 等待子进程结束
exit(EXIT_SUCCESS);
}
}
程序B(接收端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 65536 // 最大数据大小
// 简单的校验和算法
unsigned int checksum(const char *data, size_t len) {
unsigned int sum = 0;
for (size_t i = 0; i < len; i++) {
sum += (unsigned char)data[i];
}
return sum;
}
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程:接收端
close(pipefd[1]); // 关闭写端
char buffer[BUFFER_SIZE];
ssize_t n;
while ((n = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
unsigned int received_checksum = *(unsigned int *)buffer;
unsigned int data_size = *(unsigned int *)(buffer + sizeof(unsigned int));
unsigned int calc_checksum = checksum(buffer + sizeof(unsigned int) * 2, data_size);
printf("Received %zu bytes of data\n", data_size);
if (received_checksum == calc_checksum) {
printf("Checksum correct\n");
write(pipefd[1], "OK", 2);
} else {
printf("Checksum incorrect\n");
write(pipefd[1], "ERROR", 5);
}
}
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else { // 父进程:发送端
close(pipefd[0]); // 关闭读端
srand(time(NULL));
for (int i = 0; i < 10; i++) {
size_t data_size = rand() % (BUFFER_SIZE - sizeof(unsigned int) * 2) + 1;
char data[BUFFER_SIZE];
for (size_t j = 0; j < data_size; j++) {
data[j] = rand() % 256;
}
unsigned int data_checksum = checksum(data, data_size);
write(pipefd[1], &data_checksum, sizeof(data_checksum));
write(pipefd[1], &data_size, sizeof(data_size));
write(pipefd[1], data, data_size);
char response[5];
read(pipefd[1], response, sizeof(response));
if (strncmp(response, "OK", 2) == 0) {
printf("Data received, checksum correct\n");
} else {
printf("Data received, checksum incorrect\n");
}
sleep(1);
}
close(pipefd[1]);
wait(NULL); // 等待子进程结束
exit(EXIT_SUCCESS);
}
}
运行说明
- 编译这两个程序:
gcc -o sender sender.c
和gcc -o receiver receiver.c
。 - 先运行接收端(
./receiver
),然后运行发送端(./sender
)。接收端会处理数据和校验,发送端会发送数据并检查结果。
这个示例在Linux环境下利用管道实现了基本的进程间通信和数据校验功能。
修改(crc校验和定期发送)
要使进程A每隔 n
秒发送一次消息,可以在 while
循环中使用 sleep
函数来实现定时发送。你需要在 while
循环中添加一个延时操作,sleep(n)
可以使进程每隔 n
秒发送一次消息。以下是更新后的代码示例:
更新后的程序A(发送端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <zlib.h> // for crc32
#define BUFFER_SIZE 65536
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程:接收端
close(pipefd[1]); // 关闭写端
char buffer[BUFFER_SIZE];
ssize_t n;
while (1) {
n = read(pipefd[0], buffer, sizeof(buffer));
if (n <= 0) break; // 退出循环条件
uint32_t received_crc = *(uint32_t *)buffer;
uint32_t data_size = *(uint32_t *)(buffer + sizeof(uint32_t));
uint32_t calc_crc = crc32(0L, (const unsigned char *)buffer + sizeof(uint32_t) * 2, data_size);
printf("B: Received %zu bytes of data\n", data_size);
if (received_crc == calc_crc) {
printf("B: CRC correct\n");
write(pipefd[1], "OK", 2);
} else {
printf("B: CRC incorrect\n");
write(pipefd[1], "ERROR", 5);
}
}
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else { // 父进程:发送端
close(pipefd[0]); // 关闭读端
srand(time(NULL));
char data[BUFFER_SIZE];
int delay = 5; // 发送间隔,单位:秒
while (1) {
size_t data_size = rand() % (BUFFER_SIZE - sizeof(uint32_t) * 2) + 1;
for (size_t j = 0; j < data_size; j++) {
data[j] = rand() % 256;
}
uint32_t data_crc = crc32(0L, (const unsigned char *)data, data_size);
write(pipefd[1], &data_crc, sizeof(data_crc));
write(pipefd[1], &data_size, sizeof(data_size));
write(pipefd[1], data, data_size);
char response[5];
read(pipefd[1], response, sizeof(response));
if (strncmp(response, "OK", 2) == 0) {
printf("A: B received %zu bytes of data, CRC correct\n", data_size);
} else {
printf("A: B received %zu bytes of data, CRC incorrect\n", data_size);
}
sleep(delay); // 模拟延时,n秒
}
close(pipefd[1]);
wait(NULL);
exit(EXIT_SUCCESS);
}
}
在这个示例中,delay
变量定义了发送间隔时间(单位为秒)。你可以根据需要调整 delay
的值。
B端代码
当然,以下是更新后的程序B的代码,用于接收和验证来自程序A的数据。这个接收端程序将从管道读取数据,并计算其CRC值与发送的CRC值进行比较。
更新后的程序B(接收端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <zlib.h> // for crc32
#define BUFFER_SIZE 65536
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程:接收端
close(pipefd[1]); // 关闭写端
char buffer[BUFFER_SIZE];
ssize_t n;
while (1) {
n = read(pipefd[0], buffer, sizeof(buffer));
if (n <= 0) break; // 退出循环条件
// 读取CRC值和数据大小
uint32_t received_crc = *(uint32_t *)buffer;
uint32_t data_size = *(uint32_t *)(buffer + sizeof(uint32_t));
char *data = buffer + sizeof(uint32_t) * 2;
// 计算数据的CRC值
uint32_t calc_crc = crc32(0L, (const unsigned char *)data, data_size);
// 打印接收到的数据大小
printf("B: Received %zu bytes of data\n", data_size);
// 检查CRC值是否匹配
if (received_crc == calc_crc) {
printf("B: CRC correct\n");
write(pipefd[1], "OK", 2);
} else {
printf("B: CRC incorrect\n");
write(pipefd[1], "ERROR", 5);
}
}
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else { // 父进程:发送端
close(pipefd[0]); // 关闭读端
wait(NULL); // 等待子进程结束
close(pipefd[1]);
exit(EXIT_SUCCESS);
}
}
说明
-
管道:程序B使用管道来接收来自程序A的数据。它读取数据、计算CRC值并与接收到的CRC值进行比较,然后将结果返回到程序A。
-
数据处理:
- 从管道中读取数据并解析出CRC值、数据大小和实际数据。
- 使用
crc32
函数计算数据的CRC值,并将其与接收到的CRC值进行比较。 - 根据CRC值是否匹配,返回"OK"或"ERROR"到程序A。
-
通信:
- 程序B的接收端需要读取来自管道的数据,并在处理后将结果写回到管道中以通知程序A。
这个代码片段假设程序A和程序B在同一进程中运行,并且它们通过管道进行通信。你可以根据需要调整和测试这些代码。
父子进程管道通信
当然,这里是一个示例程序,展示了父子进程如何使用管道进行循环通信。在这个示例中,父进程将字符串发送到子进程,子进程接收到数据后将其返回给父进程。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 100
int main() {
int pipefd[2];
pid_t pid;
char buffer[BUFFER_SIZE];
// 创建管道
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
// 从管道读取数据
ssize_t bytesRead = read(pipefd[0], buffer, BUFFER_SIZE);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // 添加字符串结束符
printf("Child received: %s\n", buffer);
// 将数据返回到父进程
write(pipefd[1], buffer, bytesRead);
}
close(pipefd[0]); // 关闭读端
exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd[0]); // 关闭读端
// 写数据到管道
const char *message = "Hello from parent";
write(pipefd[1], message, strlen(message));
close(pipefd[1]); // 关闭写端
// 等待子进程
wait(NULL);
// 读取子进程返回的数据
pipefd[0]; // 重新打开读端
ssize_t bytesRead = read(pipefd[0], buffer, BUFFER_SIZE);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // 添加字符串结束符
printf("Parent received: %s\n", buffer);
}
close(pipefd[0]); // 关闭读端
}
return 0;
}
说明:
pipe(pipefd)
:创建一个管道,pipefd[0]
是读端,pipefd[1]
是写端。fork()
:创建一个子进程。- 在子进程中:
- 关闭写端。
- 从管道读取数据并打印。
- 关闭读端,并写回数据。
- 在父进程中:
- 关闭读端。
- 向管道写入数据。
- 关闭写端,并等待子进程结束。
- 重新打开读端读取子进程返回的数据。
这个程序展示了基本的父子进程间的管道通信和循环操作。
父子进程双pipe通信
如果你希望父进程和子进程之间能够一直进行通信,可以使用一个循环来持续交换消息。下面是一个示例程序,其中父进程和子进程通过管道进行循环通信,直到满足某个条件(例如,发送了特定的退出消息)为止:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <wait.h>
#define BUFFER_SIZE 100
#define EXIT_MESSAGE "exit"
void parent_process(int write_fd, int read_fd);
void child_process(int write_fd, int read_fd);
int main() {
int pipefd1[2]; // 用于父子进程的管道
int pipefd2[2]; // 用于子父进程的管道
pid_t pid;
// 创建两个管道
if (pipe(pipefd1) == -1 || pipe(pipefd2) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd1[1]); // 关闭写端
close(pipefd2[0]); // 关闭读端
child_process(pipefd2[1], pipefd1[0]);
close(pipefd1[0]); // 关闭读端
close(pipefd2[1]); // 关闭写端
exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd1[0]); // 关闭读端
close(pipefd2[1]); // 关闭写端
parent_process(pipefd1[1], pipefd2[0]);
close(pipefd1[1]); // 关闭写端
close(pipefd2[0]); // 关闭读端
// 等待子进程结束
wait(NULL);
}
return 0;
}
void parent_process(int write_fd, int read_fd) {
char buffer[BUFFER_SIZE];
while (1) {
// 从标准输入读取数据
printf("Parent: ");
fflush(stdout);
fgets(buffer, BUFFER_SIZE, stdin);
// 移除换行符
buffer[strcspn(buffer, "\n")] = '\0';
// 发送数据到子进程
write(write_fd, buffer, strlen(buffer) + 1);
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
break;
}
// 从子进程读取数据
read(read_fd, buffer, BUFFER_SIZE);
printf("Parent received: %s\n", buffer);
}
}
void child_process(int write_fd, int read_fd) {
char buffer[BUFFER_SIZE];
while (1) {
// 从父进程读取数据
read(read_fd, buffer, BUFFER_SIZE);
printf("Child received: %s\n", buffer);
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
break;
}
// 发送数据到父进程
write(write_fd, buffer, strlen(buffer) + 1);
}
}
说明:
- 创建两个管道:
pipefd1
用于父进程到子进程的通信,pipefd2
用于子进程到父进程的通信。 - 子进程和父进程:
- 子进程在
child_process
函数中运行,通过pipefd1
读取父进程的数据,通过pipefd2
发送数据回父进程。 - 父进程在
parent_process
函数中运行,通过pipefd2
读取子进程的数据,通过pipefd1
发送数据给子进程。
- 子进程在
- 循环通信:父进程和子进程都在循环中发送和接收消息,直到接收到退出消息 (
"exit"
) 为止。
在终端中运行该程序时,父进程等待用户输入数据并发送给子进程,子进程处理接收到的数据并将其返回给父进程,直到输入 "exit"
为止,进程才会退出。
非循环crc
如果父进程发送的数据长度不固定,可以通过以下步骤处理:
- 先发送数据长度:在发送实际数据之前,先发送数据的长度。
- 接收数据长度:子进程接收数据长度,然后接收相应长度的数据。
这里是调整后的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdint.h>
#define BUFFER_SIZE 1024
#define POLYNOMIAL 0xEDB88320L
// CRC-32计算函数
uint32_t crc32(uint32_t crc, const unsigned char *buf, size_t len) {
crc = ~crc;
while (len--) {
crc ^= *buf++;
for (int i = 0; i < 8; i++) {
if (crc & 1)
crc = (crc >> 1) ^ POLYNOMIAL;
else
crc >>= 1;
}
}
return ~crc;
}
void parent_process(int write_fd, int read_fd) {
char buffer[BUFFER_SIZE];
uint32_t crc;
size_t data_len;
// 准备数据
snprintf(buffer, BUFFER_SIZE, "Hello from parent! This is a test.");
data_len = strlen(buffer);
// 计算CRC
crc = crc32(0, (unsigned char*)buffer, data_len);
// 发送数据长度
write(write_fd, &data_len, sizeof(data_len));
// 发送数据
write(write_fd, buffer, data_len);
// 发送CRC
write(write_fd, &crc, sizeof(crc));
// 从子进程读取验证结果
int status;
read(read_fd, &status, sizeof(status));
if (status) {
printf("CRC check passed\n");
} else {
printf("CRC check failed\n");
}
}
void child_process(int write_fd, int read_fd) {
char buffer[BUFFER_SIZE];
uint32_t received_crc, computed_crc;
size_t data_len;
// 从父进程读取数据长度
read(read_fd, &data_len, sizeof(data_len));
// 从父进程读取数据
read(read_fd, buffer, data_len);
buffer[data_len] = '\0'; // 确保字符串结束
// 从父进程读取CRC
read(read_fd, &received_crc, sizeof(received_crc));
// 计算接收到数据的CRC
computed_crc = crc32(0, (unsigned char*)buffer, data_len);
// 校验CRC
int status = (computed_crc == received_crc) ? 1 : 0;
write(write_fd, &status, sizeof(status)); // 发送校验结果
}
int main() {
int pipefd1[2]; // 用于父子进程的管道
int pipefd2[2]; // 用于子父进程的管道
pid_t pid;
// 创建两个管道
if (pipe(pipefd1) == -1 || pipe(pipefd2) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd1[1]); // 关闭写端
close(pipefd2[0]); // 关闭读端
child_process(pipefd2[1], pipefd1[0]);
close(pipefd1[0]); // 关闭读端
close(pipefd2[1]); // 关闭写端
exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd1[0]); // 关闭读端
close(pipefd2[1]); // 关闭写端
parent_process(pipefd1[1], pipefd2[0]);
close(pipefd1[1]); // 关闭写端
close(pipefd2[0]); // 关闭读端
// 等待子进程结束
wait(NULL);
}
return 0;
}
修改点
- 发送数据长度:父进程先发送数据长度。
- 接收数据长度:子进程先接收数据长度,然后再接收数据和CRC码。
这样,无论数据长度多长,子进程都能正确处理。
父子进程随机发送数据
下面是一个使用 pipe
实现父子进程通信的示例程序,包含数据的传输和 CRC 校验功能。
1. CRC 校验函数
#include <stdint.h>
uint32_t crc32(const void *data, size_t length) {
static const uint32_t table[256] = {
// CRC-32表的内容
// 这里应该填入实际的CRC-32表数据
};
uint32_t crc = 0xFFFFFFFF;
const uint8_t *byte = (const uint8_t *)data;
for (size_t i = 0; i < length; i++) {
uint8_t table_index = (crc ^ byte[i]) & 0xFF;
crc = (crc >> 8) ^ table[table_index];
}
return crc ^ 0xFFFFFFFF;
}
2. 父子进程通信代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#define BUFFER_SIZE 1024 // 缓冲区大小
// CRC 校验函数声明
uint32_t crc32(const void *data, size_t length);
int main() {
int pipefd[2];
pid_t pid;
char buffer[BUFFER_SIZE];
uint32_t crc;
ssize_t bytes_written, bytes_read;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
// 从管道读取数据
bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if (bytes_read == -1) {
perror("read");
exit(EXIT_FAILURE);
}
// 读取 CRC
uint32_t received_crc;
memcpy(&received_crc, buffer + bytes_read - sizeof(received_crc), sizeof(received_crc));
// 计算 CRC
uint32_t computed_crc = crc32(buffer, bytes_read - sizeof(received_crc));
// 验证 CRC
if (computed_crc == received_crc) {
printf("子进程: 数据接收并验证成功\n");
} else {
printf("子进程: 数据验证失败\n");
}
close(pipefd[0]); // 关闭读端
} else { // 父进程
close(pipefd[0]); // 关闭读端
// 生成随机数据
size_t data_size = (rand() % (BUFFER_SIZE - 1)) + 1;
for (size_t i = 0; i < data_size; i++) {
buffer[i] = rand() % 256;
}
// 计算 CRC
crc = crc32(buffer, data_size);
// 发送数据和 CRC
memcpy(buffer + data_size, &crc, sizeof(crc));
bytes_written = write(pipefd[1], buffer, data_size + sizeof(crc));
if (bytes_written == -1) {
perror("write");
exit(EXIT_FAILURE);
}
close(pipefd[1]); // 关闭写端
}
return 0;
}
3. 编译和运行
编译并运行程序:
gcc -o parent_child_communication parent_child_communication.c
./parent_child_communication
4. 解释
- 父进程:生成随机数据,计算其 CRC 值,并将数据及 CRC 值通过管道发送给子进程。
- 子进程:从管道读取数据和 CRC 值,计算数据的 CRC 值,并与接收到的 CRC 值进行比较,验证数据完整性。
确保 CRC 表的内容正确并适配你的 CRC 校验需求。
crc库实现
使用 zlib
库的 crc32
函数可以简化 CRC 校验的实现。以下是基于 zlib
的父子进程通信示例程序:
1. 父子进程通信代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <zlib.h> // 包含 zlib 库
#define BUFFER_SIZE 1024 // 缓冲区大小
int main() {
int pipefd[2];
pid_t pid;
char buffer[BUFFER_SIZE];
uint32_t crc;
ssize_t bytes_written, bytes_read;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
// 从管道读取数据
bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if (bytes_read == -1) {
perror("read");
exit(EXIT_FAILURE);
}
// 读取 CRC
uint32_t received_crc;
memcpy(&received_crc, buffer + bytes_read - sizeof(received_crc), sizeof(received_crc));
// 计算 CRC
uint32_t computed_crc = crc32(0L, Z_NULL, 0); // 初始化 CRC
computed_crc = crc32(computed_crc, (const Bytef *)buffer, bytes_read - sizeof(received_crc));
// 验证 CRC
if (computed_crc == received_crc) {
printf("子进程: 数据接收并验证成功\n");
} else {
printf("子进程: 数据验证失败\n");
}
close(pipefd[0]); // 关闭读端
} else { // 父进程
close(pipefd[0]); // 关闭读端
// 生成随机数据
size_t data_size = (rand() % (BUFFER_SIZE - 1)) + 1;
for (size_t i = 0; i < data_size; i++) {
buffer[i] = rand() % 256;
}
// 计算 CRC
crc = crc32(0L, Z_NULL, 0); // 初始化 CRC
crc = crc32(crc, (const Bytef *)buffer, data_size);
// 发送数据和 CRC
memcpy(buffer + data_size, &crc, sizeof(crc));
bytes_written = write(pipefd[1], buffer, data_size + sizeof(crc));
if (bytes_written == -1) {
perror("write");
exit(EXIT_FAILURE);
}
close(pipefd[1]); // 关闭写端
}
return 0;
}
2. 编译和运行
确保已安装 zlib
库。编译并运行程序:
gcc -o parent_child_communication parent_child_communication.c -lz
./parent_child_communication
3. 解释
- 父进程:生成随机数据,计算其 CRC 值,并将数据和 CRC 值通过管道发送给子进程。
- 子进程:从管道读取数据和 CRC 值,计算数据的 CRC 值,并与接收到的 CRC 值进行比较,以验证数据的完整性。
zlib
提供了高效的 CRC 计算,简化了校验逻辑。