使用write系统调用实现echo命令时输出字符长度异常原因排查
为什么用write系统调用实现echo会输出异常?
问题重现
正常工作的printf实现
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { while (--argc) printf(((argc == 1) ? "%s\n" : "%s "), *++argv); }
运行结果:
$ ./a.out Bring a towel Bring a towel
输出异常的write实现
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char *argv[]) { while (--argc) { write(STDOUT_FILENO, *++argv, strlen(*argv)); write(STDOUT_FILENO, ((argc == 1) ? "\n" : " "), 1); } }
运行结果:
$ ./a.out Bring a towel Bringa atow t
问题原因
核心问题在于write系统调用不保证一次性写入所有请求的字节数。
当调用write时,操作系统可能因为输出缓冲区已满、设备繁忙等原因,只写入部分字节,并返回实际写入的字节数。你直接忽略了write的返回值,没有处理部分写入的情况,导致部分字符未被输出,后续的write操作拼接了不完整的内容,最终出现混乱的输出。
相比之下,printf属于标准IO库函数,内部已经封装了循环写入的逻辑,会自动处理部分写入的情况,确保所有数据都被输出。
另外,你尝试的fflush(stdout)对write无效——write绕过了标准IO的缓冲区,直接操作内核缓冲区,fflush仅对标准IO的缓冲区生效。
解决办法
实现一个封装函数,确保所有请求的字节都被写入:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> // 确保完整写入所有字节的封装函数 ssize_t full_write(int fd, const void *buf, size_t count) { const char *ptr = buf; size_t remaining = count; while (remaining > 0) { ssize_t written = write(fd, ptr, remaining); if (written == -1) { perror("write failed"); return -1; } remaining -= written; ptr += written; } return count; } int main(int argc, char *argv[]) { while (--argc) { full_write(STDOUT_FILENO, *++argv, strlen(*argv)); full_write(STDOUT_FILENO, ((argc == 1) ? "\n" : " "), 1); } return 0; }
这个函数会循环调用write,直到所有字节都被写入或遇到错误,从而保证输出内容完整且正确。
内容的提问来源于stack exchange,提问作者Mate de Vita
相关产品推荐
相关产品推荐

