深入理解linux下write()和read()函数

深入理解linux下write()和read()函数1、write()函数定义:ssize_twrite(intfd,constvoid*buf,size_tcount);函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。附加说明:(1)write…

大家好,又见面了,我是你们的朋友全栈君。

1、write()

函数定义:ssize_t write (int fd, const void * buf, size_t count); 

函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。

返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。

附加说明:

(1)write()函数返回值一般无0,只有当如下情况发生时才会返回0:write(fp, p1+len, (strlen(p1)-len))中第三参数为0,此时write()什么也不做,只返回0。man手册给出的write()返回值的说明如下:

深入理解linux下write()和read()函数

(2)write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。如可按如下格式实现读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。

(3)在write一次可以写的最大数据范围内(貌似是BUFSIZ ,8192),第三参数count大小最好为buf中数据的大小,以免出现错误。(经过笔者再次试验,write一次能够写入的并不只有8192这么多,笔者尝试一次写入81920000,结果也是可以,看来其一次最大写入数据并不是8192,但内核中确实有BUFSIZ这个参数,具体指什么还有待研究)

以下通过一个例子具体说明write函数用法

#include <string.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
  char *p1 = "This is a c test code";
  volatile int len = 0;

  int fp = open("/home/test.txt", O_RDWR|O_CREAT);
  for(;;)
  {
     int n;

     if((n=write(fp, p1+len, (strlen(p1)-len)))== 0)   //if((n=write(fp, p1+len, 3)) == 0) 
     {                                                 //strlen(p1) = 21
         printf("n = %d \n", n);
         break;
     }
     len+=n;
  }
  return 0;
}

此程序中的字符串”This is a c test code”有21个字符,经笔者亲自试验,若write时每次写3个字节,虽然可以将p1中数据写到fp中,但文件test.txt中会带有很多乱码。唯一正确的做法还是将第三参数设为(strlen(p1) – len,这样当write到p1末尾时(strlen(p1) – len将会变为0,此时符合附加说明(1)中所说情况,write返回0, write结束。 

2、read()

函数定义:ssize_t read(int fd, void * buf, size_t count);

函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。

返回值:返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据。若参数count 为0, 则read()不会有作用并返回0。另外,以下情况返回值小于count:

(1)读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有50个字节而请求读100个字节,则read返回50,下次read将返回0。

(2)对于网络套接字接口,返回值可能小于count,但这不是错误,详细解释参考这篇文章socket编程中recv()和read()的使用与区别_hhhlizhao的博客-CSDN博客_read recv

注意:read时fd中的数据如果小于要读取的数据,就会引起阻塞。(关于read的阻塞情况评论区有朋友有不同意见,笔者查阅资料后作如下补充。)以下情况read不会引起阻塞:

(1)常规文件不会阻塞,不管读到多少数据都会返回;

(2)从终端读不一定阻塞:如果从终端输入的数据没有换行符,调用read读终端设备会阻塞,其他情况下不阻塞;

(3)从网络设备读不一定阻塞:如果网络上没有接收到数据包,调用read会阻塞,除此之外读取的数值小于count也可能不阻塞,原因见上面链接。

由于笔者水平有限,文中如有谬误之处还请读者朋友指出,以免误导大家。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/141170.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Git创建远程分支并提交代码到远程分支

    Git创建远程分支并提交代码到远程分支1、可以通过gitbranch-r命令查看远端库的分支情况如图所示,远程仓库只有一个master分支2、从已有的分支创建新的分支(如从master分支),创建一个dev分支但此时并没有在远程仓库上创建分支如图所示还是只有一个master分支3、建立本地到远端仓库的链接–这样代码才能提交上去使用命令行gitpush–set-…

  • c++迭代器iterator遍历map_iterator迭代器原理

    c++迭代器iterator遍历map_iterator迭代器原理什么是迭代器迭代器是一种可以遍历容器元素的数据类型。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。C++更趋向于使用迭代器而不是数组下标操作,因为标准库为每一种标准容器(如vector、map和list等)定义了一种迭代器类型,而只有少数容器(如vector)支持数组下标操作访问容器元素。可以通过迭代器指向你想访问容器的元素地址,通过*x打印出元素值。这和我们所熟知的指针极其类似。C语言有指针,指针用起来十分灵活高效。C++语言有迭代器,迭代器相对于指针而言功能更为丰富。vector,是数

    2022年10月29日
  • C语言——经典200道实例【基础例题100道——进阶例题100道】[通俗易懂]

    C语言——经典200道实例【基础例题100道——进阶例题100道】[通俗易懂]目录:===============================基础例题100道===============================1.输出”Hello,World!”2.输出整数3.输出单个字符4.输出浮点数5.输出双精度(double)数6.两个整数相加7.两个浮点数相乘8.字符转ASCII码(1)一次读取长字符,并一个一个显示…

  • 微信公众号开发系统入门教程(公众号注册、开发环境搭建、access_token管理、Demo实现、natapp外网穿透)

    微信公众号开发系统入门教程(公众号注册、开发环境搭建、access_token管理、Demo实现、natapp外网穿透)微信公众号主要有以下几个步骤微信公众号的通讯机制微信公众号简介1.注册微信公众号2.注册测试公众号3.搭建微信本地调试环境1)下载客户端natapp:2)安装natapp:4.微信公众号接入(校验签名)第1步中服务器配置包含服务器地址(URL)、令牌(Token)和消息加解密密钥(EncodingAESKey)。第2步,验证服务器地址的有效性,当点击“提交”…

  • Nginx服务器不支持PATH_INFO的问题及解决办法

    Nginx服务器不支持PATH_INFO的问题及解决办法

  • 腾讯云SSL证书_nginx反向代理配置证书

    腾讯云SSL证书_nginx反向代理配置证书申请SSL证书下载证书下载完证书之后解压,因为腾讯云选择的是nginx服务器,所以我们只需要下载nginx并解压。配置Nginx服务器我们需要把刚才解压的nginx证书文件拷贝到nginx的conf路径下面—也就是服务器中/etc/nginx/conf路径下面的。ssl_certificate1_bundle.crt;//如果文件不在conf路径下,就需要写绝对路径ssl_certificate_key1_mykey.key;重启nginx访问systemctlresta

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号