c++ - 为什么当我的程序在 Linux 上运行时 splice syscall 失败,但在 gdb 中运行时成功?
问题描述
我尝试运行一本书的示例代码。它的功能是接受一行输入并将其输出到标准输出和操作参数指定的文件中。这是代码:
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
int main( int argc, char* argv[] )
{
if ( argc != 2 )
{
printf( "usage: %s <file>\n", argv[0] );
return 1;
}
int filefd = open( argv[1], O_CREAT | O_WRONLY | O_TRUNC, 0666 );
assert( filefd > 0 );
int pipefd_stdout[2];
int ret = pipe( pipefd_stdout );
assert( ret != -1 );
int pipefd_file[2];
ret = pipe( pipefd_file );
assert( ret != -1 );
//the first splice()
ret = splice( STDIN_FILENO, NULL, pipefd_stdout[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
ret = tee( pipefd_stdout[0], pipefd_file[1], 32768, SPLICE_F_NONBLOCK );
assert( ret != -1 );
//the second splice()
ret = splice( pipefd_file[0], NULL, filefd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
//the third splice()
ret = splice( pipefd_stdout[0], NULL, STDOUT_FILENO, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
printf("errno:%d\n",errno);
assert( ret != -1 );
close( filefd );
close( pipefd_stdout[0] );
close( pipefd_stdout[1] );
close( pipefd_file[0] );
close( pipefd_file[1] );
return 0;
}
编译代码后,我运行它并输入“123”,它无法输出到标准输出,第三个 splice() 失败,errno 为 22。这是结果的屏幕截图: p1
当我使用 gdb 运行代码时,它可以正常工作。这是截图: p2
内核版本:4.19.163-1
gcc 版本:10.2.0
gdb 版本:10.1
我的编译命令:g++ test.cpp -g -o LinuxServer
我的运行命令:./LinuxServer test.txt
我的 gdb 命令:gdb LinuxServer
那么为什么当我的程序在 Linux 上运行时 splice 系统调用失败,但在 gdb 中运行时却成功了呢?
解决方案
在linux手册splice(2)中有描述ERRORS: EINVAL The target file is open in append mode。
我终端中的标准输出处于附加模式,这就是第三个拼接系统调用失败的原因。
为了解决这个问题,我们可以fcntl(STDOUT_FILENO, F_SETFL, fcntl(STDOUT_FILENO, F_GETFL) & ~O_APPEND);
在 splice syscall 之前添加。
推荐阅读
- sql - 如何替换从 XML 读取的多个值并将其存储到 SQL 数据库
- java - 数据库中每个事务的通知
- ajax - Drupal 8表单提交Ajax表单后的回调
- ios - 有没有办法在使用 expo 的 react-native 中根据电话语言翻译上下文菜单?
- java - apache lucene 的更新使用方式
- amazon-web-services - Amazon S3 可公开读取的存储桶是否损坏
- javascript - 匹配输出的两个数组索引位置
- mongodb - Docker 容器意外失败
- mysql - 如果不存在,则将值插入 MySQL
- python - Python Pandas 在合并时返回内存错误