3.11 pwrite函数-文件原子写

pwrite函数用于从打开文件的指定位置处写入指定字节的数据。函数原型如下:

#include <unistd.h>
ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
返回值:若写入成功则返回实际写入的字节数,若出错则返回-1。

参数:

1、filedes文件标识符;

2、*buf要写入到文件的数据的缓冲区;

3、nbytes要写入的字节数;

4、offset文件指针。

pwrite相当于先调用lseek接着调用write。但又不完全是这样:

(1)pwrite是原子操作,定位和写操作在一个原子操作中完成,期间不可中断。但分开的lseek和write中间可能被其他程序中断。

(2)pwrite不更改当前文件的指针,也就是说不改变当前文件偏移量。

(3)pwrite中的offset是一个绝对量,相对于文件开始处的绝对量,与当前文件指针位置无关。


实例 x.3.11.3.c

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define BUFFSIZE 256
int main(void)
{
    char        pathname[] = "/tmp/myfile";   /*待操作文件路径*/
    int         f_id;                         /*文件描述符*/

    off_t       f_offset;                     /*文件指针偏移量*/

    ssize_t     nwrite;                       /*实际写入的字节数*/
    char        buf[BUFFSIZE] = "0123456789"; /*待写入数据*/
    size_t      nbytes;                       /*准备写入的字节数*/

/*打开文件,获取文件标识符*/
    f_id = open(pathname, O_RDWR | O_CREAT);
    if (f_id == -1) {
        printf("open error for %s\n", pathname);
        return 1;
    }

/*把文件指针移动到文件开始处*/
    f_offset = lseek(f_id, 0, SEEK_SET);
    if (f_offset == -1) {
        printf("lseek error for %s\n", pathname);
        return 2;
    }

/*写入7个字节数据[0-6]*/
    nbytes = 7;
    nwrite = write(f_id, buf, nbytes);
    if (nwrite == -1) {
        printf("write error for %s\n", pathname);
        return 3;
    }

/*再写入3个字节数据[7-9]*/
    nbytes = 3;
    nwrite = write(f_id, (buf + 7), nbytes); 
    if (nwrite == -1) {
        printf("write error for %s\n", pathname);
        return 4;  
    }

/*关闭文件*/
    close(f_id);

    return 0;
}

编译与执行:

[root@localhost unixc]# rm -f /tmp/myfile
[root@localhost unixc]# cc x.3.11.3.c
[root@localhost unixc]# ./a.out
[root@localhost unixc]# cat /tmp/myfile
0123456789[root@localhost unixc]#

执行结束分析:每次调用write,文件指针都会往前移动nbytes个字节。这说明write会影响文件指针。


实例(在两次write之间调入一个pwrite调用) x.3.11.4.c

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define BUFFSIZE 256
int main(void)
{
    char        pathname[] = "/tmp/myfile";   /*待操作文件路径*/
    int         f_id;                         /*文件描述符*/

    off_t       f_offset;                     /*文件指针偏移量*/

    ssize_t     nwrite;                       /*实际写入的字节数*/
    char        buf[BUFFSIZE] = "0123456789abcd"; /*待写入数据*/
    size_t      nbytes;                       /*准备写入的字节数*/

/*打开文件,获取文件标识符*/
    f_id = open(pathname, O_RDWR | O_CREAT);
    if (f_id == -1) {
        printf("open error for %s\n", pathname);
        return 1;
    }

/*把文件指针移动到文件开始处*/
    f_offset = lseek(f_id, 0, SEEK_SET);
    if (f_offset == -1) {
        printf("lseek error for %s\n", pathname);
        return 2;
    }

/*写入7个字节数据[0-6]*/
    nbytes = 7;
    nwrite = write(f_id, buf, nbytes);
    if (nwrite == -1) {
        printf("write error for %s\n", pathname);
        return 3;
    }

/*=======调用pwrite从第一个字节后面写入四个字节数据[abcd]=======*/
    nbytes = 4;
    nwrite = pwrite(f_id, (buf + 10), nbytes, 1);
    if (nwrite == -1) {
        printf("pwrite error for %s\n", pathname);
        return 4;
    }

/*再写入3个字节数据[7-9]*/
    nbytes = 3;
    nwrite = write(f_id, (buf + 7), nbytes); 
    if (nwrite == -1) {
        printf("write error for %s\n", pathname);
        return 5;  
    }

/*关闭文件*/
    close(f_id);

    return 0;
}

编译与执行:

[root@localhost unixc]# rm -f /tmp/myfile
[root@localhost unixc]# cc x.3.11.4.c
[root@localhost unixc]# ./a.out
[root@localhost unixc]# cat /tmp/myfile
0abcd56789[root@localhost unixc]#

分析:第一次调用write写入了[0123456]七个数字,第二次调用pwrite从第一个字节[0]后面写入[abcd]四个字母,pwrite写入的[abcd]把write写入的[1234]给覆盖掉了,此时文件数据是[0abcd56],文件指针不变,指向[6]后面。接着继续调用write写入[789]三个数字,写入位置是第一次write后的位置,所以[789]在[6]后面。最后写入文件的数据是[0abcd56789]。可见,pwrite并不改变当前文件的指针。

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值