前言 - 赠送 readn / writen
Linux 上默认的 read 和 write 函数会被信号软中断. 且 read 和 write 函数中第三个参数 count
#include <unistd.h> extern ssize_t read(int fd, void * buf, size_t count); extern ssize_t write(int fd, const void * buf, size_t count);
也会因内部缓冲机制, 不一定保证读取或写入到指定 count 大小数据.
这里将 read 和 write 拓展成 readn 和 writen
// // readn - 力求读取 n 个字节 // fd : 文件描述符 // buf : 缓冲区 // n : 读取长度 // return : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n // ssize_t readn(int fd, void * buf, size_t n) { size_t div = n; char * ptr = buf; while (div > 0) { ssize_t ret = read(fd, ptr, div); if (ret < 0) { if (errno == EINTR) continue; return -1; } if (ret == 0) break; ptr += ret; div -= ret; } return n - div; } // // writen - 力求写入 n 个字节 // fd : 文件描述符 // buf : 缓冲区 // n : 读取长度 // return : 返回写入长度, -1 标识错误, 默认 n // ssize_t writen(int fd, const void * buf, size_t n) { size_t div = n; const char * ptr = buf; while (div > 0) { ssize_t ret = write(fd, ptr, div); if (ret <= 0) { if (errno == EINTR) continue; return -1; } ptr += ret; div -= ret; } return n; }
有了这些收获, 不妨写个小测试
#include <stdio.h> #include <errno.h> #include <assert.h> #include <unistd.h> // // readn - 力求读取 n 个字节 // fd : 文件描述符 // buf : 缓冲区 // n : 读取长度 // return : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n // extern ssize_t readn(int fd, void * buf, size_t n); // // writen - 力求写入 n 个字节 // fd : 文件描述符 // buf : 缓冲区 // n : 读取长度 // return : 返回写入长度, -1 标识错误, 默认 n // extern ssize_t writen(int fd, const void * buf, size_t n); /* _oo0oo_ o8888888o 88" . "88 (| -_- |) 0 = /0 ___/`---'\___ .' \| |// '. / \||| : |||// / _||||| -:- |||||- | | \ - /// | | | \_| ''---/'' |_/ | .-\__ '-' ___/-. / ___'. .' /--.-- `. .'___ ."" '< `.___\_<|>_/___.' >' "". | | : `- \`.;` _ /`;.`/ - ` : | | `_. \_ __ /__ _/ .-` / / =====`-.____`.___ \_____/___.-`___.-'===== `=---=' */ int main(int argc, char * argv[]) { ssize_t ret = writen(STDOUT_FILENO, "12345 1", 6); printf("ret = %ld ", ret); char buf[4]; ret = readn(STDIN_FILENO, buf, 3); buf[3] = '