免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
76 [报告]
发表于 2010-10-22 10:31 |只看该作者
回复 75# qingfenghao

为什么实际会比较少产生数据不完整的情况?因为发生的概率比较低,多个线程对同一文件而且要对相同的一个以上的扇区同时写入,才有可能。为了确保这一点,
多个线程都要对文件的同一个position,而且要写入512个字节以上才可确保冲突存在。而冲突存在也不定会发生,这还和当时线程调度的具体情况有关。当然,写入的数据
越多,冲突的可能性越大。写入1024字节就比写入512字节发生冲突的可能性高。有兴趣可以写代码试试。

论坛徽章:
0
75 [报告]
发表于 2010-10-22 10:23 |只看该作者
回复 74# chenzhanyiczy
首先阐明两个概念:原子操作,可被打断(中断)和数据完整性(data integrity)。
不可被打断的操作一定是原子操作,但原子操作不一定非得不可被打断,而只是指不可被对同一数据资源的操作打断。
也就是说:原子操作只是说对本数据或资源的操作是原子的。而由其他进/线程执行的对其他数据或资源的操作是可以打断本操作的。
就像你用mutex锁定对一段数据的访问,但这并不会不被其他线程打断。
所以原子操作应该和一段数据/资源的访问相提才是有意义的。而数据完整性是指数据操作的结果和所期望的是一致的。
多线程环境下,原子操作可以保证数据完整性,否则不可以。

再来看read和write函数。所以问题就是:write函数本身是否可以保证多线程对同一文件写的数据完整性?
答案是NO。

因为内核对文件的读写事实上是按块(扇区)为单位进行的,一般每个扇区大小默认512字节,当然程序可调。
而内核的write实现并没有保证它是原子的,而只是保证它对单个扇区的读写是原子的,因为硬盘的读写就是以扇区为单位的。
这也提高了效率,否则如果write操作写的是两个不同的文件,那么如果write是原子的性能就很低。

所以只要你让多个线程同时写入一个以上字节的数据到同一文件,就可能导致数据的不完整。
假设两个线程t1,t2:
  1. write(fd, "ab");
  2. write(fd, "cd");
复制代码
那么a可能写入到扇区x,b写入到扇区x+1。
c写入到扇区x,d写入到扇区x+1。
这样写入顺序就有6种:
  1. a, b, c, d-------结果-------->cd
  2. a, c, b, d------结果--------->bd
  3. a, c, d, b------结果--------->db
  4. c, d, a, b------结果--------->ab
  5. c, a, d, b------结果--------->db
  6. c, a, b, d------结果--------->bd
复制代码
结果有4种:ab,db,bd,cd
这4种结果只有2种是数据完整的:ab和cd,假如你不关心写入顺序的话。其他都被写乱了。
所以数据完整性应该由调用者自己来保证。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
74 [报告]
发表于 2010-10-21 20:53 |只看该作者
回复  chenzhanyiczy


    这段到没注意到.
不过并不矛盾
恰恰是我(6;4)楼说的因为偏移导致的错乱 而 ...
epegasus 发表于 2010-10-21 19:10



这个跟长短没有关系,只要是同一个页块内就会发生交叉。

论坛徽章:
0
73 [报告]
发表于 2010-10-21 19:14 |只看该作者
回复 68# epegasus

我对这个问题的细节也不是100%熟悉,所以是在讨论。
你的分析结论好像是不对的。

2个进程同时写同一个文件的同一位置也有交错发生,很容易编程实验出来。
还有,交错不是因为没有写完(write返回值不等于参数数值)。而是完全写完的时候发生的交错。
也就是说,write完全写完的时候,写不是原子的。

还有,pipefs是用inode锁的,并且是不可SEEK的(排除了SEEK错误引起的覆盖)。
pipe不会重叠,但多个进程写一个pipe在块大小超过PIPE_BUF时候不是原子的,数据交错的乱七八糟。但数据没有丢一个字节。

所以,你说写文件用inode->i_mutex互斥了,只有第一个write写完,才进行第二个write应该不正确。

请再详细研究看。

论坛徽章:
0
72 [报告]
发表于 2010-10-21 19:10 |只看该作者
回复 70# chenzhanyiczy


    这段到没注意到.
不过并不矛盾
恰恰是我(6;4)楼说的因为偏移导致的错乱 而不是因为并行交叉写
所以我上面好几个帖子提到测试方法都强调要2个进程写入通样长度的.
你2个不一样长.发生了错乱就无法分辨到底是什么引起的

论坛徽章:
0
71 [报告]
发表于 2010-10-21 17:47 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
70 [报告]
发表于 2010-10-21 17:27 |只看该作者
回复  思一克


    如果这样,那么多个进程不断写同一个文件的同一位置(比如0---1024)能如何交错法? ...
epegasus 发表于 2010-10-21 17:01



    "应该不会有任何交错.一切符合上面说的.包括跨页块的写"
请问,有代码证据吗?

比如:
线程a write 5个字节(11111)
线程b write 1个字节(2)

如果两次write成功的话,那么你觉得应该不会出现:12111 或者 11211 等等,而可能出现11112,21111的情况?
如果是的话,那么请看下面源码:
asmlinkage ssize_t sys_read(unsigned int fd, 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_read(file, buf, count, &pos);      --------> b阻塞在这,a也阻塞在这,但a是执行的,b是等待a执行完再执行的
         file_pos_write(file, pos);                  ----->假设a执行到,现在才更新pos,而b现在开始执行在vfs_read(),pos是原来的pos
         fput_light(file, fput_needed);
     }

     return ret;
}

论坛徽章:
0
69 [报告]
发表于 2010-10-21 17:02 |只看该作者
回复 67# sumland


    没完过.我没有UNIX-LINUX环境

论坛徽章:
0
68 [报告]
发表于 2010-10-21 17:01 |只看该作者
回复 65# 思一克


    如果这样,那么多个进程不断写同一个文件的同一位置(比如0---1024)能如何交错法?
---------------------------------

应该不会有任何交错.一切符合上面说的.包括跨页块的写
说"应该"是因为我只能确定ext2,对于ext3我还有不确定的地方.即写本身到磁盘分成好几步.它的写是通过一种异步实现的,所以没搞清楚

测试是否交错有一种方法:
一个重复的写2个字符AB
另一个重复写CD
2个都是从0偏移开始
不管用不用追加方式.都不应该看到单独的被拆分的A 或 B或C或D出现.
不过这个条件建立在一个write要么写2个字符成功.要么一个都写不进
如果出现单独的说明 写如一个就终止的,这种情况APUE没有明说 linux系统编程(by robert love)倒是说了可能存在.




如果按你这样分析,多个进程写同一个pipefd, 数据会交叉吗?
如何交叉?
---------------------------------------------------------------------------
pipe和普通磁盘文件系统是一样 也通过mutex_lock(&inode->i_mutex)保护
所以结论和上面的ext2一样 但是对于pipe或许出现写入字节数小于传入字节数的可能性更大.----要确定这个要看pipe是如何定义和实现的.我不能确定.
而pipe写还可能已经类似普通文件一样默认就是O_APPEND方式,所以我认为写它真的不需要加锁.

论坛徽章:
0
67 [报告]
发表于 2010-10-21 16:44 |只看该作者
回复 2# epegasus
请问大侠 apue中的例程你敲过吗?我现在在官网上下的包apue.linux.tar.gz怎么装不上呢?想安装它的头文件,才能运行书中的例子,但是我一直没能装上去,很头疼。。。
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP