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

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()返回值的说明如下:

(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也可能不阻塞,原因见上面链接。

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

  • 112
    点赞
  • 508
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
### 回答1: Linux 操作系统中的 write() 和 read() 函数是文件 I/O(输入/输出)操作的基础。 write() 函数用于向文件中写入数据,其原型为: ``` ssize_t write(int fd, const void *buf, size_t count); ``` 其中 fd 是文件描述符,buf 是要写入的数据缓冲区,count 是要写入的字节数。 read() 函数用于从文件中读取数据,其原型为: ``` ssize_t read(int fd, void *buf, size_t count); ``` 其中 fd 是文件描述符,buf 是读取的数据缓冲区,count 是要读取的字节数。 两个函数均返回实际读写字节数,读写失败返回-1. ### 回答2: 在Linux系统下,write()和read()函数是用于文件I/O操作的常用函数之一。write()函数可以将指定长度的数据从缓冲区中写入到文件中,而read()函数则可以将文件中指定长度的数据读取到缓冲区中。 write()函数的语法如下: ``` ssize_t write(int fd, const void *buf, size_t count); ``` 其中,fd参数是文件描述符,对于要写入数据的文件,需要先打开,并且获得该文件的文件描述符;buf参数是要写入的数据所在的缓冲区,count参数是要写入的数据的字节数。该函数执行成功后,会返回写入数据的字节数,如果出现错误,会返回-1。 read()函数的语法如下: ``` ssize_t read(int fd, void *buf, size_t count); ``` 其中,fd参数和write()函数中的相同;buf参数是要读取数据所在的缓冲区,count参数是要读取的数据的字节数。执行成功后,该函数会返回读取数据的字节数,如果出现错误,也会返回-1。 需要注意的是,write()和read()函数一般情况下是阻塞的,在等待操作完成的过程中会一直等待,直到完成后返回。除此之外,还有一些相关的函数,如writev()和readv()函数,可以实现对多个缓冲区的写入和读取。 在Linux系统中,write()和read()函数是常用的文件I/O操作函数,具有很高的灵活性和适应性,能够应对各种类型的文件操作,而在网络编程中也经常用到它们,如实现socket通讯。虽然在使用这些函数时需要格外谨慎,确保程序的安全性和可靠性,但是它们是Linux系统中必不可少的重要函数。 ### 回答3: 在Linux系统中,write()和read()函数C语言中用于读写文件的基本函数。这两个函数分别被用于写操作和读操作,是Linux系统中最常用的函数之一。 write()函数的语法为:ssize_t write(int fd, const void *buf, size_t count)。它的作用是将buf指向的数据写入文件描述符为fd的文件中。其中,buf是需要写入的数据的指针,count是需要写入的数据的长度。函数返回值为实际写入的字节数。 read()函数的语法为:ssize_t read(int fd, void *buf, size_t count)。它的作用是将文件描述符为fd的文件中的数据读入到buf指向的缓冲区中。其中,buf是需要读取的缓冲区的指针,count是需要读取的数据的长度。函数返回值为实际读取的字节数。 这两个函数都是系统调用,因此操作系统会为它们提供底层支持。在使用这两个函数时,需要注意以下几点: 1. 文件描述符必须是有效的,否则将无法完成读写操作。 2. 在读取时,读取数据的长度必须小于或等于文件的当前长度,否则将读取到文件末尾的空白区域。 3. 在写入时,写入数据的长度必须小于或等于文件系统的剩余空间,否则将出现文件写满导致写入失败。 4. 在使用这两个函数时,需要使用正确的参数,否则会发生未定义的行为或错误。 总之,在Linux系统中,write()和read()函数是非常重要的函数,它们提供了文件I/O基础功能,涉及到文件操作的各种应用场景。因此,需要掌握它们的用法,以便对Linux系统进行更深入的了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值