Linux的sendfile()为何与/dev/zero不兼容?代码报错原因咨询
问题原因分析
你的代码执行报错EINVAL(无效参数),核心原因有两点:
1. /dev/zero不符合sendfile()的源文件要求
Linux的sendfile()系统调用对源文件描述符有严格限制:
- 若用于在两个文件描述符间传输数据(非Socket场景),源文件描述符必须指向常规文件(即支持
seek()、mmap()等随机访问操作的普通文件)。 /dev/zero是字符特殊设备文件,它不支持随机访问(无法执行seek操作),也不满足sendfile()底层依赖的文件系统操作逻辑,因此无法作为源使用。
2. sendfile()的偏移参数使用错误
sendfile()的第三个参数offset是off_t*类型指针,用于指定源文件的读取起始偏移,调用后还会更新该值以反映实际读取位置:
- 当源文件描述符不是Socket时,这个参数不能传NULL(你的代码中传的
0等价于NULL),必须传入一个有效的off_t变量地址。哪怕源是合法的常规文件,传NULL也会触发EINVAL错误。
替代实现示例
如果需要实现从/dev/zero写入数据到临时文件的需求,可改用read()+write()的组合,示例代码如下:
#include <iostream> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <stdexcept> int main(){ int f1 = fileno(tmpfile()); int devzero = open("/dev/zero", O_RDONLY); if(f1 < 0 || devzero < 0){ throw std::runtime_error("Failed to open files"); } char buf[1]; ssize_t read_bytes = read(devzero, buf, sizeof(buf)); if(read_bytes > 0){ ssize_t written = write(f1, buf, read_bytes); std::cout << "written " << written << " bytes" << std::endl; } else { std::cout << "read failed. errno " << errno << " strerror " << strerror(errno) << std::endl; } close(devzero); close(f1); return 0; }
内容的提问来源于stack exchange,提问作者hanshenrik
相关产品推荐
相关产品推荐

