免费注册 查看新帖 |

Chinaunix

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

[C] linux write 函数 是否是 线程安全的? [复制链接]

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
11 [报告]
发表于 2015-09-11 23:30 |只看该作者
我从posix的角度来解释一下这个问题:
首先我们根据posix的规定可以明定哪些系统调用是线程安全的"A function that may be safely invoked concurrently by multiple threads. Each function defined in the System Interfaces volume of POSIX.1-2008 is thread-safe unless explicitly stated otherwise. ",由标准的定义可知除非另行说明,否则常见的系统调用都是线程安全的。那么具体到write,其规定中并没有直接说明线程安全的问题,但着重说明了多个write可能导致的数据覆盖问题。write具体做了什么由如下规定"On a regular file or other file capable of seeking, the actual writing of data shall proceed from the position in the file indicated by the file offset associated with fildes. Before successful return from write(), the file offset shall be incremented by the number of bytes actually written. On a regular file, if the position of the last byte written is greater than or equal to the length of the file, the length of the file shall be set to this position plus one. ",从上面的操作可知write不是个原子操作,一次成功的write需要seeking和writing两个动作,所以原则上来讲write是非线程安全的。进而关于write有如下规定"This volume of POSIX.1-2008 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control.",显然多进程操作同一文件肯定是需要同步的,但是多线程就没有更多的规定了,只能推断write是非线程安全的(因为不是原子操作),至于write写socket那么就肯定是线程安全的,因为有如下规定"If fildes refers to a socket, write ( ) shall be equivalent to send ( ) with no flags set.",而且send是线程安全的。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-12-23 06:20:00每日论坛发贴之星
日期:2015-12-23 06:20:00
12 [报告]
发表于 2015-09-12 09:49 |只看该作者
回复 11# myworkstation

  感谢你这么细致的解释,你的解释也与我的实验结果是一致的
我现在还是一个小菜鸟,对手册的阅读也没能达到细致,以后闲下来应该仔细读读man手册。

我还想请教一下,查看linux源码是否需要把源码下载下来?

   

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
13 [报告]
发表于 2015-09-12 12:19 |只看该作者
回复 10# folklore


    以前没仔细研究,还以为write和send像read recv一样,对socket操作一次返回的值可能小于传入的参数,我自己写的send都是循环的,看来没必要

    看完11楼的好像明了一些,是不是普通文件有offset,而socket没有,所以对于普通文件不见得是原子而对socket是原子,而且,阻塞和非阻塞的情况
    一致?

   

论坛徽章:
0
14 [报告]
发表于 2015-09-12 12:26 |只看该作者
[ 本帖最后由 giantchen 于 2015-09-11 21:37 编辑 ]

POSIX 标准明确规定 write() 是线程安全的。

pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09

2.9.1 Thread-Safety

All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe.

后面列的函数名单里没有 write,所以按标准它是线程安全的。

不过,据Linux手册,write 在 3.14 之后的内核才符合标准。

man7.org/linux/man-pages/man2/write.2.html

BUGS

       According to POSIX.1-2008/SUSv4 Section XSI 2.9.7 ("Thread
       Interactions with Regular File Operations"):

           All of the following functions shall be atomic with respect to
           each other in the effects specified in POSIX.1-2008 when they
           operate on regular files or symbolic links: ...

       Among the APIs subsequently listed are write() and writev(2).  And
       among the effects that should be atomic across threads (and
       processes) are updates of the file offset.  However, on Linux before
       version 3.14, this was not the case: if two processes that share an
       open file description (see open(2)) perform a write() (or writev(2))
       at the same time, then the I/O operations were not atomic with
       respect updating the file offset, with the result that the blocks of
       data output by the two processes might (incorrectly) overlap.  This
       problem was fixed in Linux 3.14.

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
15 [报告]
发表于 2015-09-12 14:10 |只看该作者
回复 13# cokeboL


    seek +wirte是不是原子的(显然分开的两个调用无论如何也不可能是原子的),和·write是不是原子的没有关系。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
16 [报告]
发表于 2015-09-12 19:40 |只看该作者
回复 15# folklore


    两次系统调用肯定离原子八竿子远了。我是想问,单次write,写入成功的数量一定等于传入的参数吗?

论坛徽章:
154
2022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:5720周年集字徽章-年
日期:2022-10-26 16:44:2015-16赛季CBA联赛之深圳
日期:2022-11-02 14:02:4515-16赛季CBA联赛之八一
日期:2022-11-28 12:07:4820周年集字徽章-20	
日期:2023-07-19 08:49:4515-16赛季CBA联赛之八一
日期:2023-11-04 19:23:5115-16赛季CBA联赛之广夏
日期:2023-12-13 18:09:34
17 [报告]
发表于 2015-09-12 22:43 来自手机 |只看该作者
不安全,自己封装安全接口,供上层业务简单轻松调用

论坛徽章:
0
18 [报告]
发表于 2015-09-14 09:22 |只看该作者
路过看看~~

论坛徽章:
0
19 [报告]
发表于 2015-09-14 09:22 |只看该作者
路过看看~~

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
20 [报告]
发表于 2015-09-15 14:01 |只看该作者
回复 16# cokeboL


    write 一个Socket也是原子的, 但不能保证能写入你想要的长度(其实这个理论上对于文件系统也是一样的, 只不过基本不会发生)。

所谓原子, 是说这个调用本身是原子的,比如两个进程往同一个文件同一个offset写, 原子性保证这个文件中的内容或者是进程1重写进程2,
或者进程2改写进程1, 而不是最后的结果是进程1和进程2的混杂。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP