免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3382 | 回复: 8
打印 上一主题 下一主题

write的原子操作问题. [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-06-18 11:40 |只看该作者 |倒序浏览
两个进程并发写write文件,数据是否会交叉?
IEEE的规范是要求只要小于一个值,就可以保证写是原子操作,不会被其他进程的数据交叉.

我看到管道写数据是有限制的PIPE_BUF,普通文件呢?也是这个上限?还是必须加append?

我最关心的是我在write的时候是否会被其他进程中途打断,写成别的数据.写完后被其他进程修改是允许的.

比如a进程写文件从偏移0开始10个字节a.
b进程写文件从偏移0开始10个字节b.

如果是原子操作则结果应该是10个a,或者10个b,但不应该出现ab交错.

原子操作的函数有哪些?

论坛徽章:
0
2 [报告]
发表于 2006-06-18 11:51 |只看该作者
write是原子操作,如果不放心的话可以加锁

论坛徽章:
0
3 [报告]
发表于 2006-06-18 13:11 |只看该作者
APUE相关说明

  1. 3.11. Atomic Operations
  2. Appending to a File
  3. Consider a single process that wants to append to the end of a file. Older versions of the UNIX System didn't support the O_APPEND option to open, so the program was coded as follows:

  4.      if (lseek(fd, 0L, 2) < 0)                /* position to EOF */
  5.         err_sys("lseek error");
  6.      if (write(fd, buf, 100) != 100)          /* and write */
  7.         err_sys("write error");



  8. This works fine for a single process, but problems arise if multiple processes use this technique to append to the same file. (This scenario can arise if multiple instances of the same program are appending messages to a log file, for example.)

  9. Assume that two independent processes, A and B, are appending to the same file. Each has opened the file but without the O_APPEND flag. This gives us the same picture as Figure 3.7. Each process has its own file table entry, but they share a single v-node table entry. Assume that process A does the lseek and that this sets the current offset for the file for process A to byte offset 1,500 (the current end of file). Then the kernel switches processes, and B continues running. Process B then does the lseek, which sets the current offset for the file for process B to byte offset 1,500 also (the current end of file). Then B calls write, which increments B's current file offset for the file to 1,600. Because the file's size has been extended, the kernel also updates the current file size in the v-node to 1,600. Then the kernel switches processes and A resumes. When A calls write, the data is written starting at the current file offset for A, which is byte offset 1,500. This overwrites the data that B wrote to the file.

  10. The problem here is that our logical operation of "position to the end of file and write" requires two separate function calls (as we've shown it). The solution is to have the positioning to the current end of file and the write be an atomic operation with regard to other processes. Any operation that requires more than one function call cannot be atomic, as there is always the possibility that the kernel can temporarily suspend the process between the two function calls (as we assumed previously).

  11. The UNIX System provides an atomic way to do this operation if we set the O_APPEND flag when a file is opened. As we described in the previous section, this causes the kernel to position the file to its current end of file before each write. We no longer have to call lseek before each write.

  12. pread and pwrite Functions
  13. The Single UNIX Specification includes XSI extensions that allow applications to seek and perform I/O atomically. These extensions are pread and pwrite.


  14. [View full width]
  15. #include <unistd.h>

  16. ssize_t pread(int filedes, void *buf, size_t
  17. nbytes, off_t offset);




  18. Returns: number of bytes read, 0 if end of file, 1 on error


  19. [View full width]
  20. ssize_t pwrite(int filedes, const void *buf,
  21. size_t nbytes, off_t offset);



  22. Returns: number of bytes written if OK, 1 on error





  23. Calling pread is equivalent to calling lseek followed by a call to read, with the following exceptions.

  24. There is no way to interrupt the two operations using pread.

  25. The file pointer is not updated.

  26. Calling pwrite is equivalent to calling lseek followed by a call to write, with similar exceptions.

  27. Creating a File
  28. We saw another example of an atomic operation when we described the O_CREAT and O_EXCL options for the open function. When both of these options are specified, the open will fail if the file already exists. We also said that the check for the existence of the file and the creation of the file was performed as an atomic operation. If we didn't have this atomic operation, we might try

  29.     if ((fd = open(pathname, O_WRONLY)) < 0) {
  30.         if (errno == ENOENT) {
  31.             if ((fd = creat(pathname, mode)) < 0)
  32.                  err_sys("creat error");
  33.         } else {
  34.             err_sys("open error");
  35.         }
  36.     }



  37. The problem occurs if the file is created by another process between the open and the creat. If the file is created by another process between these two function calls, and if that other process writes something to the file, that data is erased when this creat is executed. Combining the test for existence and the creation into a single atomic operation avoids this problem.

  38. In general, the term atomic operation refers to an operation that might be composed of multiple steps. If the operation is performed atomically, either all the steps are performed, or none are performed. It must not be possible for a subset of the steps to be performed. We'll return to the topic of atomic operations when we describe the link function (Section 4.15) and record locking (Section 14.3).
复制代码

似乎还可以采用其他的同步方式来代替原子操作并要注意对write返回值做检查,防止write被中断

论坛徽章:
0
4 [报告]
发表于 2006-06-18 16:14 |只看该作者
谢谢crspo,fh。
这个我也看过。

并发应该是没有问题了。

但其实有个问题没有明确的指出就是write的原子操作数据长度是否有限制?
在apue中对管道的描写是有限制的,限制是pipe_buf。
普通文件的限制呢?


同样可以引申出来一个定义是对于一个文件,
在某一时刻真正写到磁盘的操作并不是并发的,或许是并发的,那内核需要做判断,原子操作不能被交叉。

论坛徽章:
0
5 [报告]
发表于 2006-06-18 16:58 |只看该作者
write写到文件似乎没有长度限制,总是能一次成功。
LZ好好man一下文档,曾经见过一个说的比较详细的。

论坛徽章:
0
6 [报告]
发表于 2006-06-18 18:20 |只看该作者
原帖由 FH 于 2006-6-18 16:58 发表
write写到文件似乎没有长度限制,总是能一次成功。
LZ好好man一下文档,曾经见过一个说的比较详细的。

长度一般没有限制,但是有些系统比如AIX(其他系统没注意),好像有一个限制,具体多少,忘记了(2G以上),这是受分配的segment的限制。

论坛徽章:
0
7 [报告]
发表于 2006-06-18 18:33 |只看该作者
Good! 学习中 ...

论坛徽章:
0
8 [报告]
发表于 2006-06-18 23:12 |只看该作者
原帖由 圆点坐标 于 2006-6-18 18:20 发表

长度一般没有限制,但是有些系统比如AIX(其他系统没注意),好像有一个限制,具体多少,忘记了(2G以上),这是受分配的segment的限制。


倒!俺从来没申请过超过64K的内存!

论坛徽章:
0
9 [报告]
发表于 2006-06-18 23:57 |只看该作者
大家可能没有注意这句,PIPE_BUF,管道有限制,我分析普通文件也是有限制的。
但apue没有明确指出,有空的话,我man下看看。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP