You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

char*类型共享内存收发数据量异常问题排查

共享内存传输文件数据量不符的解决方法

共享内存段类型为char*,发送端读取文件并将内容复制到共享内存地址current_channel.data,但出现发送端中strlen(data)远小于batch_read,导致收发数据量不符的问题。已确认其他变量正常,仅数据量获取存在问题。

发送端原代码

char data[GLOB_SEGSIZE];
char filesize[21];
batch_read = 0, start_point = 0;
while ((int)(batch_read = pread(fd, data, GLOB_SEGSIZE, start_point)) > 0)
{
    sem_wait(current_channel.writer_sem);
   
    strncpy(current_channel.data, data, (size_t)GLOB_SEGSIZE);
    start_point += batch_read;
    printf("%zu of %s\n", strlen(data), filesize);
    
    sem_post(current_channel.reader_sem);
}

接收端原代码

int curr_received = 0;
size_t filesize; // File size is received in the shared mem before the file transfer begins
while (curr_received < (int)filesize)
{
    sem_wait(current_channel.reader_sem);

    curr_received += strlen(current_channel.data);
    gfs_send(ctx, current_channel.data, strlen(current_channel.data));
    printf("%zu of %zu\n", strlen(current_channel.data), filesize);

    sem_post(current_channel.writer_sem);
}

问题原因

  1. strlen的局限性:strlen通过查找字符串结束符\0计算长度,若文件是二进制格式(包含\0字节),会提前终止计数;即使是文本文件,pread读取的原始数据不会自动添加\0,strlen会越界读取,结果完全不可靠。
  2. strncpy的隐患:strncpy遇到\0会停止复制,无法完整传输包含\0的二进制数据。

解决方法

1. 扩展共享内存结构

在current_channel中新增size_t batch_size字段,用于存储当前批次的有效字节数:

typedef struct {
    char data[GLOB_SEGSIZE];
    size_t batch_size; // 新增:记录当前批次实际数据长度
    sem_t writer_sem;
    sem_t reader_sem;
} Channel;

2. 修改发送端代码

  • 用memcpy替代strncpy,保证按字节完整复制数据
  • 直接使用batch_read(pread返回的实际读取字节数)作为有效长度,存入共享内存的batch_size字段
  • 打印和进度更新时不再依赖strlen

修改后代码:

char data[GLOB_SEGSIZE];
char filesize[21];
ssize_t batch_read = 0;
off_t start_point = 0;
while ((batch_read = pread(fd, data, GLOB_SEGSIZE, start_point)) > 0)
{
    sem_wait(&current_channel.writer_sem);
   
    memcpy(current_channel.data, data, (size_t)batch_read);
    current_channel.batch_size = (size_t)batch_read; // 写入实际数据长度
    start_point += batch_read;
    printf("%zd of %s\n", batch_read, filesize);
    
    sem_post(&current_channel.reader_sem);
}

3. 修改接收端代码

  • 从共享内存的batch_size字段获取当前批次的有效字节数
  • 传输数据和更新接收进度时,使用该batch_size代替strlen

修改后代码:

int curr_received = 0;
size_t filesize; // 文件大小已在传输前通过共享内存获取
while (curr_received < (int)filesize)
{
    sem_wait(&current_channel.reader_sem);

    size_t curr_batch_size = current_channel.batch_size;
    curr_received += (int)curr_batch_size;
    gfs_send(ctx, current_channel.data, curr_batch_size);
    printf("%zu of %zu\n", curr_batch_size, filesize);

    sem_post(&current_channel.writer_sem);
}

内容的提问来源于stack exchange,提问作者Josh Voytek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:30:50