免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: rain_fish
打印 上一主题 下一主题

关于多线程对同一个文件进行写操作,记得坛子里面讨论过,不需要互斥,原因什么来着? [复制链接]

论坛徽章:
0
21 [报告]
发表于 2010-10-19 16:58 |只看该作者
回复 15# 思一克


    晕 确实应该交叉
从WRITE的语义上 传入的N是不被保证写完的
那么期望锁的区间要么没有 要么就是待写的这段
如果是后者空洞就造成大麻烦
问题是追加方式如果是如上所说可以留出空间然后并发写 也会有空洞问题啊 因为一般情况下你不会知道该留多少

论坛徽章:
0
22 [报告]
发表于 2010-10-19 17:00 |只看该作者
OS提供了专门的文件锁,在应用里是lockf, flock之类的函数。
从这个也可以知道write不是原子的。要原子地写,需要先用这类的锁起作用。

论坛徽章:
0
23 [报告]
发表于 2010-10-19 17:16 |只看该作者
晕 确实应该交叉
从WRITE的语义上 传入的N是不被保证写完的
那么期望锁的区间要么没有 要么就是待写的这段
如果是后者空洞就造成大麻烦
问题是追加方式如果是如上所说可以留出空间然后并发写 也会有空洞问题啊 因为一般情况下你不会知道该留多少
-----------
不是没写完的问题。传入的N写完也会交叉。

论坛徽章:
0
24 [报告]
发表于 2010-10-19 17:17 |只看该作者
晕 确实应该交叉
从WRITE的语义上 传入的N是不被保证写完的
那么期望锁的区间要么没有 要么就是待写的这段
如果是后者空洞就造成大麻烦
问题是追加方式如果是如上所说可以留出空间然后并发写 也会有空洞问题啊 因为一般情况下你不会知道该留多少
----------
APPEND知道留多少。根据write的块大小参数就知道了。

论坛徽章:
0
25 [报告]
发表于 2010-10-19 17:36 |只看该作者
回复 24# 思一克
    用关键字 '写文件'搜了C版 有数十帖问这个问题 所有的都看了遍

找到个帖子好象靠谱 当然可能漏了同一问题其他关键字帖子
http://bbs.chinaunix.net/viewthread.php?tid=908716
十楼


   
追加模式不能实现互斥,但能保证你要写的数据在一个页面内不交错
isnowran 发表于 2007-03-13 15:15


http://bbs.chinaunix.net/viewthr ... p;extra=&page=2
20楼
man 2 pread
man 2 pwrite
JohnBull 发表于 2007-06-19 23:12


  那么大致认为加锁才是真正安全的

追加方式不见得合理 比如WRITE不完全的时候 或许对日志要求不高时适用

最后的问题就是上面 追加方式在WRITE不完全的时候回形成空洞吗?
>>append方式下的write也会被打断,但空间保留了,回来再继续写不影响原子性。

按这个说法是会的.

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
26 [报告]
发表于 2010-10-19 17:45 |只看该作者
有时间测试一下。
能不能说一下为什么会交错呢?
-------------
sys_write磁盘文件不具有原子性。
writ ...
思一克 发表于 2010-10-19 16:35



感觉还是有点问题。

请看:

asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
{
     struct file *file;
     ssize_t ret = -EBADF;
     int fput_needed;
      file = fget_light(fd, &fput_needed);
     if (file) {
         loff_t pos = file_pos_read(file);
         ret = vfs_write(file, buf, count, &pos);
         file_pos_write(file, pos);
         fput_light(file, fput_needed);
     }
     return ret;
}

ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
     struct inode *inode = file->f_dentry->d_inode;
     ssize_t ret;

     if (!(file->f_mode & FMODE_WRITE))
         return -EBADF;
     if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
         return -EINVAL;
     ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
     if (!ret) {
         ret = security_file_permission (file, MAY_WRITE);
         if (!ret) {
              if (file->f_op->write)
                   ret = file->f_op->write(file, buf, count, pos);
              else
                   ret = do_sync_write(file, buf, count, pos);
              if (ret > 0)
                   dnotify_parent(file->f_dentry, DN_MODIFY);
         }
     }

     return ret;
}

从上面源码可以看出:
1.locks_verify_area是对文件某部分的区域锁,如果两次write()的时候,不是在文件同一个区域的话,应该就不会有问题,即不会出现交叉出错的情况
2.如果两次write()的时候,是在文件同一个区域的话,那么应该会出现交叉出错或者覆盖的情况。
         loff_t pos = file_pos_read(file);        
      ret = vfs_write(file, buf, count, &pos);
         file_pos_write(file, pos);
    可以从粗体的部分可以看出。

不知道是不是这样?

论坛徽章:
0
27 [报告]
发表于 2010-10-19 18:21 |只看该作者
从上面源码可以看出:
1.locks_verify_area是对文件某部分的区域锁,如果两次write()的时候,不是在文件同一个区域的话,应该就不会有问题,即不会出现交叉出错的情况
2.如果两次write()的时候,是在文件同一个区域的话,那么应该会出现交叉出错或者覆盖的情况。
         loff_t pos = file_pos_read(file);        
      ret = vfs_write(file, buf, count, &pos);
         file_pos_write(file, pos);
    可以从粗体的部分可以看出。

不知道是不是这样?
------------------------
是的。不在同一区域不会交叉。因为应用都没有交叉。
出现AABBABBBBBA是在应用重叠的时候。
如果写是原子的,就能确保不会交叉,无论应用层如何写。

论坛徽章:
0
28 [报告]
发表于 2010-10-19 18:35 |只看该作者
可以编写一个程序,5个线程,4个往同一打开的文件的同一位置(SEEK = 0)写一块(比如1024字节)数据。
数据是111111.。。     2222222222.。。。。  3333333333.。。。。。。。 44444444

一个线程读出全部数据。
如果读出的不全是一样的字节,就是交叉了。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
29 [报告]
发表于 2010-10-19 23:19 |只看该作者
从上面源码可以看出:
1.locks_verify_area是对文件某部分的区域锁,如果两次write()的时候,不是在文件同 ...
思一克 发表于 2010-10-19 18:21



    恩,看来终于讲到一起去了,

send()会是怎样呢? 感觉更加复杂,因为关系到tcp的一些流量控制等。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
30 [报告]
发表于 2010-10-19 23:20 |只看该作者
可以编写一个程序,5个线程,4个往同一打开的文件的同一位置(SEEK = 0)写一块(比如1024字节)数据。
数据 ...
思一克 发表于 2010-10-19 18:35



  为什么加个O_APPEND就是原子操作? 源码中哪里有体现吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP